From: Dmitry Shachnev Date: Fri, 16 Dec 2016 18:07:41 +0000 (+0000) Subject: Import qtlocation-opensource-src_5.7.1.orig.tar.xz X-Git-Tag: archive/raspbian/5.15.8+dfsg-3+rpi1~1^2^2^2^2^2^2^2^2^2^2^2~3 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=530495029ab0759d7ac750b401e6cd1fb96bf94d;p=qtlocation-opensource-src.git Import qtlocation-opensource-src_5.7.1.orig.tar.xz [dgit import orig qtlocation-opensource-src_5.7.1.orig.tar.xz] --- 530495029ab0759d7ac750b401e6cd1fb96bf94d diff --git a/.qmake.conf b/.qmake.conf new file mode 100644 index 0000000..a2a0d41 --- /dev/null +++ b/.qmake.conf @@ -0,0 +1,3 @@ +load(qt_build_config) + +MODULE_VERSION = 5.7.1 diff --git a/.tag b/.tag new file mode 100644 index 0000000..8294ae9 --- /dev/null +++ b/.tag @@ -0,0 +1 @@ +de5be121d84b062f1b72c91dddc877e5e88babc0 diff --git a/LGPL_EXCEPTION.txt b/LGPL_EXCEPTION.txt new file mode 100644 index 0000000..5cdacb9 --- /dev/null +++ b/LGPL_EXCEPTION.txt @@ -0,0 +1,22 @@ +The Qt Company Qt LGPL Exception version 1.1 + +As an additional permission to the GNU Lesser General Public License version +2.1, the object code form of a "work that uses the Library" may incorporate +material from a header file that is part of the Library. You may distribute +such object code under terms of your choice, provided that: + (i) the header files of the Library have not been modified; and + (ii) the incorporated material is limited to numerical parameters, data + structure layouts, accessors, macros, inline functions and + templates; and + (iii) you comply with the terms of Section 6 of the GNU Lesser General + Public License version 2.1. + +Moreover, you may apply this exception to a modified version of the Library, +provided that such modification does not involve copying material from the +Library into the modified Library's header files unless such material is +limited to (i) numerical parameters; (ii) data structure layouts; +(iii) accessors; and (iv) small macros, templates and inline functions of +five lines or less in length. + +Furthermore, you are not required to apply this additional permission to a +modified version of the Library. diff --git a/LICENSE.FDL b/LICENSE.FDL new file mode 100644 index 0000000..938bb8d --- /dev/null +++ b/LICENSE.FDL @@ -0,0 +1,450 @@ + GNU Free Documentation License + Version 1.3, 3 November 2008 + + + Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The "publisher" means any person or entity that distributes copies of +the Document to the public. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no +other conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to +give them a chance to provide you with an updated version of the +Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other +documents released under this License, and replace the individual +copies of this License in the various documents with a single copy +that is included in the collection, provided that you follow the rules +of this License for verbatim copying of each of the documents in all +other respects. + +You may extract a single document from such a collection, and +distribute it individually under this License, provided you insert a +copy of this License into the extracted document, and follow this +License in all other respects regarding verbatim copying of that +document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +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, receipt of a copy of some or all of the same material does +not give you any rights to use it. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions of the +GNU Free Documentation 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. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +11. RELICENSING + +"Massive Multiauthor Collaboration Site" (or "MMC Site") means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +"Massive Multiauthor Collaboration" (or "MMC") contained in the site +means any set of copyrightable works thus published on the MMC site. + +"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +"Incorporate" means to publish or republish a Document, in whole or in +part, as part of another Document. + +An MMC is "eligible for relicensing" if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole or +in part into the MMC, (1) had no cover texts or invariant sections, and +(2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/LICENSE.GPL2 b/LICENSE.GPL2 new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE.GPL2 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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. diff --git a/LICENSE.GPL3 b/LICENSE.GPL3 new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE.GPL3 @@ -0,0 +1,674 @@ + 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/LICENSE.GPL3-EXCEPT b/LICENSE.GPL3-EXCEPT new file mode 100644 index 0000000..b1cb1be --- /dev/null +++ b/LICENSE.GPL3-EXCEPT @@ -0,0 +1,704 @@ +This is the GNU General Public License version 3, annotated with The +Qt Company GPL Exception 1.0: + +------------------------------------------------------------------------- + +The Qt Company GPL Exception 1.0 + +Exception 1: + +As a special exception you may create a larger work which contains the +output of this application and distribute that work under terms of your +choice, so long as the work is not otherwise derived from or based on +this application and so long as the work does not in itself generate +output that contains the output from this application in its original +or modified form. + +Exception 2: + +As a special exception, you have permission to combine this application +with Plugins licensed under the terms of your choice, to produce an +executable, and to copy and distribute the resulting executable under +the terms of your choice. However, the executable must be accompanied +by a prominent notice offering all users of the executable the entire +source code to this application, excluding the source code of the +independent modules, but including any changes you have made to this +application, under the terms of this license. + + +------------------------------------------------------------------------- + + 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/LICENSE.GPLv2 b/LICENSE.GPLv2 new file mode 100644 index 0000000..a424477 --- /dev/null +++ b/LICENSE.GPLv2 @@ -0,0 +1,292 @@ + GNU GENERAL PUBLIC LICENSE + + The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + You may use, distribute and copy the Qt Toolkit under the terms of + GNU General Public License version 2, which is displayed below. + +------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +Preamble + + The licenses for most software are designed to take away your freedom +to share and change it. By contrast, the GNU General Public License is +intended to guarantee your freedom to share and change free software +--to make sure the software is free for all its users. This General +Public License applies to most of the Free Software Foundation's +software and to any other program whose authors commit to using it. +(Some other Free Software Foundation software is covered by the GNU +Lesser General Public License instead.) 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 this +service 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 make restrictions that forbid anyone +to deny you these rights or to ask you to surrender the rights. These +restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis + or for a fee, you must give the recipients all the rights that you +have. 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. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software patents. +We wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program +proprietary. To prevent this, we have made it clear that any patent +must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a +notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of running +the Program is not restricted, and the output from the Program is +covered only if its contents constitute a work based on the Program +(independent of having been made by running the Program). Whether that +is true depends on what the Program does. + +1. You may copy and distribute 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 +and disclaimer of warranty; keep intact all the notices that refer to +this License and to the absence of any warranty; and give any other +recipients of the Program a copy of this License along with the +Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of +it, thus forming a work based on the Program, and copy and distribute +such modifications or work under the terms of Section 1 above, provided +that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the + Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of a +storage or distribution medium does not bring the other work under the +scope of this License. + +3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software + interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your cost + of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to control +compilation and installation of the executable. However, as a special +exception, the source code distributed need not include anything that +is normally distributed (in either source or binary form) with the +major components (compiler, kernel, and so on) of the operating system +on which the executable runs, unless that component itself accompanies +the executable. + +If distribution of executable or object code is made by offering access +to copy from a designated place, then offering equivalent access to +copy the source code from the same place counts as distribution of the +source code, even though third parties are not compelled to copy the +source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt otherwise +to copy, modify, sublicense or distribute the Program is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this License +will not have their licenses terminated so long as such parties remain +in full compliance. + +5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further restrictions +on the recipients' exercise of the rights granted herein. You are not +responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent license +would not permit royalty-free redistribution of the Program by all +those who receive copies directly or indirectly through you, then the +only way you could satisfy both it and this License would be to refrain +entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License may +add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among countries +not thus excluded. In such case, this License incorporates the limitation +as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Program does not specify a version +number of this License, you may choose any version ever published by +the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the +author to ask for permission. For software which is copyrighted by +the Free Software Foundation, write to the Free Software Foundation; +we sometimes make exceptions for this. Our decision will be guided by +the two goals of preserving the free status of all derivatives of our +free software and of promoting the sharing and reuse of software +generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY +MODIFY AND/OR REDISTRIBUTE 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. + +END OF TERMS AND CONDITIONS diff --git a/LICENSE.GPLv3 b/LICENSE.GPLv3 new file mode 100644 index 0000000..71c4ad4 --- /dev/null +++ b/LICENSE.GPLv3 @@ -0,0 +1,686 @@ + GNU GENERAL PUBLIC LICENSE + + The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + You may use, distribute and copy the Qt Toolkit under the terms of + GNU Lesser General Public License version 3. That license references + the General Public License version 3, that is displayed below. Other + portions of the Qt Toolkit may be licensed directly under this license. + +------------------------------------------------------------------------- + + 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/LICENSE.LGPL3 b/LICENSE.LGPL3 new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/LICENSE.LGPL3 @@ -0,0 +1,165 @@ + GNU LESSER 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. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser 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 +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/LICENSE.LGPLv21 b/LICENSE.LGPLv21 new file mode 100644 index 0000000..dfcab5e --- /dev/null +++ b/LICENSE.LGPLv21 @@ -0,0 +1,514 @@ + GNU LESSER GENERAL PUBLIC LICENSE + + The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + You may use, distribute and copy the Qt Toolkit under the terms of + GNU Lesser General Public License version 2.1, which is displayed below. + +------------------------------------------------------------------------- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey 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 library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/LICENSE.LGPLv3 b/LICENSE.LGPLv3 new file mode 100644 index 0000000..6bf924c --- /dev/null +++ b/LICENSE.LGPLv3 @@ -0,0 +1,175 @@ + GNU LESSER GENERAL PUBLIC LICENSE + + The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + You may use, distribute and copy the Qt Toolkit under the terms of + GNU Lesser General Public License version 3, which is displayed below. + This license makes reference to the version 3 of the GNU General + Public License, which you can find in the LICENSE.GPLv3 file. + +------------------------------------------------------------------------- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright © 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies of this +licensedocument, but changing it is not allowed. + +This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + +0. Additional Definitions. + + As used herein, “this License” refers to version 3 of the GNU Lesser +General Public License, and the “GNU GPL” refers to version 3 of the +GNU General Public License. + + “The Library” refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An “Application” is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A “Combined Work” is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the “Linked +Version”. + + The “Minimal Corresponding Source” for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The “Corresponding Application Code” for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + +1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + +2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort + to ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + +3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this + license document. + +4. Combined Works. + + You may convey a Combined Work under terms of your choice that, taken +together, effectively do not restrict modification of the portions of +the Library contained in the Combined Work and reverse engineering for +debugging such modifications, if you also do each of the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this + license document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of + this License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with + the Library. A suitable mechanism is one that (a) uses at run + time a copy of the Library already present on the user's + computer system, and (b) will operate properly with a modified + version of the Library that is interface-compatible with the + Linked Version. + + e) Provide Installation Information, but only if you would + otherwise be required to provide such information under section 6 + of the GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the Application + with a modified version of the Linked Version. (If you use option + 4d0, the Installation Information must accompany the Minimal + Corresponding Source and Corresponding Application Code. If you + use option 4d1, you must provide the Installation Information in + the manner specified by section 6 of the GNU GPL for conveying + Corresponding Source.) + +5. Combined Libraries. + + You may place library facilities that are a work based on the Library +side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities, conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of + it is a work based on the Library, and explaining where to find + the accompanying uncombined form of the same work. + +6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser 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 Library +as you received it specifies that a certain numbered version of the +GNU Lesser General Public License “or any later version” applies to +it, you have the option of following the terms and conditions either +of that published version or of any later version published by the +Free Software Foundation. If the Library as you received it does not +specify a version number of the GNU Lesser General Public License, +you may choose any version of the GNU Lesser General Public License +ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the Library. + diff --git a/config.tests/gypsy/gypsy.pro b/config.tests/gypsy/gypsy.pro new file mode 100644 index 0000000..f9dcffa --- /dev/null +++ b/config.tests/gypsy/gypsy.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +unix { + CONFIG += link_pkgconfig + PKGCONFIG += gypsy gconf-2.0 +} +SOURCES += main.cpp diff --git a/config.tests/gypsy/main.cpp b/config.tests/gypsy/main.cpp new file mode 100644 index 0000000..2b8d3ca --- /dev/null +++ b/config.tests/gypsy/main.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +int main() +{ + GypsyControl *control = gypsy_control_get_default(); + GypsyDevice *device = gypsy_device_new("test"); + GypsySatellite *satellite = gypsy_satellite_new("test"); + + GConfClient *client = gconf_client_get_default(); + g_object_unref(client); + + return 0; +} diff --git a/dist/changes-5.2.1 b/dist/changes-5.2.1 new file mode 100644 index 0000000..37a1f55 --- /dev/null +++ b/dist/changes-5.2.1 @@ -0,0 +1,53 @@ +Qt 5.2.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.2.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.2 + +The Qt version 5.2 series is binary compatible with the 5.1.x series. +Applications compiled for 5.1 will continue to run with 5.2. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* General * +**************************************************************************** + +General Improvements +-------------------- + + - [QTBUG-34910] Fixed too long weather status string in weatherinfo + example (UI change). + - [QTBUG-36187] Byte order marker removed from positionpoll plugin + which caused compile errors on some older compilers. + - Fixed make install rules for all examples. + - declarative_core unit test was fixed and re-enabled. + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - [QTBUG-33220] Removed QtQml dependency from QtPositioning. + +**************************************************************************** +* Plugin Specific Changes * +**************************************************************************** + +GeoClue +------- + + - Delay satellite provider until requested. + - Sets the default preferred positioning method to AllPositioningMethods. + - Fix for incorrect accuracy values reported by the plug-in. + diff --git a/dist/changes-5.3.0 b/dist/changes-5.3.0 new file mode 100644 index 0000000..1bf445a --- /dev/null +++ b/dist/changes-5.3.0 @@ -0,0 +1,74 @@ +Qt 5.3 introduces many new features and improvements as well as bugfixes +over the 5.2.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.3 + +The Qt version 5.3 series is binary compatible with the 5.2.x series. +Applications compiled for 5.2 will continue to run with 5.3. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* General * +**************************************************************************** + +General Improvements +-------------------- + + - New SatelliteInfo example added. The example displays the signal + strength of surrounding satellites. The example employs a demo mode on + those platforms which don't provide satellite information + + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - Position (QML): + * Added direction and vertical speed properties. + + - QGeoPositionInfoSource: + * iOS position backend added. + * [QTBUG-34102] Android backend added. Android devices can retrieve + their current position. Network- and Satellite-based providers are + supported. + + - QGeoSatelliteInfoSource: + * [QTBUG-34102] Android backend added. Android devices can retrieve + information about the currently accessible GPS and GLONASS satellites. + + - QGeoRectangle: + * Added QGeoRectangle(QList) constructor added. + * Improved class documentation. + + - QGeoShape: + * Added extendShape(QGeoCoordinate) function. + + - QNmeaPositionInfoSource: + * Added support for reporting position accuracy. + + +**************************************************************************** +* Plugin Specific Changes * +**************************************************************************** + +GeoClue +------- + - [QTBUG-36298] Reports direction of travel and + vertical speed attributes, if supported by the active Geoclue + provider. + - Fixed the emission of the updateTimeout() signal when + position updates do not arrive in a timely manner. + - Position info source provider no longer internally filters + position updates to the requested update interval. + diff --git a/dist/changes-5.3.1 b/dist/changes-5.3.1 new file mode 100644 index 0000000..8913770 --- /dev/null +++ b/dist/changes-5.3.1 @@ -0,0 +1,57 @@ +Qt 5.3.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.3.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.3 + +The Qt version 5.3 series is binary compatible with the 5.2.x series. +Applications compiled for 5.2 will continue to run with 5.3. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* General * +**************************************************************************** + +General Improvements +-------------------- + + - Added PLUGIN_CLASS_NAME variable to all plug-in based projects. This + enables the automatic static linking and deployment of this plug-ins. + + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - QGeoPositionInfoSource: + * WinRT backend added + + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-39082] Fixed crash on Galaxy S4 when running satellite and position + updates at the same time. + +iOS +--- + + - [QTBUG-38770] Added "classname" entry to all qmldir files enabling QML + plug-ins when doing static builds on iOS. + diff --git a/dist/changes-5.3.2 b/dist/changes-5.3.2 new file mode 100644 index 0000000..b1981f6 --- /dev/null +++ b/dist/changes-5.3.2 @@ -0,0 +1,50 @@ +Qt 5.3.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.3.0 and Qt 5.3.1. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.3 + +The Qt version 5.3 series is binary compatible with the 5.2.x series. +Applications compiled for 5.2 will continue to run with 5.3. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - [QTBUG-39843] [iOS] Fixed link error of positioncl and positionpoll + plug-in. + + - [QTBUG-40198] Fixed symbol clash between sensor and position plug-in. + This happened when using static builds of Qt (e.g. on iOS) and the + application used QtSensors and QtPositioning at the same time. + + - Improved weatherinfo example to not hang on the "Loading weather data" + screen if the current QGeoPositionInfoSource instance returned an error + during its startup. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +[iOS] + + - [QTBUG-38300] Fixed wrong value of QGeoPositionInfo attributes if those + attributes were not provided by the platforms CoreLocation framework. + +[Linux] + + - [QTBUG-40425] Fixed missing error report when failing to connect to GeoClue. + diff --git a/dist/changes-5.4.0 b/dist/changes-5.4.0 new file mode 100644 index 0000000..3a14766 --- /dev/null +++ b/dist/changes-5.4.0 @@ -0,0 +1,54 @@ +Qt 5.4 introduces many new features and improvements as well as bugfixes +over the 5.3.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.4 + +The Qt version 5.4 series is binary compatible with the 5.3.x series. +Applications compiled for 5.3 will continue to run with 5.4. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - Position: + * [QTBUG-39547] Added magneticVariation and magneticVariationValid + property to the QML Position type. + + - General: + * Weatherinfo end Flickr example improved. + + - QGeoCircle: + * [QTBUG-41447] Fixed contains() when rounding errors occur + + - QGeoCoordinate: + * [QTBUG-41739] Fixed toString() output in cases when rounding + of longitude/latitude is necessary. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-41873] Fixed wrong initialization of QGeoPositionInfoSource::error() + after class instantiation. + +iOS +--- + + - [QTBUG-41827] Fixed position retrieval on iOS 8. This was required due + to the new authorization scheme in CLLocationManager. + diff --git a/dist/changes-5.4.1 b/dist/changes-5.4.1 new file mode 100644 index 0000000..4876ab3 --- /dev/null +++ b/dist/changes-5.4.1 @@ -0,0 +1,29 @@ +Qt 5.4.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.4.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://doc.qt.io/qt-5.4 + +The Qt version 5.4 series is binary compatible with the 5.3.x series. +Applications compiled for 5.3 will continue to run with 5.4. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - PositionSource: + * Fixed a case where an NMEA source file, which is integrated + using qrc, was not loaded. diff --git a/dist/changes-5.4.2 b/dist/changes-5.4.2 new file mode 100644 index 0000000..4f256ef --- /dev/null +++ b/dist/changes-5.4.2 @@ -0,0 +1,28 @@ +Qt 5.4.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.4.0 and Qt 5.4.1. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://doc.qt.io/qt-5.4 + +The Qt version 5.4 series is binary compatible with the 5.3.x series. +Applications compiled for 5.3 will continue to run with 5.4. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - [QTBUG-44572] Fixed issue where the default timeout for position update + requests was not set on WinRT. diff --git a/dist/changes-5.5.0 b/dist/changes-5.5.0 new file mode 100644 index 0000000..737ce13 --- /dev/null +++ b/dist/changes-5.5.0 @@ -0,0 +1,40 @@ +Qt 5.5 introduces many new features and improvements as well as bugfixes +over the 5.4.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + + http://doc.qt.io/qt-5/index.html + +The Qt version 5.5 series is binary compatible with the 5.4.x series. +Applications compiled for 5.4 will continue to run with 5.5. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - Added QGeoShape::center() function + - Converted QGeoShape, QGeoCircle, QGeoRectangle & QGeoCoordinate to Q_GADGET. + It simplifies the integration of the above classes into QML as the extensive + QML value type wrapper conversion is implicitly done by Qt QML. The existing + custom wrappers were removed. + - Fixed Debug stream operators for QGeoAreaMonitorInfo, QGeoCoordinate, + QGeoPositionInfo, QGeoSatelliteInfo & QGeoShape following a QDebug related + change in Qt Base. + - [QTBUG-44663] Added updateTimeout() signal to QML PositionSource type + - [QTBUG-44983] Fixed broken build of qtlocation repo when using qmake -r + on OS X + +QtLocation +---------- + + - First Technology Preview release of this module diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1 new file mode 100644 index 0000000..8b2ce35 --- /dev/null +++ b/dist/changes-5.5.1 @@ -0,0 +1,54 @@ +Qt 5.5.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.5.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://doc.qt.io/qt-5.5/ + +The Qt version 5.5 series is binary compatible with the 5.4.x series. +Applications compiled for 5.4 will continue to run with 5.5. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtLocation +----------- + + - Fixed change signal emission for Map.activeMapType property. + - Improved places-list and places-map examples. + - [QTBUG-47188] Fixed incorrect naming of OSM plugin's parameter. + The documentation mandates the osm prefix which was not used in + the case of the geocoding.host, useragent and routing.host parameters. + The required osm.places.host parameter was not handled at all. + - [QTBUG-47322] Added support for zoom level 19 to OSM plugin. + - Fixed an issue where the incorrect prefetch algorithm was used for map + tile fetching. + +QtPositioning +------------- + + - Improved minor documentation issues. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Windows +------- + + - Added missing QtQuick.Controls import to mapviewer example. + +Linux/gcc +--------- + + - [QTBUG-47427] Fixed compile issue in geoclue plugin when using gcc 4.5. diff --git a/dist/changes-5.6.0 b/dist/changes-5.6.0 new file mode 100644 index 0000000..1402343 --- /dev/null +++ b/dist/changes-5.6.0 @@ -0,0 +1,69 @@ +Qt 5.6 introduces many new features and improvements as well as bugfixes +over the 5.5.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + + http://doc.qt.io/qt-5/index.html + +The Qt version 5.6 series is binary compatible with the 5.5.x series. +Applications compiled for 5.5 will continue to run with 5.6. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - Removed Blackberry 10 support. + - [QTBUG-40702] Removed dependency towards libgeoclue. The plugin uses the + GeoClue DBus interface. + - Enabled Position plugin for OS X. Previously only the plugin was only working + for iOS. + - [QTBUG-48082] Added QtSerialPort based NMEA position plugin for Windows. + - Improved and fixed the WinRT position backend. Various changes on the WinRT + platform caused the necessity for such and update. + - Fixed endless requests towards Android's LocationManager when stopUpdates() was not + called in pair with startUpdates(). + +QtLocation +---------- + + - First stable release of the Qt Location API. The QML API changed significantly + compared to the Qt 5.5 release. The changes are documented in the official + module documentation under "API changes". + - Improved the Flick and Pinch implementation for QML Map. + - [QTBUG-44809] Fixed tile version handling + - Fixed crash during Map.setVisibleRegion while no plugin has been set. + - Improved error reporting in map, geocoding and routing model APIs. + - QTBUG[36919] Added means to prevent stealing of mouse/touch grabs on map. + - Improved coordinate related animation handling. Previously an animation along + the longitude always used a shortest path direction. Now it is possible to set + the direction for the animation. + - [QTBUG-46147] Fixed crash in QML Map element. + - [QTBUG-44311] Fixed bouncing Map flick on zoom level 2. + - [QTBUG-47020] & [QTBUG-47019] Improved Mouse and keyboard integration of QML Map + - [QTBUG-46388] Fixed Pinch when no MouseArea overlaps QML Map element. + - Fixed various unit test. + - Fixed a variety of minor documentation issues. + - Fixed dysfunctional tile cache for OSM plugin due to the server delivering JPEG + file when PNG files were expected. + - [QTBUG-41187] Unified the default tile cache location on disk. + - Fixed crash in gesture area while receiving wheel events. + - Fixed route requests with excluded areas for HERE plugin. + - Added support for custom map background color. + - Improved Map rendering performance throughout the QML API. + - [QTBUG-49772] Fixed weatherinfo example due to missing appid handling for + openweatermap.org. + - [QTBUG-47292] Added ability to clear the map cache. + - [QTBUG-50060] Improved performance of QML MapPolyline. + - [QTBUG-50240] Fixed OSM routing to handle changed server status code for a + successful route retrieval. + - [QTBUG-50519] Fixed map in mapviewer example when displaying the minimap. diff --git a/dist/changes-5.6.1 b/dist/changes-5.6.1 new file mode 100644 index 0000000..cd579b6 --- /dev/null +++ b/dist/changes-5.6.1 @@ -0,0 +1,38 @@ +Qt 5.6.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.6.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://doc.qt.io/qt-5.6/ + +The Qt version 5.6 series is binary compatible with the 5.5.x series. +Applications compiled for 5.5 will continue to run with 5.6. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtLocation +---------- + + - Improved the example and class documentation + - Consolidated various qmake project files across the module + - [QTBUG-51541] Fixed compile issue on linux/gcc-4.8 when using C++98 + - Improved compression rate of various screenshots throughout the documentation + +QtPositioning +------------- + + - [QTBUG-38802] Added default capability (location) for WinRT + - [QTBUG-53059] Fixed crash on iOS/OS X due to incorrectly initialized member + variable in the positioning backend + diff --git a/dist/changes-5.6.2 b/dist/changes-5.6.2 new file mode 100644 index 0000000..9f2a6f9 --- /dev/null +++ b/dist/changes-5.6.2 @@ -0,0 +1,55 @@ +Qt 5.6.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.6.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://doc.qt.io/qt-5/index.html + +The Qt version 5.6 series is binary compatible with the 5.5.x series. +Applications compiled for 5.5 will continue to run with 5.6. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtLocation +---------- + + - Fixed autotests containing bugs not showing in the tests + - [QTBUG-31797][QTBUG-53455] Fixed the QtLocation autotest framework by + replacing waitForRendering() with waitForPolished() + - Disabled explicit example installation + - [QTBUG-52514] Fixed QML Map not working with repeaters + - [QTBUG-53128] Fixed QML Map items not updating on window resize + - [QTBUG-52075] Fixed QML Map items losing focus during fast dragging + - [QTBUG-52301] Prevented flickering upon MapItemView's model reset + - [QTBUG-54141] Fixed QML Map setVisibleRegion failing in some cases + - Fixed a potential memory leak in QGeoTiledMappingManagerEngine + - [QTBUG-19929] Prevented generating MapCircles with invalid radius + - [QTBUG-54599] Added support for fetching OSM provider information from + a remote repository + - [QTBUG-54337] Fixed bounding calculation for QGeoCircle + - Added a minimal QML Map usage example + - Added support for dynamically remove unavailable providers from the OSM + plugin + - [QTBUG-55081] Fixed accessing MapPolyline before it is added to a Map + - [QTBUG-54964] Fixed invisible copyright notice on Android using Holo theme + - Improved macOS documentation + - Fixed the geocoding in the MapViewer example + - [QTBUG-55371] Fixed OSM plugin geocoding feature + +QtPositioning +------------- + + - [QTBUG-54026] Reduced Android minimum update interval + - Improved Android 5.0+ compatibility + diff --git a/dist/changes-5.7.0 b/dist/changes-5.7.0 new file mode 100644 index 0000000..d1fdb43 --- /dev/null +++ b/dist/changes-5.7.0 @@ -0,0 +1,53 @@ +Qt 5.7 introduces many new features and improvements as well as bugfixes +over the 5.6.x series. Also, there is a change in the licensing terms. +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://doc.qt.io/qt-5/index.html + +The Qt version 5.7 series is binary compatible with the 5.6.x series. +Applications compiled for 5.6 will continue to run with 5.7. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Important License Changes * +**************************************************************************** + + This module is no longer available under LGPLv2.1. The libraries are + now available under the following licenses: + * Commercial License + * GNU General Public License v2.0 (LICENSE.GPL2) and later + * GNU Lesser General Public License v3.0 (LICENSE.LGPL3) + + The tools are now available under the following licenses: + * Commercial License + * GNU General Public License 3.0 (LICENSE.GPL3) with exceptions + described in The Qt Company GPL Exception 1.0 (LICENSE.GPL3-EXCEPT) + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------------- + + - Added support for tvOs to iOS/OS X positioning engine + - Added qHash() function for QGeoCoordinate + - Fixed negative QGeoCoordinate.azimuthTo results + - Added experimental support for GeoPosition API on Windows desktop + running Windows 8 or later + +QtLocation +---------- + + - [QTBUG-47025] Added option to hide map data copyright information + - Adjusted minimum map zoom level to prevent gray bounds. It prevents the map + from being smaller than the canvas size. + - Fixed several internal performance issues diff --git a/dist/changes-5.7.1 b/dist/changes-5.7.1 new file mode 100644 index 0000000..2d111d5 --- /dev/null +++ b/dist/changes-5.7.1 @@ -0,0 +1,45 @@ +Qt 5.7.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.7.0. + +Qt 5.7.1 contains a merge from Qt 5.6.2 and all changes in Qt 5.6.2 are +also in Qt 5.7.1. For more see changes-5.6.2. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.7 series is binary compatible with the 5.6.x series. +Applications compiled for 5.6 will continue to run with 5.7. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtLocation +---------- + +- [QTBUG-55535] Fixed map polygon not working correctly when zooming. +- [QTBUG-55964] Fixed rendering of polylines and polygons at the edge + of the map. +- [QTBUG-52610] Fixed incorrect map polyline drawing. +- [QTBUG-52076] Fixed crashes on tessellation of self-intersecting + GeoPolygons. +- [QTBUG-52030] Fixed that map's center and zoom were not initialized when + used in a layout. +- [QTBUG-52514] Fixed not working MapPolygon inside Repeater. +- [QTBUG-53128] Fixed map objects moving incorrectly on map resize. +- [QTBUG-52075] Fixed losing map item focus while dragging. + +QtPositioning +------------- + +- [QTBUG-54506] Fixed unneeded dependency on Activity for Android Platform. diff --git a/examples/examples.pro b/examples/examples.pro new file mode 100644 index 0000000..da770da --- /dev/null +++ b/examples/examples.pro @@ -0,0 +1,7 @@ +TEMPLATE = subdirs + +qtHaveModule(positioning) { + SUBDIRS += positioning + + qtHaveModule(location): SUBDIRS += location +} diff --git a/examples/location/location.pro b/examples/location/location.pro new file mode 100644 index 0000000..0b4b233 --- /dev/null +++ b/examples/location/location.pro @@ -0,0 +1,10 @@ +TEMPLATE = subdirs + +qtHaveModule(quick) { + SUBDIRS += places \ + places_list \ + places_map \ + mapviewer \ + minimal_map \ + planespotter +} diff --git a/examples/location/mapviewer/doc/images/mapviewer.png b/examples/location/mapviewer/doc/images/mapviewer.png new file mode 100644 index 0000000..4dc13f7 Binary files /dev/null and b/examples/location/mapviewer/doc/images/mapviewer.png differ diff --git a/examples/location/mapviewer/doc/src/mapviewer.qdoc b/examples/location/mapviewer/doc/src/mapviewer.qdoc new file mode 100644 index 0000000..1fe0411 --- /dev/null +++ b/examples/location/mapviewer/doc/src/mapviewer.qdoc @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example mapviewer + \title Map Viewer (QML) + \ingroup qtlocation-examples + + \brief The Map Viewer example shows how to display and interact with a map, + search for an address, and find driving directions. + + \image mapviewer.png + + This is a large example covering many basic uses of maps, positioning, and + navigation services in Qt Location. This page is divided into sections + covering each of these areas of functionality with snippets from the code. + + \include examples-run.qdocinc + + \include example-parameters.qdocinc + + \section1 Overview + + QML types shown in this example: + + \list + \li Displaying a map + \list + \li \l{QtLocation::Map}{Map} + \li \l{QtLocation::MapGestureArea}{MapGestureArea} + \li \l[QML]{coordinate} + \endlist + \li Finding an address + \list + \li \l{QtLocation::GeocodeModel}{GeocodeModel} + \li \l{QtLocation::MapItemView}{MapItemView} + \li \l{QtLocation::MapCircle}{MapCircle} + \endlist + \li Directions and travel routes + \list + \li \l{QtLocation::RouteModel}{RouteModel} + \li \l{QtLocation::MapRoute}{MapRoute} + \endlist + \endlist + + \section1 Displaying a Map + + Drawing a map on-screen is accomplished using the Map type, as shown + below. + + \snippet mapviewer/map/MapComponent.qml top + \snippet mapviewer/map/MapComponent.qml coord + \snippet mapviewer/map/MapComponent.qml end + + In this example, we give the map an initial center \l [QML]{coordinate} + with a set latitude and longitude. We also set the initial zoom level to 50% (halfway between + the maximum and minimum). + + \section1 Finding an Address (Geocoding) + + To locate a certain address or place on the map uses a process called + geocoding. In order to perform a geocode operation, we first need to adjust + our Map object to be able to receive the result. + + Receiving results of geocoding is done through a GeocodeModel: + + \snippet mapviewer/map/MapComponent.qml geocodemodel0 + + To display the contents of the GeocodeModel we use a MapItemView: + + \snippet mapviewer/map/MapComponent.qml geocodeview + + MapItemView uses an object called a "delegate" to act as a template for the + items it creates. This can contain any map object desired, but in this case + we show a MapCircle: + + \snippet mapviewer/map/MapComponent.qml pointdel0 + \snippet mapviewer/map/MapComponent.qml pointdel1 + + With these three objects, we have enough to receive Geocode responses and + display them on our Map. The final piece is to send the actual Geocode + request. + + To send a geocode request, first we create an \l [QML]{Address} object, and fill it + in with the desired parameters. + + \snippet mapviewer/mapviewer.qml geocode0 + + Then we set "geocodeModel.query" to the filled in \l [QML]{Address}, + and call update() on the GeocodeModel. + + \snippet mapviewer/map/MapComponent.qml geocode1 + + \section1 Directions and Travel Routes + + Similar to the GeocodeModel, Qt Location also features the RouteModel type, + which allows information about routes (for example driving directions) between two + or more points, to be received and used with a Map. + + Here again, we instantiate the RouteModel as a property of our Map: + + \snippet mapviewer/map/MapComponent.qml routemodel0 + + To display the contents of a model to the user, we need a view. Once again + we will use a MapItemView, to display the Routes as objects on the Map: + + \snippet mapviewer/map/MapComponent.qml routeview0 + \snippet mapviewer/map/MapComponent.qml routeview1 + + To act as a template for the objects we wish the view to create, we create + a delegate component: + + \snippet mapviewer/map/MapComponent.qml routedelegate0 + \snippet mapviewer/map/MapComponent.qml routedelegate1 + + With the model, view and delegate now complete, the only missing component + is some kind of control over the model to begin the Route request process. + In the simplest case, we can fill out a Route request using two already + available \l [QML]{coordinate}{coordinates}: + + \snippet mapviewer/mapviewer.qml routecoordinate + + In the next snippet, we show how to set up the request object and instruct + the model to update. We also instruct the map to center on the start + coordinate for our routing request. + + \snippet mapviewer/map/MapComponent.qml routerequest0 + \snippet mapviewer/map/MapComponent.qml routerequest1 + \snippet mapviewer/map/MapComponent.qml routerequest2 + + This is all that is required to display a Route on the Map. However, it is + also useful to be able to retrieve the written directions and explanation + of the travel route. In the example, these are displayed in a \l {ListView} element. + To create this content, we use a standard \l {Models and Views in Qt Quick#ListModel}{ListModel} and + \l {ListView} pair. The data in the \l {Models and Views in Qt Quick#ListModel}{ListModel} is + built from the routeModel's output: + + \snippet mapviewer/forms/RouteList.qml routeinfomodel0 + \snippet mapviewer/forms/RouteList.qml routeinfomodel1 + \snippet mapviewer/forms/RouteList.qml routeinfomodel3 + + Inside the RouteModel, as you can see above, we add an + \l{QtLocation::RouteModel::status}{onStatusChanged} handler, which + calls the \c{showRouteList()} which updates the \c{routeInfoModel}: + + \snippet mapviewer/forms/RouteList.qml routeinfomodel2 +*/ diff --git a/examples/location/mapviewer/forms/Geocode.qml b/examples/location/mapviewer/forms/Geocode.qml new file mode 100644 index 0000000..9e27325 --- /dev/null +++ b/examples/location/mapviewer/forms/Geocode.qml @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtPositioning 5.5 + +GeocodeForm { + + property variant address + signal showPlace(variant address) + signal closeForm() + + goButton.onClicked: { + // fill out the Address element + address.street = street.text + address.city = city.text + address.state = state.text + address.country = country.text + address.postalCode = postalCode.text + showPlace(address) + } + + clearButton.onClicked: { + street.text = "" + city.text = "" + state.text = "" + country.text = "" + postalCode.text = "" + } + + cancelButton.onClicked: { + closeForm() + } + + Component.onCompleted: { + street.text = address.street + city.text = address.city + state.text = address.state + country.text = address.country + postalCode.text = address.postalCode + } +} + + diff --git a/examples/location/mapviewer/forms/GeocodeForm.ui.qml b/examples/location/mapviewer/forms/GeocodeForm.ui.qml new file mode 100644 index 0000000..3ed715a --- /dev/null +++ b/examples/location/mapviewer/forms/GeocodeForm.ui.qml @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + property alias goButton: goButton + property alias clearButton: clearButton + property alias postalCode: postalCode + property alias street: street + property alias city: city + property alias state: state + property alias country: country + property alias cancelButton: cancelButton + Rectangle { + id: tabRectangle + y: 20 + height: tabTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: qsTr("Geocode") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + id: item2 + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + + GridLayout { + id: gridLayout3 + anchors.rightMargin: 0 + anchors.bottomMargin: 0 + anchors.leftMargin: 0 + anchors.topMargin: 0 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + id: label2 + text: qsTr("Street") + } + + TextField { + id: street + Layout.fillWidth: true + } + + Label { + id: label3 + text: qsTr("City") + } + + TextField { + id: city + Layout.fillWidth: true + } + + Label { + id: label4 + text: qsTr("State") + } + + TextField { + id: state + Layout.fillWidth: true + } + + Label { + id: label5 + text: qsTr("Country") + } + + TextField { + id: country + Layout.fillWidth: true + } + + Label { + id: label6 + text: qsTr("Postal Code") + } + + TextField { + id: postalCode + Layout.fillWidth: true + } + + RowLayout { + id: rowLayout1 + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignRight + + Button { + id: goButton + text: qsTr("Proceed") + } + + Button { + id: clearButton + text: qsTr("Clear") + } + + Button { + id: cancelButton + text: qsTr("Cancel") + } + } + + Item { + Layout.fillHeight: true + Layout.columnSpan: 2 + } + } + } +} diff --git a/examples/location/mapviewer/forms/Locale.qml b/examples/location/mapviewer/forms/Locale.qml new file mode 100644 index 0000000..6e76c98 --- /dev/null +++ b/examples/location/mapviewer/forms/Locale.qml @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtPositioning 5.5 + +LocaleForm { + property string locale + signal selectLanguage(string language) + signal closeForm() + + goButton.onClicked: { + + if (!languageGroup.current) return + + if (otherRadioButton.checked) { + selectLanguage(language.text) + } else { + selectLanguage(languageGroup.current.text) + } + } + + clearButton.onClicked: { + language.text = "" + } + + cancelButton.onClicked: { + closeForm() + } + + Component.onCompleted: { + switch (locale) { + case "en": + enRadioButton.checked = true; + break + case "fr": + frRadioButton.checked = true; + break + default: + otherRadioButton.checked = true; + language.text = locale + break + } + } +} diff --git a/examples/location/mapviewer/forms/LocaleForm.ui.qml b/examples/location/mapviewer/forms/LocaleForm.ui.qml new file mode 100644 index 0000000..91a0847 --- /dev/null +++ b/examples/location/mapviewer/forms/LocaleForm.ui.qml @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + property alias clearButton: clearButton + property alias goButton: goButton + property alias cancelButton: cancelButton + property alias tabTitle: tabTitle + property alias languageGroup: languageGroup + property alias enRadioButton: enRadioButton + property alias frRadioButton: frRadioButton + property alias otherRadioButton: otherRadioButton + property alias language: language + + Rectangle { + id: tabRectangle + y: 20 + height: tabTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: "Locale" + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + id: item2 + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + GridLayout { + id: gridLayout3 + anchors.rightMargin: 0 + anchors.bottomMargin: 0 + anchors.leftMargin: 0 + anchors.topMargin: 0 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + ExclusiveGroup { id: languageGroup } + RadioButton { + id: enRadioButton + text: qsTr("en") + exclusiveGroup: languageGroup + Layout.columnSpan: 2 + } + + RadioButton { + id: frRadioButton + text: qsTr("fr") + exclusiveGroup: languageGroup + Layout.columnSpan: 2 + } + + RadioButton { + id: otherRadioButton + text: qsTr("Other") + exclusiveGroup: languageGroup + } + + TextField { + id: language + Layout.fillWidth: true + placeholderText: qsTr("") + } + + RowLayout { + id: rowLayout1 + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignRight + + Button { + id: goButton + text: qsTr("Proceed") + } + + Button { + id: clearButton + text: qsTr("Clear") + } + + Button { + id: cancelButton + text: qsTr("Cancel") + } + } + + Item { + Layout.fillHeight: true + Layout.columnSpan: 2 + } + + + } + } +} diff --git a/examples/location/mapviewer/forms/Message.qml b/examples/location/mapviewer/forms/Message.qml new file mode 100644 index 0000000..5d12c1f --- /dev/null +++ b/examples/location/mapviewer/forms/Message.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 + +MessageForm { + property string title + property string message + property variant backPage + + signal closeForm(variant backPage) + + button.onClicked: { + closeForm(backPage) + } + + Component.onCompleted: { + messageText.text = message + messageTitle.text = title + } +} diff --git a/examples/location/mapviewer/forms/MessageForm.ui.qml b/examples/location/mapviewer/forms/MessageForm.ui.qml new file mode 100644 index 0000000..a300841 --- /dev/null +++ b/examples/location/mapviewer/forms/MessageForm.ui.qml @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + id: root + property alias messageText: messageText + property alias messageTitle: messageTitle + property alias button: button + + Rectangle { + id: tabRectangle + y: 20 + height: messageTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: messageTitle + color: "#ffffff" + text: qsTr("type") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + ColumnLayout { + id: columnLayout1 + spacing: 20 + anchors.fill: parent + + Label { + id: messageText + text: qsTr("message") + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + textFormat: Text.RichText + } + + Button { + id: button + text: qsTr("OK") + Layout.alignment: Qt.AlignHCenter + } + + Item { + Layout.fillHeight: true + } + } + } +} + diff --git a/examples/location/mapviewer/forms/ReverseGeocode.qml b/examples/location/mapviewer/forms/ReverseGeocode.qml new file mode 100644 index 0000000..9e3cd65 --- /dev/null +++ b/examples/location/mapviewer/forms/ReverseGeocode.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtPositioning 5.5 + +//Reverse Geocode Dialog +ReverseGeocodeForm { + property string title; + property variant coordinate + signal showPlace(variant coordinate) + signal closeForm() + + goButton.onClicked: { + var coordinate = QtPositioning.coordinate(parseFloat(latitude.text), + parseFloat(longitude.text)); + if (coordinate.isValid) { + showPlace(coordinate) + } + } + + clearButton.onClicked: { + latitude.text = "" + longitude.text = "" + } + + cancelButton.onClicked: { + closeForm() + } + + Component.onCompleted: { + latitude.text = "" + coordinate.latitude + longitude.text = "" + coordinate.longitude + if (title.length != 0) { + tabTitle.text = title; + } + } +} diff --git a/examples/location/mapviewer/forms/ReverseGeocodeForm.ui.qml b/examples/location/mapviewer/forms/ReverseGeocodeForm.ui.qml new file mode 100644 index 0000000..29eaec9 --- /dev/null +++ b/examples/location/mapviewer/forms/ReverseGeocodeForm.ui.qml @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + property alias clearButton: clearButton + property alias goButton: goButton + property alias longitude: longitude + property alias latitude: latitude + property alias cancelButton: cancelButton + property alias tabTitle: tabTitle + Rectangle { + id: tabRectangle + y: 20 + height: tabTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: qsTr("Reverse Geocode") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + id: item2 + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + GridLayout { + id: gridLayout3 + anchors.rightMargin: 0 + anchors.bottomMargin: 0 + anchors.leftMargin: 0 + anchors.topMargin: 0 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + id: label2 + text: qsTr("Latitude") + } + + TextField { + id: latitude + Layout.fillWidth: true + } + + Label { + id: label3 + text: qsTr("Longitude") + } + + TextField { + id: longitude + Layout.fillWidth: true + placeholderText: qsTr("") + } + + RowLayout { + id: rowLayout1 + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignRight + + Button { + id: goButton + text: qsTr("Proceed") + } + + Button { + id: clearButton + text: qsTr("Clear") + } + + Button { + id: cancelButton + text: qsTr("Cancel") + } + } + Item { + Layout.fillHeight: true + Layout.columnSpan: 2 + } + } + } +} diff --git a/examples/location/mapviewer/forms/RouteAddress.qml b/examples/location/mapviewer/forms/RouteAddress.qml new file mode 100644 index 0000000..248396d --- /dev/null +++ b/examples/location/mapviewer/forms/RouteAddress.qml @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtPositioning 5.5 + +RouteAddressForm { + property alias plugin : tempGeocodeModel.plugin; + property variant fromAddress; + property variant toAddress; + signal showMessage(string topic, string message) + signal showRoute(variant startCoordinate,variant endCoordinate) + signal closeForm() + + goButton.onClicked: { + tempGeocodeModel.reset() + fromAddress.country = fromCountry.text + fromAddress.street = fromStreet.text + fromAddress.city = fromCity.text + toAddress.country = toCountry.text + toAddress.street = toStreet.text + toAddress.city = toCity.text + tempGeocodeModel.startCoordinate = QtPositioning.coordinate() + tempGeocodeModel.endCoordinate = QtPositioning.coordinate() + tempGeocodeModel.query = fromAddress + tempGeocodeModel.update(); + goButton.enabled = false; + } + + clearButton.onClicked: { + fromStreet.text = "" + fromCity.text = "" + fromCountry.text = "" + toStreet.text = "" + toCity.text = "" + toCountry.text = "" + } + + cancelButton.onClicked: { + closeForm() + } + + Component.onCompleted: { + fromStreet.text = fromAddress.street + fromCity.text = fromAddress.city + fromCountry.text = fromAddress.country + toStreet.text = toAddress.street + toCity.text = toAddress.city + toCountry.text = toAddress.country + } + + GeocodeModel { + id: tempGeocodeModel + + property int success: 0 + property variant startCoordinate + property variant endCoordinate + + onCountChanged: { + if (success == 1 && count == 1) { + query = toAddress + update(); + } + } + + onStatusChanged: { + if ((status == GeocodeModel.Ready) && (count == 1)) { + success++ + if (success == 1) { + startCoordinate.latitude = get(0).coordinate.latitude + startCoordinate.longitude = get(0).coordinate.longitude + } + if (success == 2) { + endCoordinate.latitude = get(0).coordinate.latitude + endCoordinate.longitude = get(0).coordinate.longitude + success = 0 + if (startCoordinate.isValid && endCoordinate.isValid) + showRoute(startCoordinate,endCoordinate) + else + goButton.enabled = true + } + } else if ((status == GeocodeModel.Ready) || (status == GeocodeModel.Error)) { + var st = (success == 0 ) ? "start" : "end" + success = 0 + if ((status == GeocodeModel.Ready) && (count == 0 )) { + showMessage(qsTr("Geocode Error"),qsTr("Unsuccessful geocode")); + goButton.enabled = true; + } + else if (status == GeocodeModel.Error) { + showMessage(qsTr("Geocode Error"), + qsTr("Unable to find location for the") + " " + + st + " " +qsTr("point")) + goButton.enabled = true; + } + else if ((status == GeocodeModel.Ready) && (count > 1 )) { + showMessage(qsTr("Ambiguous geocode"), + count + " " + qsTr("results found for the") + + " " + st + " " +qsTr("point, please specify location")) + goButton.enabled = true; + } + } + } + } +} diff --git a/examples/location/mapviewer/forms/RouteAddressForm.ui.qml b/examples/location/mapviewer/forms/RouteAddressForm.ui.qml new file mode 100644 index 0000000..3f98dc0 --- /dev/null +++ b/examples/location/mapviewer/forms/RouteAddressForm.ui.qml @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + property alias fromStreet: fromStreet + property alias fromCountry: fromCountry + property alias toStreet: toStreet + property alias toCity: toCity + property alias toCountry: toCountry + property alias fromCity: fromCity + property alias goButton: goButton + property alias clearButton: clearButton + property alias cancelButton: cancelButton + + Rectangle { + id: tabRectangle + y: 20 + height: tabTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: qsTr("Route Address") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + id: item2 + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + GridLayout { + id: gridLayout3 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + id: label1 + text: qsTr("From") + font.bold: true + anchors.horizontalCenter: parent.horizontalCenter + Layout.columnSpan : 2 + } + + Label { + id: label2 + text: qsTr("Street") + } + + TextField { + id: fromStreet + Layout.fillWidth: true + } + + Label { + id: label3 + text: qsTr("City") + } + + TextField { + id: fromCity + Layout.fillWidth: true + } + + Label { + id: label7 + text: qsTr("Country") + } + + TextField { + id: fromCountry + Layout.fillWidth: true + } + + Label { + id: label6 + text: qsTr("To") + font.bold: true + anchors.horizontalCenter: parent.horizontalCenter + Layout.columnSpan: 2 + } + + Label { + id: label4 + text: qsTr("Street") + } + + TextField { + id: toStreet + Layout.fillWidth: true + } + + Label { + id: label5 + text: qsTr("City") + } + + TextField { + id: toCity + Layout.fillWidth: true + } + + Label { + id: label8 + text: qsTr("Country") + } + + TextField { + id: toCountry + Layout.fillWidth: true + } + + RowLayout { + id: rowLayout1 + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignRight + + Button { + id: goButton + text: qsTr("Proceed") + } + + Button { + id: clearButton + text: qsTr("Clear") + } + + Button { + id: cancelButton + text: qsTr("Cancel") + } + } + + Item { + Layout.fillHeight: true + Layout.columnSpan: 2 + } + } + } +} diff --git a/examples/location/mapviewer/forms/RouteCoordinate.qml b/examples/location/mapviewer/forms/RouteCoordinate.qml new file mode 100644 index 0000000..f195ac7 --- /dev/null +++ b/examples/location/mapviewer/forms/RouteCoordinate.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtPositioning 5.5 + +RouteCoordinateForm { + property variant toCoordinate + property variant fromCoordinate + signal showRoute(variant startCoordinate,variant endCoordinate) + signal closeForm() + + goButton.onClicked: { + var startCoordinate = QtPositioning.coordinate(parseFloat(fromLatitude.text), + parseFloat(fromLongitude.text)); + var endCoordinate = QtPositioning.coordinate(parseFloat(toLatitude.text), + parseFloat(toLongitude.text)); + if (startCoordinate.isValid && endCoordinate.isValid) { + goButton.enabled = false; + showRoute(startCoordinate,endCoordinate) + } + } + + clearButton.onClicked: { + fromLatitude.text = "" + fromLongitude.text = "" + toLatitude.text = "" + toLongitude.text = "" + } + + cancelButton.onClicked: { + closeForm() + } + + Component.onCompleted: { + fromLatitude.text = "" + fromCoordinate.latitude + fromLongitude.text = "" + fromCoordinate.longitude + toLatitude.text = "" + toCoordinate.latitude + toLongitude.text = "" + toCoordinate.longitude + } +} + diff --git a/examples/location/mapviewer/forms/RouteCoordinateForm.ui.qml b/examples/location/mapviewer/forms/RouteCoordinateForm.ui.qml new file mode 100644 index 0000000..bd492d3 --- /dev/null +++ b/examples/location/mapviewer/forms/RouteCoordinateForm.ui.qml @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + property alias fromLatitude: fromLatitude + property alias fromLongitude: fromLongitude + property alias toLatitude: toLatitude + property alias toLongitude: toLongitude + property alias clearButton: clearButton + property alias goButton: goButton + property alias cancelButton: cancelButton + + Rectangle { + id: tabRectangle + y: 20 + height: tabTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: qsTr("Route Coordinates") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + id: item2 + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + GridLayout { + id: gridLayout3 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + id: label1 + text: qsTr("From") + anchors.horizontalCenter: parent.horizontalCenter + font.bold: true + Layout.columnSpan : 2 + } + + Label { + id: label2 + text: qsTr("Latitude") + } + + TextField { + id: fromLatitude + Layout.fillWidth: true + } + + Label { + id: label3 + text: qsTr("Longitude") + } + + TextField { + id: fromLongitude + Layout.fillWidth: true + } + + Label { + id: label6 + text: qsTr("To") + anchors.horizontalCenter: parent.horizontalCenter + font.bold: true + Layout.columnSpan: 2 + } + + Label { + id: label4 + text: qsTr("Latitude") + } + + TextField { + id: toLatitude + Layout.fillWidth: true + } + + Label { + id: label5 + text: qsTr("Longitude") + } + + TextField { + id: toLongitude + Layout.fillWidth: true + } + + RowLayout { + id: rowLayout1 + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignRight + Button { + id: goButton + text: qsTr("Proceed") + } + + Button { + id: clearButton + text: qsTr("Clear") + } + + Button { + id: cancelButton + text: qsTr("Cancel") + } + } + Item { + Layout.fillHeight: true + Layout.columnSpan: 2 + } + } + } +} diff --git a/examples/location/mapviewer/forms/RouteList.qml b/examples/location/mapviewer/forms/RouteList.qml new file mode 100644 index 0000000..27fa572 --- /dev/null +++ b/examples/location/mapviewer/forms/RouteList.qml @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import "../helper.js" as Helper + +//! [routeinfomodel0] +ListView { +//! [routeinfomodel0] + property variant routeModel + property string totalTravelTime + property string totalDistance + signal closeForm() +//! [routeinfomodel1] + interactive: true + model: ListModel { id: routeInfoModel } + header: RouteListHeader {} + delegate: RouteListDelegate{ + routeIndex.text: index + 1 + routeInstruction.text: instruction + routeDistance.text: distance + } +//! [routeinfomodel1] + footer: Button { + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Close") + onClicked: { + closeForm() + } + } + + Component.onCompleted: { + //! [routeinfomodel2] + routeInfoModel.clear() + if (routeModel.count > 0) { + for (var i = 0; i < routeModel.get(0).segments.length; i++) { + routeInfoModel.append({ + "instruction": routeModel.get(0).segments[i].maneuver.instructionText, + "distance": Helper.formatDistance(routeModel.get(0).segments[i].maneuver.distanceToNextInstruction) + }); + } + } + //! [routeinfomodel2] + totalTravelTime = routeModel.count == 0 ? "" : Helper.formatTime(routeModel.get(0).travelTime) + totalDistance = routeModel.count == 0 ? "" : Helper.formatDistance(routeModel.get(0).distance) + } +//! [routeinfomodel3] +} +//! [routeinfomodel3] diff --git a/examples/location/mapviewer/forms/RouteListDelegate.qml b/examples/location/mapviewer/forms/RouteListDelegate.qml new file mode 100644 index 0000000..2dc9981 --- /dev/null +++ b/examples/location/mapviewer/forms/RouteListDelegate.qml @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + id: root + property bool checked: false + property alias routeInstruction: instructionLabel + property alias routeDistance: distanceLabel + property alias routeIndex: indexLabel + + width: parent.width + height: indexLabel.height * 2 + + RowLayout { + spacing: 10 + anchors.left: parent.left + anchors.leftMargin: 30 + anchors.verticalCenter: parent.verticalCenter + Label { + id: indexLabel + } + Label { + id: instructionLabel + wrapMode: Text.Wrap + } + Label { + id: distanceLabel + } + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 15 + height: 1 + color: "#46a2da" + } +} + + + diff --git a/examples/location/mapviewer/forms/RouteListHeader.qml b/examples/location/mapviewer/forms/RouteListHeader.qml new file mode 100644 index 0000000..383f892 --- /dev/null +++ b/examples/location/mapviewer/forms/RouteListHeader.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Item { + property alias travelTime: travelTimeLabel + property alias distance: distanceLabel + width: parent.width + height: tabTitle.height * 3.0 + + Rectangle { + id: tabRectangle + y: tabTitle.height + height: tabTitle.height * 2 - 1 + color: "#46a2da" + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: qsTr("Route Information") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + + Label { + id: travelTimeLabel + text: totalTravelTime + color: "#ffffff" + font.bold: true + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + } + + Label { + id: distanceLabel + text: totalDistance + color: "#ffffff" + font.bold: true + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + } + } +} diff --git a/examples/location/mapviewer/helper.js b/examples/location/mapviewer/helper.js new file mode 100644 index 0000000..19201d0 --- /dev/null +++ b/examples/location/mapviewer/helper.js @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library + +function roundNumber(number, digits) +{ + var multiple = Math.pow(10, digits); + return Math.round(number * multiple) / multiple; +} + +function formatTime(sec) +{ + var value = sec + var seconds = value % 60 + value /= 60 + value = (value > 1) ? Math.round(value) : 0 + var minutes = value % 60 + value /= 60 + value = (value > 1) ? Math.round(value) : 0 + var hours = value + if (hours > 0) value = hours + "h:"+ minutes + "m" + else value = minutes + "min" + return value +} + +function formatDistance(meters) +{ + var dist = Math.round(meters) + if (dist > 1000 ){ + if (dist > 100000){ + dist = Math.round(dist / 1000) + } + else{ + dist = Math.round(dist / 100) + dist = dist / 10 + } + dist = dist + " km" + } + else{ + dist = dist + " m" + } + return dist +} diff --git a/examples/location/mapviewer/main.cpp b/examples/location/mapviewer/main.cpp new file mode 100644 index 0000000..1b52643 --- /dev/null +++ b/examples/location/mapviewer/main.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +static bool parseArgs(QStringList& args, QVariantMap& parameters) +{ + + while (!args.isEmpty()) { + + QString param = args.takeFirst(); + + if (param.startsWith("--help")) { + QTextStream out(stdout); + out << "Usage: " << endl; + out << "--plugin. - Sets parameter = value for plugin" << endl; + out.flush(); + return true; + } + + if (param.startsWith("--plugin.")) { + + param.remove(0, 9); + + if (args.isEmpty() || args.first().startsWith("--")) { + parameters[param] = true; + } else { + + QString value = args.takeFirst(); + + if (value == "true" || value == "on" || value == "enabled") { + parameters[param] = true; + } else if (value == "false" || value == "off" + || value == "disable") { + parameters[param] = false; + } else { + parameters[param] = value; + } + } + } + } + return false; +} + +int main(int argc, char *argv[]) +{ + QGuiApplication application(argc, argv); + + QVariantMap parameters; + QStringList args(QCoreApplication::arguments()); + + if (parseArgs(args, parameters)) + return 0; + if (!args.contains(QStringLiteral("osm.useragent"))) + parameters[QStringLiteral("osm.useragent")] = QStringLiteral("QtLocation Mapviewer example"); + + QQmlApplicationEngine engine; + engine.addImportPath(QStringLiteral(":/imports")); + engine.load(QUrl(QStringLiteral("qrc:///mapviewer.qml"))); + QObject::connect(&engine, SIGNAL(quit()), qApp, SLOT(quit())); + + QObject *item = engine.rootObjects().first(); + Q_ASSERT(item); + + QMetaObject::invokeMethod(item, "initializeProviders", + Q_ARG(QVariant, QVariant::fromValue(parameters))); + + return application.exec(); +} diff --git a/examples/location/mapviewer/map/CircleItem.qml b/examples/location/mapviewer/map/CircleItem.qml new file mode 100644 index 0000000..3b32ba5 --- /dev/null +++ b/examples/location/mapviewer/map/CircleItem.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.5 +import QtLocation 5.6 + +//TODO: remove/refactor me when items are integrated + +MapCircle { + + color: "#46a2da" + border.color: "#190a33" + border.width: 2 + smooth: true + opacity: 0.25 + + function setGeometry(markers, index){ + center.latitude = markers[index].coordinate.latitude + center.longitude = markers[index].coordinate.longitude + radius= center.distanceTo(markers[index + 1].coordinate) + } +} diff --git a/examples/location/mapviewer/map/ImageItem.qml b/examples/location/mapviewer/map/ImageItem.qml new file mode 100644 index 0000000..3bf4dfe --- /dev/null +++ b/examples/location/mapviewer/map/ImageItem.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.5; +import QtLocation 5.6 + +MapQuickItem { //to be used inside MapComponent only + id: imageItem + + MouseArea { + anchors.fill: parent + drag.target: parent + } + + function setGeometry(markers, index) { + coordinate.latitude = markers[index].coordinate.latitude + coordinate.longitude = markers[index].coordinate.longitude + } + + sourceItem: Image { + id: testImage + source: "../resources/icon.png" + opacity: 0.7 + } +} diff --git a/examples/location/mapviewer/map/MapComponent.qml b/examples/location/mapviewer/map/MapComponent.qml new file mode 100644 index 0000000..008a4a0 --- /dev/null +++ b/examples/location/mapviewer/map/MapComponent.qml @@ -0,0 +1,641 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtLocation 5.6 +import QtPositioning 5.5 +import "../helper.js" as Helper + +//! [top] +Map { + id: map +//! [top] + property variant markers + property variant mapItems + property int markerCounter: 0 // counter for total amount of markers. Resets to 0 when number of markers = 0 + property int currentMarker + property int lastX : -1 + property int lastY : -1 + property int pressX : -1 + property int pressY : -1 + property int jitterThreshold : 30 + property bool followme: false + property variant scaleLengths: [5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000, 2000000] + property alias routeQuery: routeQuery + property alias routeModel: routeModel + property alias geocodeModel: geocodeModel + + signal showGeocodeInfo() + signal geocodeFinished() + signal routeError() + signal coordinatesCaptured(double latitude, double longitude) + signal showMainMenu(variant coordinate) + signal showMarkerMenu(variant coordinate) + signal showRouteMenu(variant coordinate) + signal showPointMenu(variant coordinate) + signal showRouteList() + + function geocodeMessage() + { + var street, district, city, county, state, countryCode, country, postalCode, latitude, longitude, text + latitude = Math.round(geocodeModel.get(0).coordinate.latitude * 10000) / 10000 + longitude =Math.round(geocodeModel.get(0).coordinate.longitude * 10000) / 10000 + street = geocodeModel.get(0).address.street + district = geocodeModel.get(0).address.district + city = geocodeModel.get(0).address.city + county = geocodeModel.get(0).address.county + state = geocodeModel.get(0).address.state + countryCode = geocodeModel.get(0).address.countryCode + country = geocodeModel.get(0).address.country + postalCode = geocodeModel.get(0).address.postalCode + + text = "Latitude: " + latitude + "
" + text +="Longitude: " + longitude + "
" + "
" + if (street) text +="Street: "+ street + "
" + if (district) text +="District: "+ district +"
" + if (city) text +="City: "+ city + "
" + if (county) text +="County: "+ county + "
" + if (state) text +="State: "+ state + "
" + if (countryCode) text +="Country code: "+ countryCode + "
" + if (country) text +="Country: "+ country + "
" + if (postalCode) text +="PostalCode: "+ postalCode + "
" + return text + } + + function calculateScale() + { + var coord1, coord2, dist, text, f + f = 0 + coord1 = map.toCoordinate(Qt.point(0,scale.y)) + coord2 = map.toCoordinate(Qt.point(0+scaleImage.sourceSize.width,scale.y)) + dist = Math.round(coord1.distanceTo(coord2)) + + if (dist === 0) { + // not visible + } else { + for (var i = 0; i < scaleLengths.length-1; i++) { + if (dist < (scaleLengths[i] + scaleLengths[i+1]) / 2 ) { + f = scaleLengths[i] / dist + dist = scaleLengths[i] + break; + } + } + if (f === 0) { + f = dist / scaleLengths[i] + dist = scaleLengths[i] + } + } + + text = Helper.formatDistance(dist) + scaleImage.width = (scaleImage.sourceSize.width * f) - 2 * scaleImageLeft.sourceSize.width + scaleText.text = text + } + + function deleteMarkers() + { + var count = map.markers.length + for (var i = 0; i= 0) + map.zoomLevel = value + } + } + + Item { + id: scale + z: map.z + 3 + visible: scaleText.text != "0 m" + anchors.bottom: parent.bottom; + anchors.right: parent.right + anchors.margins: 20 + height: scaleText.height * 2 + width: scaleImage.width + + Image { + id: scaleImageLeft + source: "../resources/scale_end.png" + anchors.bottom: parent.bottom + anchors.right: scaleImage.left + } + Image { + id: scaleImage + source: "../resources/scale.png" + anchors.bottom: parent.bottom + anchors.right: scaleImageRight.left + } + Image { + id: scaleImageRight + source: "../resources/scale_end.png" + anchors.bottom: parent.bottom + anchors.right: parent.right + } + Label { + id: scaleText + color: "#004EAE" + anchors.centerIn: parent + text: "0 m" + } + Component.onCompleted: { + map.calculateScale(); + } + } + + //! [routemodel0] + RouteModel { + id: routeModel + plugin : map.plugin + query: RouteQuery { + id: routeQuery + } + onStatusChanged: { + if (status == RouteModel.Ready) { + switch (count) { + case 0: + // technically not an error + map.routeError() + break + case 1: + map.showRouteList() + break + } + } else if (status == RouteModel.Error) { + map.routeError() + } + } + } + //! [routemodel0] + + //! [routedelegate0] + Component { + id: routeDelegate + + MapRoute { + id: route + route: routeData + line.color: "#46a2da" + line.width: 5 + smooth: true + opacity: 0.8 + //! [routedelegate0] + MouseArea { + id: routeMouseArea + anchors.fill: parent + hoverEnabled: false + property variant lastCoordinate + + onPressed : { + map.lastX = mouse.x + parent.x + map.lastY = mouse.y + parent.y + map.pressX = mouse.x + parent.x + map.pressY = mouse.y + parent.y + lastCoordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y)) + } + + onPositionChanged: { + if (mouse.button == Qt.LeftButton) { + map.lastX = mouse.x + parent.x + map.lastY = mouse.y + parent.y + } + } + + onPressAndHold:{ + if (Math.abs(map.pressX - parent.x- mouse.x ) < map.jitterThreshold + && Math.abs(map.pressY - parent.y - mouse.y ) < map.jitterThreshold) { + showRouteMenu(lastCoordinate); + } + } + + } + //! [routedelegate1] + } + } + //! [routedelegate1] + + //! [geocodemodel0] + GeocodeModel { + id: geocodeModel + plugin: map.plugin + onStatusChanged: { + if ((status == GeocodeModel.Ready) || (status == GeocodeModel.Error)) + map.geocodeFinished() + } + onLocationsChanged: + { + if (count == 1) { + map.center.latitude = get(0).coordinate.latitude + map.center.longitude = get(0).coordinate.longitude + } + } + } + //! [geocodemodel0] + + //! [pointdel0] + Component { + id: pointDelegate + + MapCircle { + id: point + radius: 1000 + color: "#46a2da" + border.color: "#190a33" + border.width: 2 + smooth: true + opacity: 0.25 + center: locationData.coordinate + //! [pointdel0] + MouseArea { + anchors.fill:parent + id: circleMouseArea + hoverEnabled: false + property variant lastCoordinate + + onPressed : { + map.lastX = mouse.x + parent.x + map.lastY = mouse.y + parent.y + map.pressX = mouse.x + parent.x + map.pressY = mouse.y + parent.y + lastCoordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y)) + } + + onPositionChanged: { + if (Math.abs(map.pressX - parent.x- mouse.x ) > map.jitterThreshold || + Math.abs(map.pressY - parent.y -mouse.y ) > map.jitterThreshold) { + if (pressed) parent.radius = parent.center.distanceTo( + map.toCoordinate(Qt.point(mouse.x, mouse.y))) + } + if (mouse.button == Qt.LeftButton) { + map.lastX = mouse.x + parent.x + map.lastY = mouse.y + parent.y + } + } + + onPressAndHold:{ + if (Math.abs(map.pressX - parent.x- mouse.x ) < map.jitterThreshold + && Math.abs(map.pressY - parent.y - mouse.y ) < map.jitterThreshold) { + showPointMenu(lastCoordinate); + } + } + } + //! [pointdel1] + } + } + //! [pointdel1] + + //! [routeview0] + MapItemView { + model: routeModel + delegate: routeDelegate + //! [routeview0] + autoFitViewport: true + //! [routeview1] + } + //! [routeview1] + + //! [geocodeview] + MapItemView { + model: geocodeModel + delegate: pointDelegate + } + //! [geocodeview] + + Timer { + id: scaleTimer + interval: 100 + running: false + repeat: false + onTriggered: { + map.calculateScale() + } + } + + MouseArea { + id: mouseArea + property variant lastCoordinate + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onPressed : { + map.lastX = mouse.x + map.lastY = mouse.y + map.pressX = mouse.x + map.pressY = mouse.y + lastCoordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y)) + } + + onPositionChanged: { + if (mouse.button == Qt.LeftButton) { + map.lastX = mouse.x + map.lastY = mouse.y + } + } + + onDoubleClicked: { + var mouseGeoPos = map.toCoordinate(Qt.point(mouse.x, mouse.y)); + var preZoomPoint = map.fromCoordinate(mouseGeoPos, false); + if (mouse.button === Qt.LeftButton) { + map.zoomLevel++; + } else if (mouse.button === Qt.RightButton) { + map.zoomLevel--; + } + var postZoomPoint = map.fromCoordinate(mouseGeoPos, false); + var dx = postZoomPoint.x - preZoomPoint.x; + var dy = postZoomPoint.y - preZoomPoint.y; + + var mapCenterPoint = Qt.point(map.width / 2.0 + dx, map.height / 2.0 + dy); + map.center = map.toCoordinate(mapCenterPoint); + + lastX = -1; + lastY = -1; + } + + onPressAndHold:{ + if (Math.abs(map.pressX - mouse.x ) < map.jitterThreshold + && Math.abs(map.pressY - mouse.y ) < map.jitterThreshold) { + showMainMenu(lastCoordinate); + } + } + } +//! [end] +} +//! [end] diff --git a/examples/location/mapviewer/map/Marker.qml b/examples/location/mapviewer/map/Marker.qml new file mode 100644 index 0000000..3c0ed17 --- /dev/null +++ b/examples/location/mapviewer/map/Marker.qml @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5; +import QtLocation 5.6 + +//! [mqi-top] +MapQuickItem { + id: marker +//! [mqi-top] + property alias lastMouseX: markerMouseArea.lastX + property alias lastMouseY: markerMouseArea.lastY + +//! [mqi-anchor] + anchorPoint.x: image.width/4 + anchorPoint.y: image.height + + sourceItem: Image { + id: image +//! [mqi-anchor] + source: "../resources/marker.png" + opacity: markerMouseArea.pressed ? 0.6 : 1.0 + MouseArea { + id: markerMouseArea + property int pressX : -1 + property int pressY : -1 + property int jitterThreshold : 10 + property int lastX: -1 + property int lastY: -1 + anchors.fill: parent + hoverEnabled : false + drag.target: marker + preventStealing: true + + onPressed : { + map.pressX = mouse.x + map.pressY = mouse.y + map.currentMarker = -1 + for (var i = 0; i< map.markers.length; i++){ + if (marker == map.markers[i]){ + map.currentMarker = i + break + } + } + } + + onPressAndHold:{ + if (Math.abs(map.pressX - mouse.x ) < map.jitterThreshold + && Math.abs(map.pressY - mouse.y ) < map.jitterThreshold) { + var p = map.fromCoordinate(marker.coordinate) + lastX = p.x + lastY = p.y + map.showMarkerMenu(marker.coordinate) + } + } + } + + Text{ + id: number + y: image.height/10 + width: image.width + color: "white" + font.bold: true + font.pixelSize: 14 + horizontalAlignment: Text.AlignHCenter + Component.onCompleted: { + text = map.markerCounter + } + } + +//! [mqi-closeimage] + } +//! [mqi-closeimage] + + Component.onCompleted: coordinate = map.toCoordinate(Qt.point(markerMouseArea.mouseX, + markerMouseArea.mouseY)); +//! [mqi-close] +} +//! [mqi-close] diff --git a/examples/location/mapviewer/map/MiniMap.qml b/examples/location/mapviewer/map/MiniMap.qml new file mode 100644 index 0000000..43af605 --- /dev/null +++ b/examples/location/mapviewer/map/MiniMap.qml @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 + +Rectangle{ + id: miniMapRect + width: 152 + height: 152 + anchors.right: (parent) ? parent.right : undefined + anchors.rightMargin: 10 + anchors.top: (parent) ? parent.top : undefined + anchors.topMargin: 10 + color: "#242424" + Map { + id: miniMap + anchors.top: parent.top + anchors.topMargin: 1 + anchors.left: parent.left + anchors.leftMargin: 1 + width: 150 + height: 150 + zoomLevel: (map.zoomLevel > minimumZoomLevel + 3) ? minimumZoomLevel + 3 : 2.5 + center: map.center + plugin: map.plugin + gesture.enabled: false + copyrightsVisible: false + + MapRectangle { + color: "#44ff0000" + border.width: 1 + border.color: "red" + topLeft { + latitude: miniMap.center.latitude + 5 + longitude: miniMap.center.longitude - 5 + } + bottomRight { + latitude: miniMap.center.latitude - 5 + longitude: miniMap.center.longitude + 5 + } + } + } +} diff --git a/examples/location/mapviewer/map/PolygonItem.qml b/examples/location/mapviewer/map/PolygonItem.qml new file mode 100644 index 0000000..cab4e6c --- /dev/null +++ b/examples/location/mapviewer/map/PolygonItem.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.5 +import QtLocation 5.6 + +//TODO: remove me when items are integrated + +MapPolygon { + + color: "#46a2da" + border.color: "#190a33" + border.width: 2 + smooth: true + opacity: 0.25 + + function setGeometry(markers, index){ + for (var i = index; i0) + plugin = Qt.createQmlObject ('import QtLocation 5.6; Plugin{ name:"' + provider + '"; parameters: appWindow.parameters}', appWindow) + else + plugin = Qt.createQmlObject ('import QtLocation 5.6; Plugin{ name:"' + provider + '"}', appWindow) + + if (minimap) { + minimap.destroy() + minimap = null + } + + var zoomLevel = null + var center = null + if (map) { + zoomLevel = map.zoomLevel + center = map.center + map.destroy() + } + + map = mapComponent.createObject(page); + map.plugin = plugin; + + if (zoomLevel != null) { + map.zoomLevel = zoomLevel + map.center = center + } else { + map.zoomLevel = (map.maximumZoomLevel - map.minimumZoomLevel)/2 + } + + map.forceActiveFocus() + } + + function getPlugins() + { + var plugin = Qt.createQmlObject ('import QtLocation 5.6; Plugin {}', appWindow) + var myArray = new Array() + for (var i = 0; i" + qsTr("Distance:") + " " + distance) + break + case "drawImage": + map.addGeoItem("ImageItem") + break + case "drawRectangle": + map.addGeoItem("RectangleItem") + break + case "drawCircle": + map.addGeoItem("CircleItem") + break; + case "drawPolyline": + map.addGeoItem("PolylineItem") + break; + case "drawPolygonMenu": + map.addGeoItem("PolygonItem") + break + default: + console.log("Unsupported operation") + } + } + } + + ItemPopupMenu { + id: itemPopupMenu + + function show(type,coordinate) + { + stackView.pop(page) + itemPopupMenu.type = type + itemPopupMenu.update() + itemPopupMenu.popup() + } + + onItemClicked: { + stackView.pop(page) + switch (item) { + case "showRouteInfo": + stackView.showRouteListPage() + break; + case "deleteRoute": + map.routeModel.reset(); + break; + case "showPointInfo": + map.showGeocodeInfo() + break; + case "deletePoint": + map.geocodeModel.reset() + break; + default: + console.log("Unsupported operation") + } + } + } + + StackView { + id: stackView + anchors.fill: parent + focus: true + initialItem: Item { + id: page + } + + function showMessage(title,message,backPage) + { + push({ item: Qt.resolvedUrl("forms/Message.qml") , + properties: { + "title" : title, + "message" : message, + "backPage" : backPage + }}) + currentItem.closeForm.connect(closeMessage) + } + + function closeMessage(backPage) + { + pop(backPage) + } + + function closeForm() + { + pop(page) + } + + function showRouteListPage() + { + push({ item: Qt.resolvedUrl("forms/RouteList.qml") , + properties: { + "routeModel" : map.routeModel + }}) + currentItem.closeForm.connect(closeForm) + } + } + + Component { + id: mapComponent + + MapComponent{ + width: page.width + height: page.height + onFollowmeChanged: mainMenu.isFollowMe = map.followme + onSupportedMapTypesChanged: mainMenu.mapTypeMenu.createMenu(map) + onCoordinatesCaptured: { + var text = "" + qsTr("Latitude:") + " " + Helper.roundNumber(latitude,4) + "
" + qsTr("Longitude:") + " " + Helper.roundNumber(longitude,4) + stackView.showMessage(qsTr("Coordinates"),text); + } + onGeocodeFinished:{ + if (map.geocodeModel.status == GeocodeModel.Ready) { + if (map.geocodeModel.count == 0) { + stackView.showMessage(qsTr("Geocode Error"),qsTr("Unsuccessful geocode")) + } else if (map.geocodeModel.count > 1) { + stackView.showMessage(qsTr("Ambiguous geocode"), map.geocodeModel.count + " " + + qsTr("results found for the given address, please specify location")) + } else { + stackView.showMessage(qsTr("Location"), geocodeMessage(),page) + } + } else if (map.geocodeModel.status == GeocodeModel.Error) { + stackView.showMessage(qsTr("Geocode Error"),qsTr("Unsuccessful geocode")) + } + } + onRouteError: stackView.showMessage(qsTr("Route Error"),qsTr("Unable to find a route for the given points"),page) + + onShowGeocodeInfo: stackView.showMessage(qsTr("Location"),geocodeMessage(),page) + + onErrorChanged: { + if (map.error != Map.NoError) { + var title = qsTr("ProviderError") + var message = map.errorString + "

" + qsTr("Try to select other provider") + "" + if (map.error == Map.MissingRequiredParameterError) + message += "
" + qsTr("or see") + " \'mapviewer --help\' " + + qsTr("how to pass plugin parameters.") + stackView.showMessage(title,message); + } + } + onShowMainMenu: mapPopupMenu.show(coordinate) + onShowMarkerMenu: markerPopupMenu.show(coordinate) + onShowRouteMenu: itemPopupMenu.show("Route",coordinate) + onShowPointMenu: itemPopupMenu.show("Point",coordinate) + onShowRouteList: stackView.showRouteListPage() + } + } +} diff --git a/examples/location/mapviewer/mapviewer.qrc b/examples/location/mapviewer/mapviewer.qrc new file mode 100644 index 0000000..a84c67d --- /dev/null +++ b/examples/location/mapviewer/mapviewer.qrc @@ -0,0 +1,37 @@ + + + mapviewer.qml + map/MapComponent.qml + map/Marker.qml + map/PolylineItem.qml + map/RectangleItem.qml + map/CircleItem.qml + map/PolygonItem.qml + map/ImageItem.qml + map/MiniMap.qml + forms/Message.qml + forms/MessageForm.ui.qml + forms/Geocode.qml + forms/GeocodeForm.ui.qml + forms/ReverseGeocode.qml + forms/ReverseGeocodeForm.ui.qml + forms/RouteCoordinate.qml + forms/RouteCoordinateForm.ui.qml + forms/RouteAddress.qml + forms/RouteAddressForm.ui.qml + forms/Locale.qml + forms/LocaleForm.ui.qml + forms/RouteList.qml + forms/RouteListDelegate.qml + forms/RouteListHeader.qml + menus/MainMenu.qml + menus/MapPopupMenu.qml + menus/MarkerPopupMenu.qml + menus/ItemPopupMenu.qml + helper.js + resources/scale_end.png + resources/scale.png + resources/marker.png + resources/icon.png + + diff --git a/examples/location/mapviewer/menus/ItemPopupMenu.qml b/examples/location/mapviewer/menus/ItemPopupMenu.qml new file mode 100644 index 0000000..8d7e2f7 --- /dev/null +++ b/examples/location/mapviewer/menus/ItemPopupMenu.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Menu { + property variant type + signal itemClicked(string item) + + function update() { + clear() + addItem(qsTr("Info")).triggered.connect(function(){itemClicked("show" + type + "Info")}) + addItem(qsTr("Delete")).triggered.connect(function(){itemClicked("delete" + type )}) + } +} diff --git a/examples/location/mapviewer/menus/MainMenu.qml b/examples/location/mapviewer/menus/MainMenu.qml new file mode 100644 index 0000000..7054c40 --- /dev/null +++ b/examples/location/mapviewer/menus/MainMenu.qml @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtLocation 5.6 + +MenuBar { + property variant providerMenu: providerMenu + property variant mapTypeMenu: mapTypeMenu + property variant toolsMenu: toolsMenu + property alias isFollowMe: toolsMenu.isFollowMe + property alias isMiniMap: toolsMenu.isMiniMap + + signal selectProvider(string providerName) + signal selectMapType(variant mapType) + signal selectTool(string tool); + signal toggleMapState(string state) + + Menu { + id: providerMenu + title: qsTr("Provider") + + function createMenu(plugins) + { + clear() + for (var i = 0; i < plugins.length; i++) { + createProviderMenuItem(plugins[i]); + } + } + + function createProviderMenuItem(provider) + { + var item = addItem(provider); + item.checkable = true; + item.triggered.connect(function(){selectProvider(provider)}) + } + } + + Menu { + id: mapTypeMenu + title: qsTr("MapType") + + function createMenu(map) + { + clear() + for (var i = 0; i 0) { + addItem(qsTr("Delete all markers")).triggered.connect(function(){itemClicked("deleteMarkers")}) + } + + if (mapItemsCount > 0) { + addItem(qsTr("Delete all items")).triggered.connect(function(){itemClicked("deleteItems")}) + } + } +} diff --git a/examples/location/mapviewer/menus/MarkerPopupMenu.qml b/examples/location/mapviewer/menus/MarkerPopupMenu.qml new file mode 100644 index 0000000..61855ff --- /dev/null +++ b/examples/location/mapviewer/menus/MarkerPopupMenu.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Menu { + property int currentMarker + property int markersCount + signal itemClicked(string item) + + function update() { + clear() + addItem(qsTr("Delete")).triggered.connect(function(){itemClicked("deleteMarker")}) + addItem(qsTr("Coordinates")).triggered.connect(function(){itemClicked("getMarkerCoordinate")}) + addItem(qsTr("Move to")).triggered.connect(function(){itemClicked("moveMarkerTo")}) + if (currentMarker == markersCount-2){ + addItem(qsTr("Route to next point")).triggered.connect(function(){itemClicked("routeToNextPoint")}); + addItem(qsTr("Distance to next point")).triggered.connect(function(){itemClicked("distanceToNextPoint")}); + } + if (currentMarker < markersCount-2){ + addItem(qsTr("Route to next points")).triggered.connect(function(){itemClicked("routeToNextPoints")}); + addItem(qsTr("Distance to next point")).triggered.connect(function(){itemClicked("distanceToNextPoint")}); + } + + var menu = addMenu(qsTr("Draw...")) + menu.addItem(qsTr("Image")).triggered.connect(function(){itemClicked("drawImage")}) + + if (currentMarker <= markersCount-2){ + menu.addItem(qsTr("Rectangle")).triggered.connect(function(){itemClicked("drawRectangle")}) + menu.addItem(qsTr("Circle")).triggered.connect(function(){itemClicked("drawCircle")}) + menu.addItem(qsTr("Polyline")).triggered.connect(function(){itemClicked("drawPolyline")}) + } + + if (currentMarker < markersCount-2){ + menu.addItem(qsTr("Polygon")).triggered.connect(function(){itemClicked("drawPolygonMenu")}) + } + } +} diff --git a/examples/location/mapviewer/resources/icon.png b/examples/location/mapviewer/resources/icon.png new file mode 100644 index 0000000..973a500 Binary files /dev/null and b/examples/location/mapviewer/resources/icon.png differ diff --git a/examples/location/mapviewer/resources/marker.png b/examples/location/mapviewer/resources/marker.png new file mode 100644 index 0000000..2116dfd Binary files /dev/null and b/examples/location/mapviewer/resources/marker.png differ diff --git a/examples/location/mapviewer/resources/scale.png b/examples/location/mapviewer/resources/scale.png new file mode 100644 index 0000000..c4f0812 Binary files /dev/null and b/examples/location/mapviewer/resources/scale.png differ diff --git a/examples/location/mapviewer/resources/scale_end.png b/examples/location/mapviewer/resources/scale_end.png new file mode 100644 index 0000000..94510b1 Binary files /dev/null and b/examples/location/mapviewer/resources/scale_end.png differ diff --git a/examples/location/minimal_map/doc/images/minimal_map.png b/examples/location/minimal_map/doc/images/minimal_map.png new file mode 100644 index 0000000..31ad0f8 Binary files /dev/null and b/examples/location/minimal_map/doc/images/minimal_map.png differ diff --git a/examples/location/minimal_map/doc/src/minimal_map.qdoc b/examples/location/minimal_map/doc/src/minimal_map.qdoc new file mode 100644 index 0000000..06b310a --- /dev/null +++ b/examples/location/minimal_map/doc/src/minimal_map.qdoc @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\example minimal_map +\title Minimal Map (QML) +\ingroup qtlocation-examples +\brief The minimum code to display a map using Qt Quick. + +\image minimal_map.png + +\e {Minimal Map} demonstrates how to use the \l{Map} item to render a map. +It shows the minimum amount of code needed to display the map, and can be used +as a basis for further experimentation. + +\include examples-run.qdocinc + +\section1 C++ Code + +In \c main.cpp we use only the QGuiApplication and QQmlApplicationEngine +classes. + +\quotefromfile minimal_map/main.cpp +\skipto #include +\printto main + +In the main function, we first instantiate a QGuiApplication object. +Then we create a QQmlApplicationEngine and tell it to load \c main.qml +from the \l{The Qt Resource System}{Qt Resource System}. + +Finally, QGuiApplication::exec() launches the main event loop. + +\printuntil } + +\section1 QML Code + +In \c main.qml, we import the \l {Qt Location QML Types}{QtLocation} QML module +and its depending \l {Qt Positioning QML Types}{QtPositioning} QML module. +Next, we create the top level window, set a sensible default size, and make +it visible. The window will be filled by a \l [QML]{Map} item showing the map. + +\quotefromfile minimal_map/main.qml +\skipto import +\printuntil } +\printline } +\skipto Map +\printuntil } +\printline } + +The \l [QML]{Plugin} item is necessary to define the map provider we are +going to use. The example can work with any of the available geo services +plugins. However, some plugins may require additional plugin parameters +in order to function correctly and we can use \l [QML]{PluginParameter} +to specify them. In this example, we use the \c osm plugin, which is a +\l {Qt Location Open Street Map Plugin} and does not require any parameters. + +In the \l [QML]{Map} item, we refer to the \c plugin we use and we set the \c +center and the \c zoomLevel of the map. + +\section1 Requirements + +The example requires a working internet connection to download +\c OpenStreetMap map tiles. An optional system proxy should be picked +up automatically. +*/ diff --git a/examples/location/minimal_map/main.cpp b/examples/location/minimal_map/main.cpp new file mode 100644 index 0000000..e0b58e3 --- /dev/null +++ b/examples/location/minimal_map/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} + diff --git a/examples/location/minimal_map/main.qml b/examples/location/minimal_map/main.qml new file mode 100644 index 0000000..26f2498 --- /dev/null +++ b/examples/location/minimal_map/main.qml @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Window 2.0 +import QtLocation 5.6 +import QtPositioning 5.6 + +Window { + width: 512 + height: 512 + visible: true + + Plugin { + id: osmPlugin + name: "osm" + // specify plugin parameters if necessary + // PluginParameter { + // name: + // value: + // } + } + + Map { + anchors.fill: parent + plugin: osmPlugin + center: QtPositioning.coordinate(59.91, 10.75) // Oslo + zoomLevel: 10 + } +} diff --git a/examples/location/minimal_map/minimal_map.pro b/examples/location/minimal_map/minimal_map.pro new file mode 100644 index 0000000..5c16525 --- /dev/null +++ b/examples/location/minimal_map/minimal_map.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +QT += location + +SOURCES += main.cpp + +RESOURCES += qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/location/minimal_map +INSTALLS += target diff --git a/examples/location/minimal_map/qml.qrc b/examples/location/minimal_map/qml.qrc new file mode 100644 index 0000000..0ff3892 --- /dev/null +++ b/examples/location/minimal_map/qml.qrc @@ -0,0 +1,6 @@ + + + main.qml + + + diff --git a/examples/location/places/doc/images/places.png b/examples/location/places/doc/images/places.png new file mode 100644 index 0000000..0b1ac8b Binary files /dev/null and b/examples/location/places/doc/images/places.png differ diff --git a/examples/location/places/doc/src/places.qdoc b/examples/location/places/doc/src/places.qdoc new file mode 100644 index 0000000..bc93bca --- /dev/null +++ b/examples/location/places/doc/src/places.qdoc @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example places + \title Places (QML) + \ingroup qtlocation-examples + + \brief The Places example demonstrates how to search for Places and access + related content. + + \image places.png + + The Places example demonstrates how to search for Places. In particular it shows + how further information such as reviews, images and related content can be retrieved. + + \include examples-run.qdocinc + + \include example-parameters.qdocinc + + \section1 Overview + + The Places example presents an application window displaying a map. At the top of the window + is a search box, which is used to enter a place search query. To search for a place enter a + search term into the text box and click the magnifying glass icon. To search for a place by + category, click the category icon to display the list of available categories and select the + desired category. The place search query will be for places that are near the current location + shown on the map. + + For some plugins like \l {Qt Location HERE Plugin} the search box provides search term + suggestions when three or more characters are entered. Selecting one of the suggestions will + cause a place search to be performed with the selected search text. + + Clicking on a search result will display details about the place. If a places has rich content + (editorials, reviews and images), these can be accessed by the buttons on the details page. + To find similar places click the "Find similar" button. + + The geo service provider can be changed by accessing the "Provider" menu. + + \section1 Displaying Categories + + Before search by category can be performed, the list of available categories needs to be + retrieved. This is achieved by creating a \l CategoryModel. + + \snippet places/places.qml CategoryModel model + + The \l CategoryModel type provides a model of the available categories. It can provide + either a flat list or a hierarchical tree model. In this example, we use a hierarchical tree + model, by setting the \l {CategoryModel::hierarchical}{hierarchical} property to \e true. The + \l {CategoryModel::plugin}{plugin} property is set during example intalization. + + Next we create a \l {ListView} to display the category model. + + \snippet places/views/CategoryView.qml CategoryModel view + + Because a hierarchical model is being used, a \l DelegateModel is needed to provide + navigation functionality. If flat list model was being used the view could use the + \l CategoryModel directly. + + The \e rootIndex property sets the root index of the \l DelegateModel. Categories are + displayed by the \e CategoryDelegate, which provides two signals. The \e onShowSubcategories + emits the \b showSubcategories() signal with root index to the current index causing the + sub categories of the selected category to be displayed. The \e onSearchCategory handler emits + the \b searchCategory() signal with a category parameter indicating which specific category + has been chosen. + + The \e CategoryDelegate displays the category name and emits the \b searchCategory() signal when + the \l {Label} is clicked: + + \snippet places/views/CategoryDelegate.qml CategoryModel delegate text + + The \e CategoryDelegate also displays \e arrow \l {ToolButton} when \e hasModelChildren property is set. + + \snippet places/views/CategoryDelegate.qml CategoryModel delegate arrow + + + \target Presenting-Search-Suggestions + \section1 Presenting Search Suggestions + + The \l PlaceSearchSuggestionModel type is used to fetch suggested search terms based on a + partially entered search term. + + A new suggestion search is triggered whenever the entered search term is changed. + + \snippet places/places.qml PlaceSearchSuggestionModel search text changed 1 + \snippet places/places.qml PlaceSearchSuggestionModel search text changed 2 + \snippet places/places.qml PlaceSearchSuggestionModel search text changed 3 + + Suggestions are only queried if the length of the search term is three or more characters. + + When the status of the \l PlaceSearchSuggestionModel changes, search suggestions are displayed. + + \snippet places/places.qml PlaceSearchSuggestionModel model + + The main object in the "SuggestionsShown" state is the \l ListView showing the search + suggestions. + + \snippet places/views/SuggestionView.qml PlaceSearchSuggestionModel view 1 + \codeline + \snippet places/views/SuggestionView.qml PlaceSearchSuggestionModel view 2 + + A \l {Label} object is used as the delegate to display the suggestion text. Clicking on the + suggested search term updates the search term and triggers a place search using the search + suggestion. + + + \section1 Searching for Places + + The \l PlaceSearchModel type is used to search for places. + + \snippet places/places.qml PlaceSearchModel model + + First some of the model's properties are set, which will be used to form the search request. + The \l {PlaceSearchModel::searchArea}{searchArea} property is set to the + \e searchRegion object which is a \l [QML]{geocircle} with a center that is linked to the current + location displayed on the \l Map. + + Finally, we define three helper functions \b searchForCategory(), \b {searchForText()} and + \b searchForRecommendations() which set either the \l {PlaceSearchModel::categories}{categories} or + \l {PlaceSearchModel::searchTerm}{searchTerm} or \l {PlaceSearchModel::recommendationId}{recommendationId} + properties and invokes the \l {PlaceSearchModel::update()}{update()} method to start the + place search. The search results are displayed in a \l ListView. + + \snippet places/views/SearchResultView.qml PlaceSearchModel place list + + The delegate used in the \l ListView, \e SearchResultDelegate, is designed to handle multiple + search result types via a \l Loader object. For results of type \e PlaceResult the delegate + is: + + \snippet places/views/SearchResultDelegate.qml PlaceSearchModel place delegate + + \section1 Displaying Place Content + + Places can have additional rich content, including editorials, reviews and images. Rich + content is accessed via a set of models. Content models are generally not created directly by + the application developer, instead models are obtained from the + \l {Place::editorialModel}{editorialModel}, \l {Place::reviewModel}{reviewModel} and + \l {Place::imageModel}{imageModel} properties of the \l Place type. + + \snippet places/views/EditorialView.qml PlaceEditorialModel view + +*/ diff --git a/examples/location/places/forms/Message.qml b/examples/location/places/forms/Message.qml new file mode 100644 index 0000000..5d12c1f --- /dev/null +++ b/examples/location/places/forms/Message.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 + +MessageForm { + property string title + property string message + property variant backPage + + signal closeForm(variant backPage) + + button.onClicked: { + closeForm(backPage) + } + + Component.onCompleted: { + messageText.text = message + messageTitle.text = title + } +} diff --git a/examples/location/places/forms/MessageForm.ui.qml b/examples/location/places/forms/MessageForm.ui.qml new file mode 100644 index 0000000..a300841 --- /dev/null +++ b/examples/location/places/forms/MessageForm.ui.qml @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + id: root + property alias messageText: messageText + property alias messageTitle: messageTitle + property alias button: button + + Rectangle { + id: tabRectangle + y: 20 + height: messageTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: messageTitle + color: "#ffffff" + text: qsTr("type") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + ColumnLayout { + id: columnLayout1 + spacing: 20 + anchors.fill: parent + + Label { + id: messageText + text: qsTr("message") + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + textFormat: Text.RichText + } + + Button { + id: button + text: qsTr("OK") + Layout.alignment: Qt.AlignHCenter + } + + Item { + Layout.fillHeight: true + } + } + } +} + diff --git a/examples/location/places/forms/PlaceDetails.qml b/examples/location/places/forms/PlaceDetails.qml new file mode 100644 index 0000000..7d7a698 --- /dev/null +++ b/examples/location/places/forms/PlaceDetails.qml @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import "../helper.js" as Helper + +PlaceDetailsForm { + + property variant place + property real distanceToPlace + + signal searchForSimilar(variant place) + signal showReviews(variant place) + signal showEditorials(variant place) + signal showImages(variant place) + + function placeAddress(place) { + if (!place) + return ""; + + if (place.location.address.text.length > 0) + return place.location.address.text; + + return place.location.address.street; + } + + function categoryNames(categories) { + var result = ""; + + for (var i = 0; i < categories.length; ++i) { + if (result == "") { + result = categories[i].name; + } else { + result = result + ", " + categories[i].name; + } + } + + return result; + } + + function additonalInformation(place) { + var keys = place.extendedAttributes.keys(); + var result; + + for (var i = 0; i < keys.length; ++i) { + var label = place.extendedAttributes[keys[i]].label; + var text = place.extendedAttributes[keys[i]].text; + if (label) { + result += label + ": " + if (text) + result += text + result += "
" + } + } + + if (!result) + result = qsTr("No information") + + return result; + } + + editorialsButton.onClicked: showEditorials(place) + imagesButton.onClicked: showImages(place) + reviewsButton.onClicked: showReviews(place) + findSimilarButton.onClicked: searchForSimilar(place) + + Component.onCompleted: { + placeName.text = place ? (place.favorite ? place.favorite.name : place.name) : "" + placeIcon.source = place ? (place.favorite ? place.favorite.icon.url(Qt.size(40,40)) + : place.icon.url() == "" ? + "../resources/marker.png" + : place.icon.url(Qt.size(40,40))) : "" + ratingView.rating = (place && place.ratings) ? place.ratings.average : 0 + distance.text = Helper.formatDistance(distanceToPlace) + address.text = placeAddress(place) + categories.text = place ? categoryNames(place.categories) : "" + phone.text = place ? place.primaryPhone : "" + fax.text = place ? place.primaryFax : "" + email.text = place ? place.primaryEmail : "" + website.text = place ? '' + place.primaryWebsite + '' : "" + addInformation.text = place ? additonalInformation(place) : "" + if (place) { + editorialsButton.enabled = Qt.binding(function(){ return place && place.editorialModel.totalCount > 0 }) + reviewsButton.enabled = Qt.binding(function(){ return place && place.reviewModel.totalCount > 0 }) + imagesButton.enabled = Qt.binding(function(){ return place && place.imageModel.totalCount > 0 }) + findSimilarButton.enabled = true + } + } +} + diff --git a/examples/location/places/forms/PlaceDetailsForm.ui.qml b/examples/location/places/forms/PlaceDetailsForm.ui.qml new file mode 100644 index 0000000..f13b9b5 --- /dev/null +++ b/examples/location/places/forms/PlaceDetailsForm.ui.qml @@ -0,0 +1,285 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 +import "../views" + +Item { + id: root + property alias placeName: placeName + property alias placeIcon: placeIcon + property alias distance: distance + property alias address: address + property alias categories: categories + property alias phone: phone + property alias fax: fax + property alias email: email + property alias website: website + property alias addInformation: addInformation + property alias editorialsButton: editorialsButton + property alias reviewsButton: reviewsButton + property alias imagesButton: imagesButton + property alias findSimilarButton: findSimilarButton + property alias ratingView: ratingView + width: parent.width + height: parent.height + + ScrollView { + id:scrollView + flickableItem.interactive: true + anchors.fill: parent + anchors.margins: 15 + + GridLayout { + width: scrollView.width - 15 + rows: 7 + columns: 2 + + RowLayout { + Layout.columnSpan: 2 + Layout.fillWidth: true + + Image { + id: placeIcon + source: "../resources/marker.png" + anchors.margins: 30 + } + + Label { + id: placeName + text: qsTr("PlaceName") + font.bold: true + } + + Item { + Layout.fillWidth: true + } + } + + RatingView { + id: ratingView + size: placeName.height * 2 + Layout.columnSpan: 2 + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + Layout.columnSpan: 2 + height: 1 + color: "#46a2da" + visible: addressBox.visible + } + + GroupBox { + id: addressBox + Layout.fillWidth: true + Layout.columnSpan: 2 + flat: true + title: qsTr("Address") + + GridLayout { + id: gridLayout3 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + text: qsTr("Distance:") + } + + Label { + id: distance + Layout.fillWidth: true + text: qsTr("1000 km") + } + + Label { + id: address + Layout.columnSpan: 2 + text: qsTr("Street Number
xxxxx City
Country") + } + } + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + Layout.columnSpan: 2 + height: 1 + color: "#46a2da" + visible: categoriesBox.visible + } + + GroupBox { + id: categoriesBox + Layout.fillWidth: true + Layout.columnSpan: 2 + flat: true + title: qsTr("Categories") + + Label { + id: categories + anchors.fill: parent + text: qsTr("category1, category2 ,category3") + } + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: "#46a2da" + visible: contactDetailsBox.visible + } + + GroupBox { + id: contactDetailsBox + Layout.fillWidth: true + Layout.columnSpan: 2 + flat: true + title: qsTr("Contact details") + GridLayout { + id: gridLayout4 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + text: qsTr("Phone: ") + } + + Label { + id: phone + Layout.fillWidth: true + text: qsTr("000-000-000") + } + + Label { + text: qsTr("Fax: ") + } + + Label { + id: fax + Layout.fillWidth: true + text: qsTr("000-000-000") + } + + Label { + text: qsTr("Email: ") + } + + Label { + id: email + Layout.fillWidth: true + text: qsTr("name@company.com") + } + + Label { + text: qsTr("Website: ") + } + + Label { + id: website + Layout.fillWidth: true + text: qsTr("http:://company.com") + } + } + } + + Rectangle { + Layout.columnSpan: 2 + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: "#46a2da" + visible: informationBox.visible + } + + GroupBox { + id: informationBox + Layout.fillWidth: true + Layout.columnSpan: 2 + flat: true + title: qsTr("Additional information") + ColumnLayout { + Label { + id: addInformation + text: qsTr("AdditionalInformation1
AdditionalInformation2
AdditionalInformation3") + } + } + } + + RowLayout { + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignHCenter + + Button { + id: editorialsButton + text: qsTr("Editorials") + enabled: false + } + + Button { + id: reviewsButton + text: qsTr("Reviews") + enabled: false + } + + Button { + id: imagesButton + text: qsTr("Images") + enabled: false + } + + Button { + id: findSimilarButton + text: qsTr("Find similar") + enabled: false + } + } + } + } +} + diff --git a/examples/location/places/forms/SearchBoundingBox.qml b/examples/location/places/forms/SearchBoundingBox.qml new file mode 100644 index 0000000..10c2863 --- /dev/null +++ b/examples/location/places/forms/SearchBoundingBox.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtPositioning 5.5 + +SearchBoundingBoxForm { + property variant searchRegion + signal changeSearchBoundingBox(variant coordinate, real widthDeg, real heightDeg) + signal closeForm() + + goButton.onClicked: { + var coordinate = QtPositioning.coordinate(parseFloat(latitude.text), + parseFloat(longitude.text)); + if (coordinate.isValid) + changeSearchBoundingBox(coordinate,parseFloat(widthDeg.text),parseFloat(heightDeg.text)) + } + + clearButton.onClicked: { + latitude.text = "" + longitude.text = "" + widthDeg.text = "" + heightDeg.text = "" + } + + cancelButton.onClicked: closeForm() + + Component.onCompleted: { + latitude.text = "" + searchRegion.center.latitude + longitude.text = "" + searchRegion.center.longitude + widthDeg.text = searchRegion.width ? "" + searchRegion.width : "0.0" + heightDeg.text = searchRegion.height ? "" + searchRegion.height: "0.0" + } +} diff --git a/examples/location/places/forms/SearchBoundingBoxForm.ui.qml b/examples/location/places/forms/SearchBoundingBoxForm.ui.qml new file mode 100644 index 0000000..4bae3d6 --- /dev/null +++ b/examples/location/places/forms/SearchBoundingBoxForm.ui.qml @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + property alias clearButton: clearButton + property alias goButton: goButton + property alias longitude: longitude + property alias latitude: latitude + property alias widthDeg: widthDeg + property alias heightDeg: heightDeg + property alias cancelButton: cancelButton + property alias tabTitle: tabTitle + Rectangle { + id: tabRectangle + y: 20 + height: tabTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: qsTr("Search Bounding Box") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + id: item2 + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + GridLayout { + id: gridLayout3 + anchors.rightMargin: 0 + anchors.bottomMargin: 0 + anchors.leftMargin: 0 + anchors.topMargin: 0 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + id: label2 + text: qsTr("Latitude") + } + + TextField { + id: latitude + Layout.fillWidth: true + } + + Label { + id: label3 + text: qsTr("Longitude") + } + + TextField { + id: longitude + Layout.fillWidth: true + placeholderText: qsTr("") + } + + Label { + id: label4 + text: qsTr("Width (deg)") + } + + TextField { + id: widthDeg + Layout.fillWidth: true + } + + Label { + id: label5 + text: qsTr("Height (deg)") + } + + TextField { + id: heightDeg + Layout.fillWidth: true + placeholderText: qsTr("") + } + + RowLayout { + id: rowLayout1 + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignRight + + Button { + id: goButton + text: qsTr("Set") + } + + Button { + id: clearButton + text: qsTr("Clear") + } + + Button { + id: cancelButton + text: qsTr("Cancel") + } + } + Item { + Layout.fillHeight: true + Layout.columnSpan: 2 + } + } + } +} diff --git a/examples/location/places/forms/SearchBoundingCircle.qml b/examples/location/places/forms/SearchBoundingCircle.qml new file mode 100644 index 0000000..ce6212a --- /dev/null +++ b/examples/location/places/forms/SearchBoundingCircle.qml @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtPositioning 5.5 + +SearchBoundingCircleForm { + property variant searchRegion + signal changeSearchBoundingCircle(variant coordinate, real radius) + signal closeForm() + + goButton.onClicked: { + var coordinate = QtPositioning.coordinate(parseFloat(latitude.text), + parseFloat(longitude.text)); + if (coordinate.isValid) + changeSearchBoundingCircle(coordinate,parseFloat(radius.text)) + } + + clearButton.onClicked: { + latitude.text = "" + longitude.text = "" + radius.text = "" + } + + cancelButton.onClicked: closeForm() + + Component.onCompleted: { + latitude.text = "" + searchRegion.center.latitude + longitude.text = "" + searchRegion.center.longitude + radius.text = searchRegion.radius ? "" + searchRegion.radius : "0.0" + } +} diff --git a/examples/location/places/forms/SearchBoundingCircleForm.ui.qml b/examples/location/places/forms/SearchBoundingCircleForm.ui.qml new file mode 100644 index 0000000..9bfd996 --- /dev/null +++ b/examples/location/places/forms/SearchBoundingCircleForm.ui.qml @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + property alias clearButton: clearButton + property alias goButton: goButton + property alias longitude: longitude + property alias latitude: latitude + property alias radius: radius + property alias cancelButton: cancelButton + property alias tabTitle: tabTitle + Rectangle { + id: tabRectangle + y: 20 + height: tabTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: qsTr("Search Bounding Circle") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + id: item2 + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + GridLayout { + id: gridLayout3 + anchors.rightMargin: 0 + anchors.bottomMargin: 0 + anchors.leftMargin: 0 + anchors.topMargin: 0 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + id: label2 + text: qsTr("Latitude") + } + + TextField { + id: latitude + Layout.fillWidth: true + } + + Label { + id: label3 + text: qsTr("Longitude") + } + + TextField { + id: longitude + Layout.fillWidth: true + placeholderText: qsTr("") + } + + Label { + id: label4 + text: qsTr("Radius (m)") + } + + TextField { + id: radius + Layout.fillWidth: true + } + + RowLayout { + id: rowLayout1 + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignRight + + Button { + id: goButton + text: qsTr("Set") + } + + Button { + id: clearButton + text: qsTr("Clear") + } + + Button { + id: cancelButton + text: qsTr("Cancel") + } + } + Item { + Layout.fillHeight: true + Layout.columnSpan: 2 + } + } + } +} diff --git a/examples/location/places/forms/SearchCenter.qml b/examples/location/places/forms/SearchCenter.qml new file mode 100644 index 0000000..b8fbda6 --- /dev/null +++ b/examples/location/places/forms/SearchCenter.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtPositioning 5.5 + +SearchCenterForm { + property string title; + property variant coordinate + signal changeSearchCenter(variant coordinate) + signal closeForm() + + goButton.onClicked: { + var coordinate = QtPositioning.coordinate(parseFloat(latitude.text), + parseFloat(longitude.text)); + if (coordinate.isValid) + changeSearchCenter(coordinate) + } + + clearButton.onClicked: { + latitude.text = "" + longitude.text = "" + } + + cancelButton.onClicked: closeForm() + + Component.onCompleted: { + latitude.text = "" + coordinate.latitude + longitude.text = "" + coordinate.longitude + if (title.length != 0) + tabTitle.text = title; + } +} diff --git a/examples/location/places/forms/SearchCenterForm.ui.qml b/examples/location/places/forms/SearchCenterForm.ui.qml new file mode 100644 index 0000000..f303b07 --- /dev/null +++ b/examples/location/places/forms/SearchCenterForm.ui.qml @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + property alias clearButton: clearButton + property alias goButton: goButton + property alias longitude: longitude + property alias latitude: latitude + property alias cancelButton: cancelButton + property alias tabTitle: tabTitle + Rectangle { + id: tabRectangle + y: 20 + height: tabTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: qsTr("Search Center") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + id: item2 + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + GridLayout { + id: gridLayout3 + anchors.rightMargin: 0 + anchors.bottomMargin: 0 + anchors.leftMargin: 0 + anchors.topMargin: 0 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + id: label2 + text: qsTr("Latitude") + } + + TextField { + id: latitude + Layout.fillWidth: true + } + + Label { + id: label3 + text: qsTr("Longitude") + } + + TextField { + id: longitude + Layout.fillWidth: true + placeholderText: qsTr("") + } + + RowLayout { + id: rowLayout1 + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignRight + + Button { + id: goButton + text: qsTr("Set") + } + + Button { + id: clearButton + text: qsTr("Clear") + } + + Button { + id: cancelButton + text: qsTr("Cancel") + } + } + Item { + Layout.fillHeight: true + Layout.columnSpan: 2 + } + } + } +} diff --git a/examples/location/places/forms/SearchOptions.qml b/examples/location/places/forms/SearchOptions.qml new file mode 100644 index 0000000..4411539 --- /dev/null +++ b/examples/location/places/forms/SearchOptions.qml @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtPositioning 5.5 + +SearchOptionsForm { + id: root + property Plugin plugin + property PlaceSearchModel model + + signal changeSearchSettings(bool orderByDistance, + bool orderByName, + string locales) + signal closeForm() + + setButton.onClicked: changeSearchSettings(distanceOrderButton.checked, + nameOrderButton.checked, + locales.text) + + clearButton.onClicked: { + locales.text = "" + distanceOrderButton.checked = false + nameOrderButton.checked = false + } + + cancelButton.onClicked: { + closeForm() + } + + Component.onCompleted: { + locales.visible = root.plugin != null && root.plugin.supportsPlaces(Plugin.LocalizedPlacesFeature); + favoritesButton.visible = false; +// favoritesButton.enabled = placeSearchModel.favoritesPlugin !== null) +// isFavoritesEnabled = true; + locales.text = root.plugin.locales.join(Qt.locale().groupSeparator); + distanceOrderButton.checked = model.relevanceHint == PlaceSearchModel.DistanceHint + nameOrderButton.checked = model.relevanceHint == PlaceSearchModel.LexicalPlaceNameHint + } +} diff --git a/examples/location/places/forms/SearchOptionsForm.ui.qml b/examples/location/places/forms/SearchOptionsForm.ui.qml new file mode 100644 index 0000000..945a389 --- /dev/null +++ b/examples/location/places/forms/SearchOptionsForm.ui.qml @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + property alias clearButton: clearButton + property alias setButton: setButton + property alias cancelButton: cancelButton + property alias tabTitle: tabTitle + property alias orderGroup: orderGroup + property alias distanceOrderButton: distanceOrderButton + property alias nameOrderButton: nameOrderButton + property alias favoritesButton: favoritesButton + property alias locales: locales + + Rectangle { + id: tabRectangle + y: 20 + height: tabTitle.height * 2 + color: "#46a2da" + anchors.rightMargin: 0 + anchors.leftMargin: 0 + anchors.left: parent.left + anchors.right: parent.right + + Label { + id: tabTitle + color: "#ffffff" + text: qsTr("Search Options") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Item { + id: item2 + anchors.rightMargin: 20 + anchors.leftMargin: 20 + anchors.bottomMargin: 20 + anchors.topMargin: 20 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.top: tabRectangle.bottom + + GridLayout { + id: gridLayout3 + anchors.rightMargin: 0 + anchors.bottomMargin: 0 + anchors.leftMargin: 0 + anchors.topMargin: 0 + rowSpacing: 10 + rows: 1 + columns: 2 + anchors.fill: parent + + Label { + id: label + text: qsTr("Locale(s)") + visible: locales.visible + } + + TextField { + id: locales + Layout.fillWidth: true + placeholderText: qsTr("") + } + + RadioButton { + id: favoritesButton + text: qsTr("Enable favorites") + Layout.columnSpan: 2 + } + + ExclusiveGroup { id: orderGroup } + RadioButton { + id: distanceOrderButton + text: qsTr("Order by distance") + exclusiveGroup: orderGroup + Layout.columnSpan: 2 + } + + RadioButton { + id: nameOrderButton + text: qsTr("Order by name") + exclusiveGroup: orderGroup + Layout.columnSpan: 2 + } + + RowLayout { + id: rowLayout1 + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignRight + + Button { + id: setButton + text: qsTr("Set") + } + + Button { + id: clearButton + text: qsTr("Clear") + } + + Button { + id: cancelButton + text: qsTr("Cancel") + } + } + + Item { + Layout.fillHeight: true + Layout.columnSpan: 2 + } + + + } + } +} diff --git a/examples/location/places/helper.js b/examples/location/places/helper.js new file mode 100644 index 0000000..5b09022 --- /dev/null +++ b/examples/location/places/helper.js @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library + +function formatDistance(distance) +{ + if (distance < 1000) + return distance.toFixed(0) + " m"; + + var km = distance/1000; + if (km < 10) + return km.toFixed(1) + " km"; + + return km.toFixed(0) + " km"; +} diff --git a/examples/location/places/items/MainMenu.qml b/examples/location/places/items/MainMenu.qml new file mode 100644 index 0000000..9785c18 --- /dev/null +++ b/examples/location/places/items/MainMenu.qml @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtLocation 5.6 + +MenuBar { + property variant providerMenu: providerMenu + property variant settingsMenu: settingsMenu + + signal selectProvider(string providerName) + signal selectSetting(string setting); + + + + Menu { + id: providerMenu + title: qsTr("Provider") + + function createMenu(plugins) + { + clear() + for (var i = 0; i < plugins.length; i++) { + createProviderMenuItem(plugins[i]); + } + } + + function createProviderMenuItem(provider) + { + var item = addItem(provider); + item.checkable = true; + item.triggered.connect(function(){selectProvider(provider)}) + } + } + + Menu { + id: settingsMenu + title: qsTr("Settings") + + function createMenu(map) + { + clear() + var item = addItem(qsTr("Search Center")); + item.triggered.connect(function(){selectSetting("searchCenter")}) + item = addItem(qsTr("Search Bounding Box")); + item.triggered.connect(function(){selectSetting("searchBoundingBox")}) + item = addItem(qsTr("Search Bounding Circle")); + item.triggered.connect(function(){selectSetting("searchBoundingCircle")}) + item = addItem(qsTr("Search Options")); + item.triggered.connect(function(){selectSetting("SearchOptions")}) + } + } +} diff --git a/examples/location/places/items/MapComponent.qml b/examples/location/places/items/MapComponent.qml new file mode 100644 index 0000000..0be555d --- /dev/null +++ b/examples/location/places/items/MapComponent.qml @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtPositioning 5.5 +import QtLocation 5.6 +import "../helper.js" as Helper + +Map { + id: map + property bool followme: false + property variant scaleLengths: [5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000, 2000000] + + function calculateScale() + { + var coord1, coord2, dist, text, f + f = 0 + coord1 = map.toCoordinate(Qt.point(0,scale.y)) + coord2 = map.toCoordinate(Qt.point(0+scaleImage.sourceSize.width,scale.y)) + dist = Math.round(coord1.distanceTo(coord2)) + + if (dist === 0) { + // not visible + } else { + for (var i = 0; i < scaleLengths.length-1; i++) { + if (dist < (scaleLengths[i] + scaleLengths[i+1]) / 2 ) { + f = scaleLengths[i] / dist + dist = scaleLengths[i] + break; + } + } + if (f === 0) { + f = dist / scaleLengths[i] + dist = scaleLengths[i] + } + } + + text = Helper.formatDistance(dist) + scaleImage.width = (scaleImage.sourceSize.width * f) - 2 * scaleImageLeft.sourceSize.width + scaleText.text = text + } + + center { + // The Qt Company in Oslo + latitude: 59.9485 + longitude: 10.7686 + } + + gesture.flickDeceleration: 3000 + gesture.enabled: true + onCopyrightLinkActivated: Qt.openUrlExternally(link) + + onCenterChanged:{ + scaleTimer.restart() + if (map.followme) + if (map.center != positionSource.position.coordinate) map.followme = false + } + + onZoomLevelChanged:{ + scaleTimer.restart() + if (map.followme) map.center = positionSource.position.coordinate + } + + onWidthChanged:{ + scaleTimer.restart() + } + + onHeightChanged:{ + scaleTimer.restart() + } + + Keys.onPressed: { + if (event.key === Qt.Key_Plus) { + map.zoomLevel++ + } else if (event.key === Qt.Key_Minus) { + map.zoomLevel-- + } + } + + Timer { + id: scaleTimer + interval: 100 + running: false + repeat: false + onTriggered: { + map.calculateScale() + } + } + + Item { + id: scale + visible: scaleText.text != "0 m" + z: map.z + 3 + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.margins: 20 + height: scaleText.height * 2 + width: scaleImage.width + + Image { + id: scaleImageLeft + source: "../../resources/scale_end.png" + anchors.bottom: parent.bottom + anchors.right: scaleImage.left + } + Image { + id: scaleImage + source: "../../resources/scale.png" + anchors.bottom: parent.bottom + anchors.right: scaleImageRight.left + } + Image { + id: scaleImageRight + source: "../../resources/scale_end.png" + anchors.bottom: parent.bottom + anchors.right: parent.right + } + Label { + id: scaleText + color: "#004EAE" + anchors.centerIn: parent + text: "0 m" + } + Component.onCompleted: { + map.calculateScale(); + } + } + + MapQuickItem { + id: poiTheQtComapny + sourceItem: Rectangle { width: 14; height: 14; color: "#e41e25"; border.width: 2; border.color: "white"; smooth: true; radius: 7 } + coordinate { + latitude: 59.9485 + longitude: 10.7686 + } + opacity:1.0 + anchorPoint: Qt.point(sourceItem.width/2, sourceItem.height/2) + } + + MapQuickItem { + sourceItem: Text{ + text: "The Qt Company" + color:"#242424" + font.bold: true + styleColor: "#ECECEC" + style: Text.Outline + } + coordinate: poiTheQtComapny.coordinate + anchorPoint: Qt.point(-poiTheQtComapny.sourceItem.width * 0.5,poiTheQtComapny.sourceItem.height * 1.5) + } + + PositionSource{ + id: positionSource + active: followme + + onPositionChanged: { + map.center = positionSource.position.coordinate + } + } + + Slider { + id: zoomSlider; + z: map.z + 3 + minimumValue: map.minimumZoomLevel; + maximumValue: map.maximumZoomLevel; + anchors.margins: 10 + anchors.bottom: scale.top + anchors.top: parent.top + anchors.right: parent.right + orientation : Qt.Vertical + value: map.zoomLevel + onValueChanged: { + map.zoomLevel = value + } + } +} diff --git a/examples/location/places/items/SearchBar.qml b/examples/location/places/items/SearchBar.qml new file mode 100644 index 0000000..e5a3b33 --- /dev/null +++ b/examples/location/places/items/SearchBar.qml @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +ToolBar { + + property bool busyIndicatorRunning : false + property bool searchBarVisbile: true + + signal doSearch(string searchText) + signal searchTextChanged(string searchText) + signal showCategories() + signal goBack() + signal showMap() + + onSearchBarVisbileChanged: { + searchBar.opacity = searchBarVisbile ? 1 : 0 + backBar.opacity = searchBarVisbile ? 0 : 1 + } + + function showSearch(text) { + if (text != null) { + searchText.ignoreTextChange = true + searchText.text = text + searchText.ignoreTextChange = false + } + } + + RowLayout { + id: searchBar + width: parent.width + height: parent.height + Behavior on opacity { NumberAnimation{} } + visible: opacity ? true : false + TextField { + id: searchText + Behavior on opacity { NumberAnimation{} } + visible: opacity ? true : false + property bool ignoreTextChange: false + placeholderText: qsTr("Type place...") + Layout.fillWidth: true + onTextChanged: { + if (!ignoreTextChange) + searchTextChanged(text) + } + onAccepted: doSearch(searchText.text) + } + ToolButton { + id: searchButton + iconSource: "../../resources/search.png" + onClicked: doSearch(searchText.text) + } + ToolButton { + id: categoryButton + iconSource: "../../resources/categories.png" + onClicked: showCategories() + } + } + + RowLayout { + id: backBar + width: parent.width + height: parent.height + opacity: 0 + Behavior on opacity { NumberAnimation{} } + visible: opacity ? true : false + ToolButton { + id: backButton + iconSource: "../../resources/left.png" + onClicked: goBack() + } + ToolButton { + id: mapButton + iconSource: "../../resources/search.png" + onClicked: showMap() + } + Item { + Layout.fillWidth: true + } + } +} + diff --git a/examples/location/places/main.cpp b/examples/location/places/main.cpp new file mode 100644 index 0000000..8c3b64e --- /dev/null +++ b/examples/location/places/main.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +static bool parseArgs(QStringList& args, QVariantMap& parameters) +{ + + while (!args.isEmpty()) { + + QString param = args.takeFirst(); + + if (param.startsWith("--help")) { + QTextStream out(stdout); + out << "Usage: " << endl; + out << "--plugin. - Sets parameter = value for plugin" << endl; + out.flush(); + return true; + } + + if (param.startsWith("--plugin.")) { + + param.remove(0, 9); + + if (args.isEmpty() || args.first().startsWith("--")) { + parameters[param] = true; + } else { + + QString value = args.takeFirst(); + + if (value == "true" || value == "on" || value == "enabled") { + parameters[param] = true; + } else if (value == "false" || value == "off" + || value == "disable") { + parameters[param] = false; + } else { + parameters[param] = value; + } + } + } + } + return false; +} + +int main(int argc, char *argv[]) +{ + QGuiApplication application(argc, argv); + + QVariantMap parameters; + QStringList args(QCoreApplication::arguments()); + + if (parseArgs(args, parameters)) + return 0; + + QQmlApplicationEngine engine; + engine.addImportPath(QStringLiteral(":/imports")); + engine.load(QUrl(QStringLiteral("qrc:///places.qml"))); + QObject::connect(&engine, SIGNAL(quit()), qApp, SLOT(quit())); + + QObject *item = engine.rootObjects().first(); + Q_ASSERT(item); + + QMetaObject::invokeMethod(item, "initializeProviders", + Q_ARG(QVariant, QVariant::fromValue(parameters))); + + return application.exec(); +} diff --git a/examples/location/places/places.pro b/examples/location/places/places.pro new file mode 100644 index 0000000..baeef40 --- /dev/null +++ b/examples/location/places/places.pro @@ -0,0 +1,44 @@ +TARGET = qml_location_places +TEMPLATE = app + +QT += qml quick network positioning location +SOURCES += main.cpp + +RESOURCES += \ + places.qrc + +OTHER_FILES += \ + places.qml \ + helper.js \ + items/MainMenu.qml \ + items/SearchBar.qml \ + items/MapComponent.qml \ + forms/Message.qml \ + forms/MessageForm.ui.qml \ + forms/SearchCenter.qml \ + forms/SearchCenterForm.ui.qml \ + forms/SearchBoundingBox.qml \ + forms/SearchBoundingBoxForm.ui.qml \ + forms/SearchBoundingCircle.qml \ + forms/SearchBoundingCircleForm.ui.qml \ + forms/PlaceDetails.qml \ + forms/PlaceDetailsForm.ui.qml \ + forms/SearchOptions.qml \ + forms/SearchOptionsForm.ui.qml \ + views/SuggestionView.qml \ + views/RatingView.qml \ + views/CategoryView.qml \ + views/CategoryDelegate.qml \ + views/SearchResultDelegate.qml \ + views/SearchResultView.qml \ + views/EditorialView.qml \ + views/EditorialDelegate.qml \ + views/EditorialPage.qml \ + views/ReviewView.qml \ + views/ReviewDelegate.qml \ + views/ReviewPage.qml \ + views/ImageView.qml + +target.path = $$[QT_INSTALL_EXAMPLES]/location/places +INSTALLS += target + diff --git a/examples/location/places/places.qml b/examples/location/places/places.qml new file mode 100644 index 0000000..0141fbb --- /dev/null +++ b/examples/location/places/places.qml @@ -0,0 +1,497 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 +import QtPositioning 5.5 +import QtLocation 5.6 +import "items" + +ApplicationWindow { + id: appWindow + property Map map + property variant parameters + property variant searchLocation: map ? map.center : QtPositioning.coordinate() + property variant searchRegion: QtPositioning.circle(searchLocation) + property variant searchRegionItem + + property Plugin favoritesPlugin + + function getPlugins() { + var plugin = Qt.createQmlObject('import QtLocation 5.3; Plugin {}', appWindow); + var myArray = new Array; + for (var i = 0; i < plugin.availableServiceProviders.length; i++) { + var tempPlugin = Qt.createQmlObject ('import QtLocation 5.3; Plugin {name: "' + plugin.availableServiceProviders[i]+ '"}', appWindow) + + if (tempPlugin.supportsPlaces() && tempPlugin.supportsMapping() ) + myArray.push(tempPlugin.name) + } + myArray.sort() + return myArray; + } + + function initializeProviders(pluginParameters) + { + var parameters = new Array() + for (var prop in pluginParameters) { + var parameter = Qt.createQmlObject('import QtLocation 5.3; PluginParameter{ name: "'+ prop + '"; value: "' + pluginParameters[prop]+'"}',appWindow) + parameters.push(parameter) + } + appWindow.parameters = parameters + var plugins = getPlugins() + mainMenu.providerMenu.createMenu(plugins) + for (var i = 0; i0) + plugin = Qt.createQmlObject ('import QtLocation 5.3; Plugin{ name:"' + provider + '"; parameters: appWindow.parameters}', appWindow) + else + plugin = Qt.createQmlObject ('import QtLocation 5.3; Plugin{ name:"' + provider + '"}', appWindow) + + if (map) + map.destroy(); + map = mapComponent.createObject(page); + map.plugin = plugin; + map.zoomLevel = (map.maximumZoomLevel - map.minimumZoomLevel)/2 + categoryModel.plugin = plugin; + categoryModel.update(); + placeSearchModel.plugin = plugin; + suggestionModel.plugin = plugin; + } + + title: qsTr("Places") + width: 360 + height: 640 + visible: true + menuBar: mainMenu + toolBar: searchBar + + MainMenu { + id: mainMenu + onSelectProvider: { + stackView.pop(page) + for (var i = 0; i < providerMenu.items.length; i++) { + providerMenu.items[i].checked = providerMenu.items[i].text === providerName + } + + createMap(providerName) + if (map.error === Map.NoError) { + settingsMenu.createMenu(map); + } else { + settingsMenu.clear(); + } + } + onSelectSetting: { + stackView.pop({tem:page,immediate: true}) + switch (setting) { + case "searchCenter": + stackView.push({ item: Qt.resolvedUrl("forms/SearchCenter.qml") , + properties: { "coordinate": map.center}}) + stackView.currentItem.changeSearchCenter.connect(stackView.changeSearchCenter) + stackView.currentItem.closeForm.connect(stackView.closeForm) + break + case "searchBoundingBox": + stackView.push({ item: Qt.resolvedUrl("forms/SearchBoundingBox.qml") , + properties: { "searchRegion": searchRegion}}) + stackView.currentItem.changeSearchBoundingBox.connect(stackView.changeSearchBoundingBox) + stackView.currentItem.closeForm.connect(stackView.closeForm) + break + case "searchBoundingCircle": + stackView.push({ item: Qt.resolvedUrl("forms/SearchBoundingCircle.qml") , + properties: { "searchRegion": searchRegion}}) + stackView.currentItem.changeSearchBoundingCircle.connect(stackView.changeSearchBoundingCircle) + stackView.currentItem.closeForm.connect(stackView.closeForm) + break + case "SearchOptions": + stackView.push({ item: Qt.resolvedUrl("forms/SearchOptions.qml") , + properties: { "plugin": map.plugin, + "model": placeSearchModel}}) + stackView.currentItem.changeSearchSettings.connect(stackView.changeSearchSettings) + stackView.currentItem.closeForm.connect(stackView.closeForm) + break + default: + console.log("Unsupported setting !") + } + } + } + + //! [PlaceSearchSuggestionModel search text changed 1] + SearchBar { + id: searchBar + //! [PlaceSearchSuggestionModel search text changed 1] + width: appWindow.width + searchBarVisbile: stackView.depth > 1 && + stackView.currentItem && + stackView.currentItem.objectName != "suggestionView" ? false : true + onShowCategories: { + if (map && map.plugin) { + stackView.pop({tem:page,immediate: true}) + stackView.enterCategory() + } + } + onGoBack: stackView.pop() + //! [PlaceSearchSuggestionModel search text changed 2] + onSearchTextChanged: { + if (searchText.length >= 3 && suggestionModel != null) { + suggestionModel.searchTerm = searchText; + suggestionModel.update(); + } + } + //! [PlaceSearchSuggestionModel search text changed 2] + onDoSearch: { + if (searchText.length > 0) + placeSearchModel.searchForText(searchText); + } + onShowMap: stackView.pop(page) + //! [PlaceSearchSuggestionModel search text changed 3] + } + //! [PlaceSearchSuggestionModel search text changed 3] + + StackView { + id: stackView + + function showMessage(title,message,backPage) + { + push({ item: Qt.resolvedUrl("forms/Message.qml") , + properties: { + "title" : title, + "message" : message, + "backPage" : backPage + }}) + currentItem.closeForm.connect(closeMessage) + } + + function closeMessage(backPage) + { + pop(backPage) + } + + function closeForm() + { + pop(page) + } + + function enterCategory(index) + { + push({ item: Qt.resolvedUrl("views/CategoryView.qml") , + properties: { "categoryModel": categoryModel, + "rootIndex" : index + }}) + currentItem.showSubcategories.connect(stackView.enterCategory) + currentItem.searchCategory.connect(placeSearchModel.searchForCategory) + } + + function showSuggestions() + { + if (currentItem.objectName != "suggestionView") { + stackView.pop(page) + push({ item: Qt.resolvedUrl("views/SuggestionView.qml") , + properties: { "suggestionModel": suggestionModel } + }) + currentItem.objectName = "suggestionView" + currentItem.suggestionSelected.connect(searchBar.showSearch) + currentItem.suggestionSelected.connect(placeSearchModel.searchForText) + } + } + + function showPlaces() + { + if (currentItem.objectName != "searchResultView") { + stackView.pop({tem:page,immediate: true}) + push({ item: Qt.resolvedUrl("views/SearchResultView.qml") , + properties: { "placeSearchModel": placeSearchModel } + }) + currentItem.showPlaceDetails.connect(showPlaceDatails) + currentItem.showMap.connect(searchBar.showMap) + currentItem.objectName = "searchResultView" + } + } + + function showPlaceDatails(place, distance) + { + push({ item: Qt.resolvedUrl("forms/PlaceDetails.qml") , + properties: { "place": place, + "distanceToPlace": distance } + }) + currentItem.searchForSimilar.connect(searchForSimilar) + currentItem.showReviews.connect(showReviews) + currentItem.showEditorials.connect(showEditorials) + currentItem.showImages.connect(showImages) + } + + function showEditorials(place) + { + push({ item: Qt.resolvedUrl("views/EditorialView.qml") , + properties: { "place": place } + }) + currentItem.showEditorial.connect(showEditorial) + } + + function showReviews(place) + { + push({ item: Qt.resolvedUrl("views/ReviewView.qml") , + properties: { "place": place } + }) + currentItem.showReview.connect(showReview) + } + + function showImages(place) + { + push({ item: Qt.resolvedUrl("views/ImageView.qml") , + properties: { "place": place } + }) + } + + function showEditorial(editorial) + { + push({ item: Qt.resolvedUrl("views/EditorialPage.qml") , + properties: { "editorial": editorial } + }) + } + + function showReview(review) + { + push({ item: Qt.resolvedUrl("views/ReviewPage.qml") , + properties: { "review": review } + }) + } + + function changeSearchCenter(coordinate) + { + stackView.pop(page) + map.center = coordinate; + if (searchRegionItem) { + map.removeMapItem(searchRegionItem); + searchRegionItem.destroy(); + } + } + + function changeSearchBoundingBox(coordinate,widthDeg,heightDeg) + { + stackView.pop(page) + map.center = coordinate + searchRegion = QtPositioning.rectangle(map.center, widthDeg, heightDeg) + if (searchRegionItem) { + map.removeMapItem(searchRegionItem); + searchRegionItem.destroy(); + } + searchRegionItem = Qt.createQmlObject('import QtLocation 5.3; MapRectangle { color: "#46a2da"; border.color: "#190a33"; border.width: 2; opacity: 0.25 }', page, "MapRectangle"); + searchRegionItem.topLeft = searchRegion.topLeft; + searchRegionItem.bottomRight = searchRegion.bottomRight; + map.addMapItem(searchRegionItem); + } + + function changeSearchBoundingCircle(coordinate,radius) + { + stackView.pop(page) + map.center = coordinate; + searchRegion = QtPositioning.circle(coordinate, radius) + + if (searchRegionItem) { + map.removeMapItem(searchRegionItem); + searchRegionItem.destroy(); + } + searchRegionItem = Qt.createQmlObject('import QtLocation 5.3; MapCircle { color: "#46a2da"; border.color: "#190a33"; border.width: 2; opacity: 0.25 }', page, "MapRectangle"); + searchRegionItem.center = searchRegion.center; + searchRegionItem.radius = searchRegion.radius; + map.addMapItem(searchRegionItem); + } + + function changeSearchSettings(orderByDistance, orderByName, locales) + { + stackView.pop(page) + /*if (isFavoritesEnabled) { + if (favoritesPlugin == null) + favoritesPlugin = Qt.createQmlObject('import QtLocation 5.3; Plugin { name: "places_jsondb" }', page); + favoritesPlugin.parameters = pluginParametersFromMap(pluginParameters); + placeSearchModel.favoritesPlugin = favoritesPlugin; + } else { + placeSearchModel.favoritesPlugin = null; + }*/ + placeSearchModel.favoritesPlugin = null; + + placeSearchModel.relevanceHint = orderByDistance ? PlaceSearchModel.DistanceHint : + orderByName ? PlaceSearchModel.LexicalPlaceNameHint : + PlaceSearchModel.UnspecifiedHint; + map.plugin.locales = locales.split(Qt.locale().groupSeparator); + } + + //! [PlaceRecommendationModel search] + function searchForSimilar(place) { + stackView.pop(page) + searchBar.showSearch(place.name) + placeSearchModel.searchForRecommendations(place.placeId); + } + //! [PlaceRecommendationModel search] + + anchors.fill: parent + focus: true + initialItem: Item { + id: page + + //! [PlaceSearchModel model] + PlaceSearchModel { + id: placeSearchModel + searchArea: searchRegion + + function searchForCategory(category) { + searchTerm = ""; + categories = category; + recommendationId = ""; + searchArea = searchRegion + limit = -1; + update(); + } + + function searchForText(text) { + searchTerm = text; + categories = null; + recommendationId = ""; + searchArea = searchRegion + limit = -1; + update(); + } + + function searchForRecommendations(placeId) { + searchTerm = ""; + categories = null; + recommendationId = placeId; + searchArea = null; + limit = -1; + update(); + } + + onStatusChanged: { + switch (status) { + case PlaceSearchModel.Ready: + if (count > 0) + stackView.showPlaces() + else + stackView.showMessage(qsTr("Search Place Error"),qsTr("Place not found !")) + break; + case PlaceSearchModel.Error: + stackView.showMessage(qsTr("Search Place Error"),errorString()) + break; + } + } + } + //! [PlaceSearchModel model] + + //! [PlaceSearchSuggestionModel model] + PlaceSearchSuggestionModel { + id: suggestionModel + searchArea: searchRegion + + onStatusChanged: { + if (status == PlaceSearchSuggestionModel.Ready) + stackView.showSuggestions() + } + } + //! [PlaceSearchSuggestionModel model] + + //! [CategoryModel model] + CategoryModel { + id: categoryModel + hierarchical: true + } + //! [CategoryModel model] + + Component { + id: mapComponent + + MapComponent { + width: page.width + height: page.height + + onErrorChanged: { + if (map.error != Map.NoError) { + var title = qsTr("ProviderError"); + var message = map.errorString + "

" + qsTr("Try to select other provider") + ""; + if (map.error == Map.MissingRequiredParameterError) + message += "
" + qsTr("or see") + " \'mapviewer --help\' " + + qsTr("how to pass plugin parameters."); + stackView.showMessage(title,message); + } + } + + MapItemView { + model: placeSearchModel + delegate: MapQuickItem { + coordinate: model.type === PlaceSearchModel.PlaceResult ? place.location.coordinate : QtPositioning.coordinate() + + visible: model.type === PlaceSearchModel.PlaceResult + + anchorPoint.x: image.width * 0.28 + anchorPoint.y: image.height + + sourceItem: Image { + id: image + source: "resources/marker.png" + MouseArea { + anchors.fill: parent + onClicked: stackView.showPlaceDatails(model.place,model.distance) + } + } + } + } + } + } + } + } + + Rectangle { + color: "white" + opacity: busyIndicator.running ? 0.8 : 0 + anchors.fill: parent + Behavior on opacity { NumberAnimation{} } + } + BusyIndicator { + id: busyIndicator + anchors.centerIn: parent + running: placeSearchModel.status == PlaceSearchModel.Loading || + categoryModel.status === CategoryModel.Loading + } +} diff --git a/examples/location/places/places.qrc b/examples/location/places/places.qrc new file mode 100644 index 0000000..42026a6 --- /dev/null +++ b/examples/location/places/places.qrc @@ -0,0 +1,42 @@ + + + places.qml + helper.js + items/MainMenu.qml + items/MapComponent.qml + items/SearchBar.qml + forms/Message.qml + forms/MessageForm.ui.qml + forms/SearchCenter.qml + forms/SearchCenterForm.ui.qml + forms/SearchBoundingBox.qml + forms/SearchBoundingBoxForm.ui.qml + forms/SearchBoundingCircle.qml + forms/SearchBoundingCircleForm.ui.qml + forms/SearchOptions.qml + forms/SearchOptionsForm.ui.qml + forms/PlaceDetails.qml + forms/PlaceDetailsForm.ui.qml + views/SuggestionView.qml + views/CategoryDelegate.qml + views/CategoryView.qml + views/EditorialDelegate.qml + views/EditorialPage.qml + views/EditorialView.qml + views/ImageView.qml + views/RatingView.qml + views/ReviewDelegate.qml + views/ReviewPage.qml + views/ReviewView.qml + views/SearchResultDelegate.qml + views/SearchResultView.qml + resources/categories.png + resources/left.png + resources/marker.png + resources/right.png + resources/scale.png + resources/scale_end.png + resources/search.png + resources/star.png + + diff --git a/examples/location/places/resources/categories.png b/examples/location/places/resources/categories.png new file mode 100644 index 0000000..b2d73ea Binary files /dev/null and b/examples/location/places/resources/categories.png differ diff --git a/examples/location/places/resources/left.png b/examples/location/places/resources/left.png new file mode 100644 index 0000000..8241a47 Binary files /dev/null and b/examples/location/places/resources/left.png differ diff --git a/examples/location/places/resources/marker.png b/examples/location/places/resources/marker.png new file mode 100644 index 0000000..2116dfd Binary files /dev/null and b/examples/location/places/resources/marker.png differ diff --git a/examples/location/places/resources/right.png b/examples/location/places/resources/right.png new file mode 100644 index 0000000..37a1b1d Binary files /dev/null and b/examples/location/places/resources/right.png differ diff --git a/examples/location/places/resources/scale.png b/examples/location/places/resources/scale.png new file mode 100644 index 0000000..c4f0812 Binary files /dev/null and b/examples/location/places/resources/scale.png differ diff --git a/examples/location/places/resources/scale_end.png b/examples/location/places/resources/scale_end.png new file mode 100644 index 0000000..94510b1 Binary files /dev/null and b/examples/location/places/resources/scale_end.png differ diff --git a/examples/location/places/resources/search.png b/examples/location/places/resources/search.png new file mode 100644 index 0000000..ce8c27a Binary files /dev/null and b/examples/location/places/resources/search.png differ diff --git a/examples/location/places/resources/star.png b/examples/location/places/resources/star.png new file mode 100644 index 0000000..cddc1e3 Binary files /dev/null and b/examples/location/places/resources/star.png differ diff --git a/examples/location/places/views/CategoryDelegate.qml b/examples/location/places/views/CategoryDelegate.qml new file mode 100644 index 0000000..d4562d4 --- /dev/null +++ b/examples/location/places/views/CategoryDelegate.qml @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtLocation 5.6 + +Item { + id: root + + property alias text: labelItem.text + property bool checked: false + signal searchCategory() + signal showSubcategories() + + width: parent.width + height: Math.max(icon.height, labelItem.height * 2) + + Image { + id: icon + anchors.left: parent.left + anchors.leftMargin: 30 + anchors.verticalCenter: parent.verticalCenter + source: category.icon.url() + } + + Rectangle { + anchors.fill: parent + color: "#44ffffff" + visible: mouse.pressed + } + + //! [CategoryModel delegate text] + Label { + id: labelItem + text: category.name + anchors.left: icon.right + anchors.verticalCenter: parent.verticalCenter + anchors.right: arrow.left + } + + MouseArea { + id: mouse + anchors.fill: parent + onClicked: root.searchCategory() + } + //! [CategoryModel delegate text] + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 15 + height: 1 + color: "#46a2da" + } + //! [CategoryModel delegate arrow] + ToolButton { + id: arrow + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.rightMargin: 15 + visible: model.hasModelChildren + iconSource: "../../resources/right.png" + onClicked: root.showSubcategories() + } + //! [CategoryModel delegate arrow] +} diff --git a/examples/location/places/views/CategoryView.qml b/examples/location/places/views/CategoryView.qml new file mode 100644 index 0000000..3cb83c7 --- /dev/null +++ b/examples/location/places/views/CategoryView.qml @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtQml.Models 2.1 + + +//! [CategoryModel view] +ListView { + id: root + property variant categoryModel + property variant rootIndex + + signal searchCategory(variant category) + signal showSubcategories(variant index) + + snapMode: ListView.SnapToItem + + model: DelegateModel { + id: delegeteDataModel + model: root.categoryModel + rootIndex: root.rootIndex + delegate: CategoryDelegate { + onSearchCategory: root.searchCategory(category); + onShowSubcategories: root.showSubcategories(delegeteDataModel.modelIndex(index)) + } + } +} +//! [CategoryModel view] diff --git a/examples/location/places/views/EditorialDelegate.qml b/examples/location/places/views/EditorialDelegate.qml new file mode 100644 index 0000000..82e544a --- /dev/null +++ b/examples/location/places/views/EditorialDelegate.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtQuick.Controls 1.4 + +Item { + id: root + signal showEditorial() + + width: parent.width + height: icon.height + 8 + + Image { + id: icon + + width: 64 + height: 64 + + anchors.verticalCenter: root.verticalCenter + anchors.left: root.left + anchors.leftMargin: 4 + + source: model.supplier.icon.url(Qt.size(64, 64), Icon.List) + fillMode: Image.PreserveAspectFit + } + + Label { + anchors.top: icon.top + anchors.topMargin: 4 + anchors.left: icon.right + anchors.leftMargin: 4 + anchors.right: root.right + anchors.rightMargin: 4 + + text: model.title.length > 0 ? model.title : qsTr("Untitled editorial") + font.bold: true + + wrapMode: Text.WordWrap + elide: Text.ElideRight + maximumLineCount: 2 + } + + MouseArea { + anchors.fill: parent + onClicked: showEditorial() + } +} diff --git a/examples/location/places/views/EditorialPage.qml b/examples/location/places/views/EditorialPage.qml new file mode 100644 index 0000000..caf0b7a --- /dev/null +++ b/examples/location/places/views/EditorialPage.qml @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + id: root + property variant editorial + width: parent.width + height: parent.height + + ScrollView { + id: scrollView + flickableItem.interactive: true + anchors.fill: parent + anchors.margins: 15 + + ColumnLayout { + width: scrollView.width - 30 + spacing: 10 + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: "#46a2da" + } + + Label { + text: editorial.title + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + wrapMode: Text.WordWrap + textFormat: Text.RichText + } + + Label { + text: editorial.text + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + wrapMode: Text.WordWrap + textFormat: Text.RichText + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: "#46a2da" + } + + Image { + Layout.alignment: Qt.AlignHCenter + source: editorial.supplier.icon.url(Qt.size(width, height), Icon.List) + } + + Label { + text: editorial.supplier.name + Layout.alignment: Qt.AlignHCenter + wrapMode: Text.WordWrap + textFormat: Text.RichText + } + + Button { + id: button + text: qsTr("Open url") + Layout.alignment: Qt.AlignHCenter + onClicked: { + Qt.openUrlExternally(editorial.supplier.url) + } + } + } + } +} diff --git a/examples/location/places/views/EditorialView.qml b/examples/location/places/views/EditorialView.qml new file mode 100644 index 0000000..05d4523 --- /dev/null +++ b/examples/location/places/views/EditorialView.qml @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 + +//! [PlaceEditorialModel view] +ListView { + id:view + property Place place + signal showEditorial(variant editorial) + width: parent.width + height: parent.height + model: place.editorialModel + delegate: EditorialDelegate { + onShowEditorial: view.showEditorial(model) + } +} +//! [PlaceEditorialModel view] + diff --git a/examples/location/places/views/ImageView.qml b/examples/location/places/views/ImageView.qml new file mode 100644 index 0000000..a4495da --- /dev/null +++ b/examples/location/places/views/ImageView.qml @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtQuick.Controls 1.4 + +Item { + id: root + property Place place + width: parent.width + height: parent.height + + GridView { + id: gridView + + anchors.fill: parent + + model: place.imageModel + + cellWidth: width / 3 + cellHeight: cellWidth + + delegate: Rectangle { + width: gridView.cellWidth + height: gridView.cellHeight + + color: "#30FFFFFF" + + Image { + anchors.fill: parent + anchors.margins: 5 + + source: url + + fillMode: Image.PreserveAspectFit + } + + MouseArea { + anchors.fill: parent + onClicked: { + listView.positionViewAtIndex(index, ListView.Contain); + root.state = "list"; + } + } + } + } + + ListView { + id: listView + + anchors.top: parent.top + anchors.bottom: position.top + width: parent.width + spacing: 10 + + model: place.imageModel + orientation: ListView.Horizontal + snapMode: ListView.SnapOneItem + + visible: false + + delegate: Item { + width: listView.width + height: listView.height + + Image { + anchors.fill: parent + source: url + fillMode: Image.PreserveAspectFit + + MouseArea { + anchors.fill: parent + onClicked: root.state = "" + } + } + + Button { + id: button + text: qsTr("Open url") + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + Qt.openUrlExternally(supplier.url) + } + } + } + } + + Label { + id: position + + width: parent.width + anchors.bottom: parent.bottom + visible: listView.visible + + text: (listView.currentIndex + 1) + '/' + listView.model.totalCount + horizontalAlignment: Text.AlignRight + } + + states: [ + State { + name: "list" + PropertyChanges { + target: gridView + visible: false + } + PropertyChanges { + target: listView + visible: true + } + } + ] +} diff --git a/examples/location/places/views/RatingView.qml b/examples/location/places/views/RatingView.qml new file mode 100644 index 0000000..7751f64 --- /dev/null +++ b/examples/location/places/views/RatingView.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 + +Row { + property real rating: 0 + property int size: 0 + + Repeater { + model: Math.ceil(rating) + Image { + source: "../../resources/star.png" + width: size + height: size + } + } +} diff --git a/examples/location/places/views/ReviewDelegate.qml b/examples/location/places/views/ReviewDelegate.qml new file mode 100644 index 0000000..7f2ba64 --- /dev/null +++ b/examples/location/places/views/ReviewDelegate.qml @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtQuick.Controls 1.4 + +Item { + id: root + signal showReview() + + width: parent.width + height: icon.height + 8 + + Image { + id: icon + + width: 64 + height: 64 + + anchors.verticalCenter: root.verticalCenter + anchors.left: root.left + anchors.leftMargin: 4 + + source: model.supplier.icon.url(Qt.size(64, 64), Icon.List) + fillMode: Image.PreserveAspectFit + } + + Label { + anchors.top: icon.top + anchors.topMargin: 4 + anchors.left: icon.right + anchors.leftMargin: 4 + anchors.right: root.right + anchors.rightMargin: 4 + + text: model.title + font.bold: true + + wrapMode: Text.WordWrap + elide: Text.ElideRight + maximumLineCount: 2 + } + + RatingView { + anchors.bottom: icon.bottom + anchors.bottomMargin: 4 + anchors.left: icon.right + anchors.leftMargin: 4 + anchors.right: root.right + anchors.rightMargin: 4 + + rating: model.rating + size: 16 + } + + MouseArea { + anchors.fill: parent + onClicked: showReview() + } +} diff --git a/examples/location/places/views/ReviewPage.qml b/examples/location/places/views/ReviewPage.qml new file mode 100644 index 0000000..d3ccf73 --- /dev/null +++ b/examples/location/places/views/ReviewPage.qml @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +Item { + id: root + property variant review + width: parent.width + height: parent.height + + ScrollView { + id: scrollView + flickableItem.interactive: true + anchors.fill: parent + anchors.margins: 15 + + ColumnLayout { + width: scrollView.width - 30 + spacing: 10 + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: "#46a2da" + } + + Label { + text: review.title + width: parent.width + wrapMode: Text.WordWrap + } + + Label { + text: Qt.formatDateTime(review.dateTime) + width: parent.width + Layout.alignment: Qt.AlignHCenter + } + + RatingView { + size: 16 + rating: review.rating + } + + Label { + text: review.text + width: parent.width + wrapMode: Text.WordWrap + Layout.alignment: Qt.AlignHCenter + textFormat: Text.RichText + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: "#46a2da" + } + + Image { + Layout.alignment: Qt.AlignHCenter + source: review.supplier.icon.url(Qt.size(width, height), Icon.List) + } + + Label { + text: editorial.supplier.name + Layout.alignment: Qt.AlignHCenter + wrapMode: Text.WordWrap + textFormat: Text.RichText + } + + Button { + id: button + text: qsTr("Open url") + Layout.alignment: Qt.AlignHCenter + onClicked: { + Qt.openUrlExternally(review.supplier.url) + } + } + } + } +} diff --git a/examples/location/places/views/ReviewView.qml b/examples/location/places/views/ReviewView.qml new file mode 100644 index 0000000..eb8727b --- /dev/null +++ b/examples/location/places/views/ReviewView.qml @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 + +//! [ReviewModel delegate] +ListView { + id:view + property Place place + signal showReview(variant review) + width: parent.width + height: parent.height + model: place.reviewModel + delegate: ReviewDelegate { + onShowReview: view.showReview(model) + } +} +//! [ReviewModel delegate] + diff --git a/examples/location/places/views/SearchResultDelegate.qml b/examples/location/places/views/SearchResultDelegate.qml new file mode 100644 index 0000000..a4ef9af --- /dev/null +++ b/examples/location/places/views/SearchResultDelegate.qml @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 +import "../helper.js" as Helper + +Item { + id: root + + signal showPlaceDetails(variant place,variant distance) + signal searchFor(string query) + + width: parent.width + height: childrenRect.height + + //! [PlaceSearchModel place delegate] + Component { + id: placeComponent + Item { + id: placeRoot + width: root.width + height: Math.max(icon.height, 3 * placeName.height) + + Rectangle { + anchors.fill: parent + color: "#44ffffff" + visible: mouse.pressed + } + + Rectangle { + anchors.fill: parent + color: "#dbffde" + visible: model.sponsored !== undefined ? model.sponsored : false + + Label { + text: qsTr("Sponsored result") + horizontalAlignment: Text.AlignRight + anchors.right: parent.right + anchors.bottom: parent.bottom + font.pixelSize: 8 + visible: model.sponsored !== undefined ? model.sponsored : false + } + } + + GridLayout { + rows: 2 + columns: 2 + anchors.fill: parent + anchors.leftMargin: 30 + flow: GridLayout.TopToBottom + + Image { + // anchors.verticalCenter: parent.verticalCenter + id:icon + source: place.favorite ? "../../resources/star.png" : place.icon.url() + Layout.rowSpan: 2 + } + + Label { + id: placeName + text: place.favorite ? place.favorite.name : place.name + Layout.fillWidth: true + } + + Label { + id: distanceText + font.italic: true + text: Helper.formatDistance(distance) + Layout.fillWidth: true + } + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 15 + height: 1 + color: "#46a2da" + } + + MouseArea { + id: mouse + anchors.fill: parent + onClicked: { + if (model.type === undefined || type === PlaceSearchModel.PlaceResult) { + if (!place.detailsFetched) + place.getDetails(); + root.showPlaceDetails(model.place, model.distance); + } + } + } + } + } + //! [PlaceSearchModel place delegate] + + Component { + id: proposedSearchComponent + + Item { + id: proposedSearchRoot + + width: root.width + height: Math.max(icon.height, 2 * proposedSearchTitle.height) + + Rectangle { + anchors.fill: parent + color: "#11ffffff" + visible: mouse.pressed + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 30 + + Image { + source: icon.url() + } + + Label { + id: proposedSearchTitle + anchors.verticalCenter: parent.verticalCenter + text: "Search for " + title + } + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 15 + height: 1 + color: "#46a2da" + } + + MouseArea { + anchors.fill: parent + onClicked: root.ListView.view.model.updateWith(index); + } + } + } + + Loader { + anchors.left: parent.left + anchors.right: parent.right + + sourceComponent: { + switch (model.type) { + case PlaceSearchModel.PlaceResult: + return placeComponent; + case PlaceSearchModel.ProposedSearchResult: + return proposedSearchComponent; + default: + //do nothing, don't assign component if result type not recognized + } + } + } +} diff --git a/examples/location/places/views/SearchResultView.qml b/examples/location/places/views/SearchResultView.qml new file mode 100644 index 0000000..1c2ee17 --- /dev/null +++ b/examples/location/places/views/SearchResultView.qml @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtLocation 5.6 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 + +//! [PlaceSearchModel place list] +ListView { + id: searchView + width: parent.width + height: parent.height + + property variant placeSearchModel + signal showPlaceDetails(variant place, variant distance) + signal showMap() + + model: placeSearchModel + delegate: SearchResultDelegate { + onShowPlaceDetails: searchView.showPlaceDetails(place, distance) + onSearchFor: placeSearchModel.searchForText(query); + } + + footer: + + RowLayout { + width: parent.width + + Button { + text: qsTr("Previous") + enabled: placeSearchModel.previousPagesAvailable + onClicked: placeSearchModel.previousPage() + Layout.alignment: Qt.AlignHCenter + } + + Button { + text: qsTr("Clear") + onClicked: { + placeSearchModel.reset() + showMap() + } + Layout.alignment: Qt.AlignHCenter + } + + Button { + text: qsTr("Next") + enabled: placeSearchModel.nextPagesAvailable + onClicked: placeSearchModel.nextPage() + Layout.alignment: Qt.AlignHCenter + } + } +} +//! [PlaceSearchModel place list] diff --git a/examples/location/places/views/SuggestionView.qml b/examples/location/places/views/SuggestionView.qml new file mode 100644 index 0000000..4ae9449 --- /dev/null +++ b/examples/location/places/views/SuggestionView.qml @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +//! [PlaceSearchSuggestionModel view 1] +ListView { + id: suggestionView + property variant suggestionModel + signal suggestionSelected(string text) +//! [PlaceSearchSuggestionModel view 1] + snapMode: ListView.SnapToItem +//! [PlaceSearchSuggestionModel view 2] + model: suggestionModel + delegate: Item { + width: parent.width + height: label.height * 1.5 + Label { + id: label + text: suggestion + } + MouseArea { + anchors.fill: parent + onClicked: suggestionSelected(suggestion) + } + } +} +//! [PlaceSearchSuggestionModel view 2] + diff --git a/examples/location/places_list/Marker.qml b/examples/location/places_list/Marker.qml new file mode 100644 index 0000000..7b73cde --- /dev/null +++ b/examples/location/places_list/Marker.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: image.width + Image { + id: image + anchors.centerIn: parent + source: "marker.png" + Text{ + y: parent.height/10 + width: parent.width + color: "white" + font.bold: true + font.pixelSize: 14 + horizontalAlignment: Text.AlignHCenter + text: index + } + } +} diff --git a/examples/location/places_list/doc/images/places_list.png b/examples/location/places_list/doc/images/places_list.png new file mode 100644 index 0000000..bf09a03 Binary files /dev/null and b/examples/location/places_list/doc/images/places_list.png differ diff --git a/examples/location/places_list/doc/src/places_list.qdoc b/examples/location/places_list/doc/src/places_list.qdoc new file mode 100644 index 0000000..ee9925a --- /dev/null +++ b/examples/location/places_list/doc/src/places_list.qdoc @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example places_list + \title Places List (QML) + \ingroup qtlocation-examples + + \brief The Places List example demonstrates how to search for and display a list of places using a \l ListView. + \image places_list.png + + \include examples-run.qdocinc + + The \c {Places List} example demonstrates how to search for a list of places + in a certain area and displays the result using a \l ListView. In this particular case, a search + for places associated with the term \c pizza is performed. + + \section1 Performing a Place Search + + To write a QML application that will show places in a list, we start by + making the following import declarations. + + \snippet places_list/places_list.qml Imports + + Instantiate a \l Plugin instance. The \l Plugin is effectively the backend + from where places are sourced from. Depending on the type of the plugin, + some mandatory parameters may be need to be filled in. The most likely type + of PluginParameter are some form of service access token which are documented + in the service plugin. As an example see the \l + {Mandatory Parameters} {HERE Plugin} documentation. In this snippet the \c osm + plugin is used which does not require any further parameter: + + \snippet places_list/places_list.qml Initialize Plugin + + Next we instantiate a \l PlaceSearchModel which we can use to specify + search parameters and perform a places search operation. For illustrative + purposes, \l {PlaceSearchModel::update} {update()} is invoked once + construction of the model is complete. Typically \l + {PlaceSearchModel::update} {update()} would be invoked in response to a + user action such as a button click. + + \snippet places_list/places_list.qml PlaceSearchModel + + Finally we instantiate a \l ListView to show the search results found by + the model. An inline delegate has been used and we have assumed that + every search result is of \l {Search Result Types} {type} \c + PlaceSearchesult. Consequently it is assumed that we always have access to + the \e place \l {PlaceSearchModel Roles} {role}, other search result types + may not have a \e place \l {PlaceSearchModel Roles} {role}. + + \snippet places_list/places_list.qml Places ListView +*/ diff --git a/examples/location/places_list/main.cpp b/examples/location/places_list/main.cpp new file mode 100644 index 0000000..2db67f7 --- /dev/null +++ b/examples/location/places_list/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +int main(int argc, char **argv) +{ + QGuiApplication app(argc,argv); + QQuickView view; + view.setSource(QUrl(QStringLiteral("qrc:///places_list.qml"))); + view.show(); + return app.exec(); +} diff --git a/examples/location/places_list/marker.png b/examples/location/places_list/marker.png new file mode 100644 index 0000000..2116dfd Binary files /dev/null and b/examples/location/places_list/marker.png differ diff --git a/examples/location/places_list/places_list.pro b/examples/location/places_list/places_list.pro new file mode 100644 index 0000000..82aa433 --- /dev/null +++ b/examples/location/places_list/places_list.pro @@ -0,0 +1,12 @@ +TARGET = places_list +TEMPLATE = app + +QT += quick qml network positioning location +SOURCES = main.cpp + +RESOURCES += \ + places_list.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/location/places_list +INSTALLS += target + diff --git a/examples/location/places_list/places_list.qml b/examples/location/places_list/places_list.qml new file mode 100644 index 0000000..cb5633a --- /dev/null +++ b/examples/location/places_list/places_list.qml @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [Imports] +import QtQuick 2.0 +import QtPositioning 5.5 +import QtLocation 5.6 +//! [Imports] + +Rectangle { + width: 360 + height: 640 + property variant startCoordinate: QtPositioning.coordinate( 59.9485, 10.7686) // The Qt Company in Oslo + + //! [Initialize Plugin] + Plugin { + id: myPlugin + name: "osm" + //specify plugin parameters as necessary + //PluginParameter {...} + //PluginParameter {...} + //... + } + //! [Initialize Plugin] + + //! [PlaceSearchModel] + PlaceSearchModel { + id: searchModel + + plugin: myPlugin + + searchTerm: "pizza" + searchArea: QtPositioning.circle(startCoordinate); + + Component.onCompleted: update() + + } + //! [PlaceSearchModel] + + //! [Places ListView] + ListView { + anchors.fill: parent + model: searchModel + delegate: Component { + Row { + spacing: 5 + Marker { height: parent.height } + Column { + Text { text: title; font.bold: true } + Text { text: place.location.address.text } + } + } + } + } + //! [Places ListView] + + Connections { + target: searchModel + onStatusChanged: { + if (searchModel.status == PlaceSearchModel.Error) + console.log(searchModel.errorString()); + } + } +} diff --git a/examples/location/places_list/places_list.qrc b/examples/location/places_list/places_list.qrc new file mode 100644 index 0000000..19a0ff5 --- /dev/null +++ b/examples/location/places_list/places_list.qrc @@ -0,0 +1,7 @@ + + + marker.png + places_list.qml + Marker.qml + + diff --git a/examples/location/places_map/doc/images/places_map.png b/examples/location/places_map/doc/images/places_map.png new file mode 100644 index 0000000..4982df2 Binary files /dev/null and b/examples/location/places_map/doc/images/places_map.png differ diff --git a/examples/location/places_map/doc/src/places_map.qdoc b/examples/location/places_map/doc/src/places_map.qdoc new file mode 100644 index 0000000..61a4be1 --- /dev/null +++ b/examples/location/places_map/doc/src/places_map.qdoc @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example places_map + \title Places Map (QML) + \ingroup qtlocation-examples + + \brief The Places Map example demonstrates how to search for and display a list of places + on a map using a MapItemView + \image places_map.png + + The example displays a map of the current location or, if no position is + available, it uses Brisbane/Australia. Subsequently a search for places + matching the term "pizza" is performed and each result shown on the map. + + \include examples-run.qdocinc + + \section1 Local Search + + To write the QML application that will show places on a map, we start by + making the following import declarations. + + \snippet places_map/places_map.qml Imports + + Instantiate a \l Plugin instance. The \l Plugin is effectively the backend + from where places are sourced from. Depending on the chosen plugin + some manadatory parameters may be needed. In this case the + \l {Qt Location Open Street Map Plugin}{OSM plugin} is selected which does not have any mandatory + parameters. + + \snippet places_map/places_map.qml Initialize Plugin + + Next we instantiate a \l PlaceSearchModel which we can use to specify + search parameters and perform a places search operation. For illustrative + purposes, \l {PlaceSearchModel::update} {update()} is invoked once + construction of the model is complete. Typically \l + {PlaceSearchModel::update} {update()} would be invoked in response to a + user action such as a button click. + + \snippet places_map/places_map.qml PlaceSearchModel + + The map is displayed by using the \l Map type and inside we declare the \l + MapItemView and supply the search model and a delegate. An inline delegate + has been used and we have assumed that every search result is of \l {Search + Result Types} {type} \c PlaceSerachesult. Consequently it is assumed that + we always have access to the \e place \l {PlaceSearchModel Roles} {role}, + other search result types may not have a \e place \l {PlaceSearchModel + Roles} {role}. + + \snippet places_map/places_map.qml Places MapItemView + + Finally, a \c PositionSource is used to reset the map to the curent + location and find "pizza" places in the new area. The position information + is updated every 2 minutes and if the new position is more than 500 meters + away from the last pizza search area the place search is retriggered. + + \snippet places_map/places_map.qml Current Location +*/ diff --git a/examples/location/places_map/main.cpp b/examples/location/places_map/main.cpp new file mode 100644 index 0000000..a2cd8fc --- /dev/null +++ b/examples/location/places_map/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +int main(int argc, char **argv) +{ + QGuiApplication app(argc,argv); + QQuickView view; + view.setSource(QUrl(QStringLiteral("qrc:///places_map.qml"))); + view.show(); + return app.exec(); +} diff --git a/examples/location/places_map/marker.png b/examples/location/places_map/marker.png new file mode 100644 index 0000000..2116dfd Binary files /dev/null and b/examples/location/places_map/marker.png differ diff --git a/examples/location/places_map/places_map.pro b/examples/location/places_map/places_map.pro new file mode 100644 index 0000000..51d61bb --- /dev/null +++ b/examples/location/places_map/places_map.pro @@ -0,0 +1,12 @@ +TARGET = places_map +TEMPLATE = app + +QT += quick qml network positioning location +SOURCES = main.cpp + +RESOURCES += \ + places_map.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/location/places_map +INSTALLS += target + diff --git a/examples/location/places_map/places_map.qml b/examples/location/places_map/places_map.qml new file mode 100644 index 0000000..e7d20e7 --- /dev/null +++ b/examples/location/places_map/places_map.qml @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [Imports] +import QtQuick 2.0 +import QtPositioning 5.5 +import QtLocation 5.6 +//! [Imports] + +Rectangle { + width: 360 + height: 640 + + //! [Initialize Plugin] + Plugin { + id: myPlugin + name: "osm" + //specify plugin parameters if necessary + //PluginParameter {...} + //PluginParameter {...} + //... + } + //! [Initialize Plugin] + + //! [Current Location] + PositionSource { + id: positionSource + property variant lastSearchPosition: locationOslo + active: true + updateInterval: 120000 // 2 mins + onPositionChanged: { + var currentPosition = positionSource.position.coordinate + map.center = currentPosition + var distance = currentPosition.distanceTo(lastSearchPosition) + if (distance > 500) { + // 500m from last performed pizza search + lastSearchPosition = currentPosition + searchModel.searchArea = QtPositioning.circle(currentPosition) + searchModel.update() + } + } + } + //! [Current Location] + + //! [PlaceSearchModel] + property variant locationOslo: QtPositioning.coordinate( 59.93, 10.76) + + PlaceSearchModel { + id: searchModel + + plugin: myPlugin + + searchTerm: "Pizza" + searchArea: QtPositioning.circle(locationOslo) + + Component.onCompleted: update() + } + //! [PlaceSearchModel] + + //! [Places MapItemView] + Map { + id: map + anchors.fill: parent + plugin: myPlugin; + center: locationOslo + zoomLevel: 13 + + MapItemView { + model: searchModel + delegate: MapQuickItem { + coordinate: place.location.coordinate + + anchorPoint.x: image.width * 0.5 + anchorPoint.y: image.height + + sourceItem: Column { + Image { id: image; source: "marker.png" } + Text { text: title; font.bold: true } + } + } + } + } + //! [Places MapItemView] + + Connections { + target: searchModel + onStatusChanged: { + if (searchModel.status == PlaceSearchModel.Error) + console.log(searchModel.errorString()); + } + } +} diff --git a/examples/location/places_map/places_map.qrc b/examples/location/places_map/places_map.qrc new file mode 100644 index 0000000..2239529 --- /dev/null +++ b/examples/location/places_map/places_map.qrc @@ -0,0 +1,6 @@ + + + marker.png + places_map.qml + + diff --git a/examples/location/planespotter/Plane.qml b/examples/location/planespotter/Plane.qml new file mode 100644 index 0000000..eec5a23 --- /dev/null +++ b/examples/location/planespotter/Plane.qml @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 +import QtLocation 5.6 + +//! [PlaneMapQuick1] +// Plane.qml +MapQuickItem { + id: plane + property string pilotName; + property int bearing: 0; + + anchorPoint.x: image.width/2 + anchorPoint.y: image.height/2 + + sourceItem: Grid { + //... +//! [PlaneMapQuick1] + columns: 1 + Grid { + horizontalItemAlignment: Grid.AlignHCenter + Image { + id: image + rotation: bearing + source: "airplane.png" + } + Rectangle { + id: bubble + color: "lightblue" + border.width: 1 + width: text.width * 1.3 + height: text.height * 1.3 + radius: 5 + Text { + id: text + anchors.centerIn: parent + text: pilotName + } + } + } + + Rectangle { + id: message + color: "lightblue" + border.width: 1 + width: banner.width * 1.3 + height: banner.height * 1.3 + radius: 5 + opacity: 0 + Text { + id: banner + anchors.centerIn: parent + } + SequentialAnimation { + id: playMessage + running: false + NumberAnimation { target: message; + property: "opacity"; + to: 1.0; + duration: 200 + easing.type: Easing.InOutQuad + } + PauseAnimation { duration: 1000 } + NumberAnimation { target: message; + property: "opacity"; + to: 0.0; + duration: 200} + } + } + } + function showMessage(message) { + banner.text = message + playMessage.start() +//! [PlaneMapQuick2] + } +} +//! [PlaneMapQuick2] diff --git a/examples/location/planespotter/airplane.png b/examples/location/planespotter/airplane.png new file mode 100644 index 0000000..080460d Binary files /dev/null and b/examples/location/planespotter/airplane.png differ diff --git a/examples/location/planespotter/doc/images/planespotter.png b/examples/location/planespotter/doc/images/planespotter.png new file mode 100644 index 0000000..dcfd55f Binary files /dev/null and b/examples/location/planespotter/doc/images/planespotter.png differ diff --git a/examples/location/planespotter/doc/src/planespotter.qdoc b/examples/location/planespotter/doc/src/planespotter.qdoc new file mode 100644 index 0000000..ed3a2b2 --- /dev/null +++ b/examples/location/planespotter/doc/src/planespotter.qdoc @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example planespotter + \title Plane Spotter (QML) + \ingroup qtlocation-examples + + \brief The \c {Plane Spotter} example demonstrates the tight integration of + location and positioning data types into QML + + \image planespotter.png + + The \c {Plane Spotter} example demonstrates how to integrate location and positioning + related C++ data types into QML and vice versa. This is useful when it is desirable to + run CPU intensive position calculations in native environments + but the results are supposed to be displayed using QML. + + The example shows a map of Europe and airplanes on two routes across Europe. + The first airplane commutes between Oslo and Berlin and the second airplane + commutes between London and Berlin. The position tracking of each airplane + is implemented in C++. The Oslo-Berlin plane is piloted in QML and the London-Berlin + plane is commanded by a C++ pilot. + + \include examples-run.qdocinc + + \section1 Overview + + + This example makes use of the \l Q_GADGET feature as part of its position controller + implementation. It permits \l {Cpp_value_integration_positioning}{direct integration} + of non-QObject based C++ value types into QML. + + The main purpose of the \c PlaneController class is to track the current + coordinates of the plane at a given time. It exposes the position + via its position property. + + \snippet planespotter/main.cpp PlaneController1 + \snippet planespotter/main.cpp PlaneController2 + + The example's \c main() function is responsible for the binding of the + \c PlaneController class instances into the QML context: + + \snippet planespotter/main.cpp PlaneControllerMain + + Similar to QObject derived classes, \l QGeoCoordinate can be integrated without + an additional QML wrapper. + + \section1 Steering the Planes + + As mentioned above, the primary purpose of \c PlaneController class is to track the current + positions of the two planes (Oslo-Berlin and London-Berlin) and advertise them as a property + to the QML layer. Its secondary purpose is to set and progress a plane along a given + flight path. In a sense it can act as a pilot. This is very much like + \l CoordinateAnimation which can animate the transition from one geo coordinate to another. + This example demonstrates how the \c {PlaneController}'s position property is modified + by C++ code using the PlaneController's own piloting abilities and by QML code using + \l CoordinateAnimation as pilot. The Oslo-Berlin plane is animated using QML code + and the London-Berlin plane is animated using C++ code. + + No matter which pilot is used, the results to the pilot's + actions are visible in C++ and QML and thus the example demonstrates unhindered and direct + exchange of position data through the C++/QML boundary. + + The visual representation of each \c Plane is done using + the \l MapQuickItem type which permits the embedding of arbitrary QtQuick items + into a map: + + \snippet planespotter/Plane.qml PlaneMapQuick1 + \snippet planespotter/Plane.qml PlaneMapQuick2 + + \section2 The C++ Pilot + + The C++ plane is steered by C++. The \c from and \c to property of the controller + class set the origin and destination which the pilot uses to calculate the + bearing for the plane: + + \snippet planespotter/main.cpp C++Pilot1 + + The pilot employs a \l QBasicTimer and \l {QTimerEvent}{QTimerEvents} to + constantly update the position. During each timer iteration + \c PlaneController::updatePosition() is called and a new position calculated. + + \snippet planespotter/main.cpp C++Pilot3 + + Once the new position is calculated, \c setPosition() is called and + the subsequent change notification of the property pushes the new position + to the QML layer. + + The C++ plane is started by clicking on the plane: + + \snippet planespotter/planespotter.qml CppPlane1 + \snippet planespotter/planespotter.qml CppPlane2 + + \l {azimuthTo}() calculates the bearing in degrees from one coordinate to another. + Note that the above code utilizes a QML animation to tie the rotation + and the position change into a single animation flow: + + \snippet planespotter/planespotter.qml CppPlane3 + + First, \l NumberAnimation rotates the plane into the correct direction + and once that is done the \c startFlight() function takes care of + starting the plane's position change. + + \snippet planespotter/main.cpp C++Pilot2 + + \section2 The QML Pilot + + The \l CoordinateAnimation type is used to control the flight from Oslo + to Berlin and vice versa. It replaces the above \l ScriptAction. + + \snippet planespotter/planespotter.qml QmlPlane1 + + The \l MouseArea of the QML plane implements the logic for the course setting + and starts the animation when required. + + \snippet planespotter/planespotter.qml QmlPlane2 + +*/ diff --git a/examples/location/planespotter/main.cpp b/examples/location/planespotter/main.cpp new file mode 100644 index 0000000..c71a699 --- /dev/null +++ b/examples/location/planespotter/main.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ANIMATION_DURATION 4000 + +//! [PlaneController1] +class PlaneController: public QObject +{ + Q_OBJECT + Q_PROPERTY(QGeoCoordinate position READ position WRITE setPosition NOTIFY positionChanged) +//! [PlaneController1] + //! [C++Pilot1] + Q_PROPERTY(QGeoCoordinate from READ from WRITE setFrom NOTIFY fromChanged) + Q_PROPERTY(QGeoCoordinate to READ to WRITE setTo NOTIFY toChanged) + //! [C++Pilot1] + +public: + PlaneController() + { + easingCurve.setType(QEasingCurve::InOutQuad); + easingCurve.setPeriod(ANIMATION_DURATION); + } + + void setFrom(const QGeoCoordinate& from) + { + fromCoordinate = from; + } + + QGeoCoordinate from() const + { + return fromCoordinate; + } + + void setTo(const QGeoCoordinate& to) + { + toCoordinate = to; + } + + QGeoCoordinate to() const + { + return toCoordinate; + } + + void setPosition(const QGeoCoordinate &c) { + if (currentPosition == c) + return; + + currentPosition = c; + emit positionChanged(); + } + + QGeoCoordinate position() const + { + return currentPosition; + } + + Q_INVOKABLE bool isFlying() const { + return timer.isActive(); + } + +//! [C++Pilot2] +public slots: + void startFlight() + { + if (timer.isActive()) + return; + + startTime = QTime::currentTime(); + finishTime = startTime.addMSecs(ANIMATION_DURATION); + + timer.start(15, this); + emit departed(); + } +//! [C++Pilot2] + + void swapDestinations() { + if (currentPosition == toCoordinate) { + // swap destinations + toCoordinate = fromCoordinate; + fromCoordinate = currentPosition; + } + } + +signals: + void positionChanged(); + void arrived(); + void departed(); + void toChanged(); + void fromChanged(); + +protected: + void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE + { + if (!event) + return; + + if (event->timerId() == timer.timerId()) + updatePosition(); + else + QObject::timerEvent(event); + } + +private: + //! [C++Pilot3] + void updatePosition() + { + // simple progress animation + qreal progress; + QTime current = QTime::currentTime(); + if (current >= finishTime) { + progress = 1.0; + timer.stop(); + } else { + progress = ((qreal)startTime.msecsTo(current) / ANIMATION_DURATION); + } + + setPosition(QGeoProjection::coordinateInterpolation( + fromCoordinate, toCoordinate, easingCurve.valueForProgress(progress))); + + if (!timer.isActive()) + emit arrived(); + } + //! [C++Pilot3] + +private: + QGeoCoordinate currentPosition; + QGeoCoordinate fromCoordinate, toCoordinate; + QBasicTimer timer; + QTime startTime, finishTime; + QEasingCurve easingCurve; +//! [PlaneController2] + // ... +}; +//! [PlaneController2] + +//! [PlaneControllerMain] +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + PlaneController oslo2berlin; + PlaneController berlin2london; + + QQmlApplicationEngine engine; + engine.rootContext()->setContextProperty("oslo2Berlin", &oslo2berlin); + engine.rootContext()->setContextProperty("berlin2London", &berlin2london); + engine.load(QUrl(QStringLiteral("qrc:/planespotter.qml"))); + + return app.exec(); +} +//! [PlaneControllerMain] + +#include "main.moc" diff --git a/examples/location/planespotter/planespotter.pro b/examples/location/planespotter/planespotter.pro new file mode 100644 index 0000000..d3be902 --- /dev/null +++ b/examples/location/planespotter/planespotter.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +TARGET = planespotter +QT += qml quick positioning positioning-private location + +SOURCES += main.cpp + +RESOURCES += qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/location/planespotter +INSTALLS += target diff --git a/examples/location/planespotter/planespotter.qml b/examples/location/planespotter/planespotter.qml new file mode 100644 index 0000000..624a015 --- /dev/null +++ b/examples/location/planespotter/planespotter.qml @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Window 2.2 +import QtPositioning 5.5 +import QtLocation 5.6 + +Window { + width: 700 + height: 500 + visible: true + + property variant topLeftEurope: QtPositioning.coordinate(60.5, 0.0) + property variant bottomRightEurope: QtPositioning.coordinate(51.0, 14.0) + property variant viewOfEurope: + QtPositioning.rectangle(topLeftEurope, bottomRightEurope) + + property variant berlin: QtPositioning.coordinate(52.5175, 13.384) + property variant oslo: QtPositioning.coordinate(59.9154, 10.7425) + property variant london: QtPositioning.coordinate(51.5, 0.1275) + + Map { + id: mapOfEurope + anchors.centerIn: parent; + anchors.fill: parent + plugin: Plugin { + name: "osm" + } + + Plane { + id: qmlPlane + pilotName: "QML" + coordinate: oslo2Berlin.position + + SequentialAnimation { + id: qmlPlaneAnimation + property real rotationDirection : 0; + NumberAnimation { + target: qmlPlane; property: "bearing"; duration: 1000 + easing.type: Easing.InOutQuad + to: qmlPlaneAnimation.rotationDirection + } + //! [QmlPlane1] + CoordinateAnimation { + id: coordinateAnimation; duration: 5000 + target: oslo2Berlin; property: "position" + easing.type: Easing.InOutQuad + } + //! [QmlPlane1] + + onStopped: { + if (coordinateAnimation.to === berlin) + qmlPlane.showMessage(qsTr("Hello Berlin!")) + else if (coordinateAnimation.to === oslo) + qmlPlane.showMessage(qsTr("Hello Oslo!")) + } + onStarted: { + if (coordinateAnimation.from === oslo) + qmlPlane.showMessage(qsTr("See you Oslo!")) + else if (coordinateAnimation.from === berlin) + qmlPlane.showMessage(qsTr("See you Berlin!")) + } + } + + //! [QmlPlane2] + MouseArea { + anchors.fill: parent + onClicked: { + if (qmlPlaneAnimation.running) { + console.log("Plane still in the air."); + return; + } + + if (oslo2Berlin.position === berlin) { + coordinateAnimation.from = berlin; + coordinateAnimation.to = oslo; + } else if (oslo2Berlin.position === oslo) { + coordinateAnimation.from = oslo; + coordinateAnimation.to = berlin; + } + + qmlPlaneAnimation.rotationDirection = oslo2Berlin.position.azimuthTo(coordinateAnimation.to) + qmlPlaneAnimation.start() + } + } + //! [QmlPlane2] + Component.onCompleted: { + oslo2Berlin.position = oslo; + } + } + + //! [CppPlane1] + Plane { + id: cppPlane + pilotName: "C++" + coordinate: berlin2London.position + + MouseArea { + anchors.fill: parent + onClicked: { + if (cppPlaneAnimation.running || berlin2London.isFlying()) { + console.log("Plane still in the air."); + return; + } + + berlin2London.swapDestinations(); + cppPlaneAnimation.rotationDirection = berlin2London.position.azimuthTo(berlin2London.to) + cppPlaneAnimation.start(); + cppPlane.departed(); + } + } + //! [CppPlane1] + //! [CppPlane3] + SequentialAnimation { + id: cppPlaneAnimation + property real rotationDirection : 0; + NumberAnimation { + target: cppPlane; property: "bearing"; duration: 1000 + easing.type: Easing.InOutQuad + to: cppPlaneAnimation.rotationDirection + } + ScriptAction { script: berlin2London.startFlight() } + } + //! [CppPlane3] + + Component.onCompleted: { + berlin2London.position = berlin; + berlin2London.to = london; + berlin2London.from = berlin; + berlin2London.arrived.connect(arrived) + } + + function arrived(){ + if (berlin2London.to === berlin) + cppPlane.showMessage(qsTr("Hello Berlin!")) + else if (berlin2London.to === london) + cppPlane.showMessage(qsTr("Hello London!")) + } + + function departed(){ + if (berlin2London.from === berlin) + cppPlane.showMessage(qsTr("See you Berlin!")) + else if (berlin2London.from === london) + cppPlane.showMessage(qsTr("See you London!")) + } + //! [CppPlane2] + } + //! [CppPlane2] + + visibleRegion: viewOfEurope + } + + Rectangle { + id: infoBox + anchors.centerIn: parent + color: "white" + border.width: 1 + width: text.width * 1.3 + height: text.height * 1.3 + radius: 5 + Text { + id: text + anchors.centerIn: parent + text: qsTr("Hit the plane to start the flight!") + } + + Timer { + interval: 5000; running: true; repeat: false; + onTriggered: fadeOut.start() + } + + NumberAnimation { + id: fadeOut; target: infoBox; + property: "opacity"; + to: 0.0; + duration: 200 + easing.type: Easing.InOutQuad + } + } +} diff --git a/examples/location/planespotter/qml.qrc b/examples/location/planespotter/qml.qrc new file mode 100644 index 0000000..6903ec0 --- /dev/null +++ b/examples/location/planespotter/qml.qrc @@ -0,0 +1,7 @@ + + + planespotter.qml + Plane.qml + airplane.png + + diff --git a/examples/positioning/geoflickr/doc/images/qml-flickr-1.jpg b/examples/positioning/geoflickr/doc/images/qml-flickr-1.jpg new file mode 100644 index 0000000..42514ff Binary files /dev/null and b/examples/positioning/geoflickr/doc/images/qml-flickr-1.jpg differ diff --git a/examples/positioning/geoflickr/doc/src/geoflickr.qdoc b/examples/positioning/geoflickr/doc/src/geoflickr.qdoc new file mode 100644 index 0000000..6d043d4 --- /dev/null +++ b/examples/positioning/geoflickr/doc/src/geoflickr.qdoc @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example geoflickr + \title GeoFlickr (QML) + \ingroup qtpositioning-examples + + \brief The GeoFlickr example shows how to use the user's current position to + fetch local content from a web service. + + This is a small example, illustrating one of the very core parts of the + \l{Qt Positioning} API: the ability to retrieve and use the user's current + geographic position. + + Key QML types shown in this example: + \list + \li \l{QtPositioning::PositionSource}{PositionSource} + \li \l{XmlListModel}{XmlListModel} + \endlist + + \image qml-flickr-1.jpg + + \include examples-run.qdocinc + + \section1 Retrieving the Current Position + + Retrieving the user's current position is achieved using the PositionSource + type. In this example, we instantiate the PositionSource as part of the + GeoTab component (the floating "window" describing current position and + status). + + \snippet geoflickr/flickrmobile/GeoTab.qml possrc + + When the "Locate and update" button is pressed, we first interrogate the + PositionSource to check if it has an available backend for positioning + data. If it does not, we fall back to using a pre-recorded NMEA log + for demonstration. We then instruct the PositionSource to update. + + \snippet geoflickr/flickrmobile/GeoTab.qml locatebutton-top + \snippet geoflickr/flickrmobile/GeoTab.qml locatebutton-clicked + + To share the new position data with the rest of the application, we use + properties that we have created on the GeoTab component: + + \snippet geoflickr/flickrmobile/GeoTab.qml props + + \section1 Using the Current Position + + The longitude and latitude values retrieved here are eventually set on + in properties on the RestModel component. The RestModel is an XmlListModel, + which retrieves XML data from a URL and creates a data model by performing + XPath queries on it. + + In this case, it retrieves data from the Flickr REST API online, based on + our current position + + \snippet geoflickr/flickrcommon/RestModel.qml restmodel + + This model data is then shown in a variety of Qt Quick views to produce + the example application. + +*/ diff --git a/examples/positioning/geoflickr/flickr-90.qml b/examples/positioning/geoflickr/flickr-90.qml new file mode 100644 index 0000000..92e9344 --- /dev/null +++ b/examples/positioning/geoflickr/flickr-90.qml @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + width: 480; height: 320 + + Loader { + y: 320; rotation: -90 + transformOrigin: Item.TopLeft + source: "flickr.qml" + } +} diff --git a/examples/positioning/geoflickr/flickr.qml b/examples/positioning/geoflickr/flickr.qml new file mode 100644 index 0000000..5ae065c --- /dev/null +++ b/examples/positioning/geoflickr/flickr.qml @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.XmlListModel 2.0 +import "flickrcommon" as Common +import "flickrmobile" as Mobile + +Item { + id: screen; width: 320; height: 480 + property bool inListView : false + + Rectangle { + id: background + anchors.fill: parent; color: "#343434"; + + Image { source: "flickrmobile/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 0.3 } + + Common.RestModel { + id: restModel + coordinate: geoTab.coordinate + } + + Item { + id: views + x: 2; width: parent.width - 4 + anchors.top: titleBar.bottom; anchors.bottom: toolBar.top + + Text { + text: qsTr("Network error") + font.pixelSize: 48 + fontSizeMode: Text.HorizontalFit + anchors.centerIn: parent + width: parent.width * 0.9 + visible: restModel.status === XmlListModel.Error + + } + + Mobile.GridDelegate { id: gridDelegate } + GridView { + x: (width/4-79)/2; y: x + id: photoGridView; model: restModel; delegate: gridDelegate; cacheBuffer: 100 + cellWidth: (parent.width-2)/4; cellHeight: cellWidth; width: parent.width; height: parent.height - 1; z: 6 + } + Mobile.ListDelegate { id: listDelegate } + ListView { + id: photoListView; model: restModel; delegate: listDelegate; z: 6 + width: parent.width; height: parent.height; x: -(parent.width * 1.5); cacheBuffer: 100; + } + states: State { + name: "ListView"; when: screen.inListView == true + PropertyChanges { target: photoListView; x: 0 } + PropertyChanges { target: photoGridView; x: -(parent.width * 1.5) } + } + + transitions: Transition { + NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } + } + } + Mobile.ImageDetails { id: imageDetails; width: parent.width; anchors.left: views.right; height: parent.height; z:1 } + Mobile.TitleBar { id: titleBar; z: 5; width: parent.width; height: 40; opacity: 0.9 } + Mobile.GeoTab { + id: geoTab; + x: 15; y:50; + } + Mobile.ToolBar { + id: toolBar; z: 5 + height: 40; anchors.bottom: parent.bottom; width: parent.width; opacity: 0.9 + button1Label: "Update"; button2Label: "View mode" + onButton1Clicked: restModel.reload() + onButton2Clicked: if (screen.inListView == true) screen.inListView = false; else screen.inListView = true + } + Connections { + target: imageDetails + onClosed: { + if (background.state == "DetailedView") { + background.state = ''; + imageDetails.photoUrl = ""; + } + } + } + + states: State { + name: "DetailedView" + PropertyChanges { target: views; x: -parent.width } + PropertyChanges { target: geoTab; x: -parent.width } + PropertyChanges { target: toolBar; button1Label: "More..." } + PropertyChanges { + target: toolBar + onButton1Clicked: if (imageDetails.state=='') imageDetails.state='Back'; else imageDetails.state='' + } + PropertyChanges { target: toolBar; button2Label: "Back" } + PropertyChanges { target: toolBar; onButton2Clicked: imageDetails.closed() } + } + + transitions: Transition { + NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } + } + } +} diff --git a/examples/positioning/geoflickr/flickr.qrc b/examples/positioning/geoflickr/flickr.qrc new file mode 100644 index 0000000..1019f7d --- /dev/null +++ b/examples/positioning/geoflickr/flickr.qrc @@ -0,0 +1,30 @@ + + + flickr.qml + flickr-90.qml + flickrcommon/Progress.qml + flickrcommon/RestModel.qml + flickrcommon/ScrollBar.qml + flickrcommon/Slider.qml + flickrmobile/Button.qml + flickrmobile/GeoTab.qml + flickrmobile/GridDelegate.qml + flickrmobile/ImageDetails.qml + flickrmobile/ListDelegate.qml + flickrmobile/nmealog.txt + flickrmobile/TitleBar.qml + flickrmobile/ToolBar.qml + flickrmobile/images/gloss.png + flickrmobile/images/lineedit.png + flickrmobile/images/lineedit.sci + flickrmobile/images/moon.png + flickrmobile/images/quit.png + flickrmobile/images/star.png + flickrmobile/images/stripes.png + flickrmobile/images/sun.png + flickrmobile/images/titlebar.png + flickrmobile/images/titlebar.sci + flickrmobile/images/toolbutton.png + flickrmobile/images/toolbutton.sci + + diff --git a/examples/positioning/geoflickr/flickrcommon/Progress.qml b/examples/positioning/geoflickr/flickrcommon/Progress.qml new file mode 100644 index 0000000..294957b --- /dev/null +++ b/examples/positioning/geoflickr/flickrcommon/Progress.qml @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + property variant progress: 0 + + Rectangle { + anchors.fill: parent; smooth: true + border.color: "white"; border.width: 0; radius: height/2 - 2 + gradient: Gradient { + GradientStop { position: 0; color: "#66343434" } + GradientStop { position: 1.0; color: "#66000000" } + } + } + + Rectangle { + y: 2; height: parent.height-4; + x: 2; width: Math.max(parent.width * progress - 4, 0); + opacity: width < 1 ? 0 : 1; smooth: true + gradient: Gradient { + GradientStop { position: 0; color: "lightsteelblue" } + GradientStop { position: 1.0; color: "steelblue" } + } + radius: height/2 - 2 + } + + Text { + text: Math.round(progress * 100) + "%" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + color: "white"; font.bold: true + } +} diff --git a/examples/positioning/geoflickr/flickrcommon/RestModel.qml b/examples/positioning/geoflickr/flickrcommon/RestModel.qml new file mode 100644 index 0000000..762cfec --- /dev/null +++ b/examples/positioning/geoflickr/flickrcommon/RestModel.qml @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.XmlListModel 2.0 + +//! [restmodel] +XmlListModel { + property variant coordinate + + source: "https://api.flickr.com/services/rest/?" + + "min_taken_date=2000-01-01+0:00:00&" + + "extras=date_taken&" + + "method=flickr.photos.search&" + + "per_page=30&" + + "sort=date-taken-desc&" + + "api_key=e36784df8a03fea04c22ed93318b291c&" + + "lat=" + coordinate.latitude + "&lon=" + coordinate.longitude; + query: "/rsp/photos/photo" + + XmlRole { name: "title"; query: "@title/string()" } + XmlRole { name: "datetaken"; query: "@datetaken/string()" } + XmlRole { name: "farm"; query: "@farm/string()" } + XmlRole { name: "server"; query: "@server/string()" } + XmlRole { name: "id"; query: "@id/string()" } + XmlRole { name: "secret"; query: "@secret/string()" } +} +//! [restmodel] diff --git a/examples/positioning/geoflickr/flickrcommon/ScrollBar.qml b/examples/positioning/geoflickr/flickrcommon/ScrollBar.qml new file mode 100644 index 0000000..c18e097 --- /dev/null +++ b/examples/positioning/geoflickr/flickrcommon/ScrollBar.qml @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: container + + property variant flickableArea + + Rectangle { + radius: 5 + color: "black" + opacity: 0.3 + border.color: "white" + border.width: 2 + x: 0 + y: flickableArea.visibleArea.yPosition * container.height + width: parent.width + height: flickableArea.visibleArea.heightRatio * container.height + } + states: [ + State { + name: "show" + when: flickableArea.movingVertically + PropertyChanges { + target: container + opacity: 1 + } + } + ] + transitions: [ + Transition { + from: "*" + to: "*" + NumberAnimation { + target: container + properties: "opacity" + duration: 400 + } + } + ] +} diff --git a/examples/positioning/geoflickr/flickrcommon/Slider.qml b/examples/positioning/geoflickr/flickrcommon/Slider.qml new file mode 100644 index 0000000..0a6fa70 --- /dev/null +++ b/examples/positioning/geoflickr/flickrcommon/Slider.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: slider; width: 400; height: 16 + + // value is read/write. + property real value + onValueChanged: { handle.x = 2 + (value - minimum) * slider.xMax / (maximum - minimum); } + property real maximum: 1 + property real minimum: 1 + property int xMax: slider.width - handle.width - 4 + + Rectangle { + anchors.fill: parent + border.color: "white"; border.width: 0; radius: 8 + gradient: Gradient { + GradientStop { position: 0.0; color: "#66343434" } + GradientStop { position: 1.0; color: "#66000000" } + } + } + + Rectangle { + id: handle; smooth: true + x: slider.width / 2 - handle.width / 2; y: 2; width: 30; height: slider.height-4; radius: 6 + gradient: Gradient { + GradientStop { position: 0.0; color: "lightgray" } + GradientStop { position: 1.0; color: "gray" } + } + + MouseArea { + anchors.fill: parent; drag.target: parent + drag.axis: Drag.XAxis; drag.minimumX: 2; drag.maximumX: slider.xMax+2 + onPositionChanged: { value = (maximum - minimum) * (handle.x-2) / slider.xMax + minimum; } + } + } +} diff --git a/examples/positioning/geoflickr/flickrmobile/Button.qml b/examples/positioning/geoflickr/flickrmobile/Button.qml new file mode 100644 index 0000000..27e5140 --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/Button.qml @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: container + + signal clicked + + property string text + + BorderImage { + id: buttonImage + source: "images/toolbutton.sci" + width: container.width; height: container.height + } + BorderImage { + id: pressed + opacity: 0 + source: "images/toolbutton.sci" + width: container.width; height: container.height + } + MouseArea { + id: mouseRegion + anchors.fill: buttonImage + onClicked: { container.clicked(); } + } + Text { + color: "white" + anchors.centerIn: buttonImage; font.bold: true + text: container.text; style: Text.Raised; styleColor: "black" + } + states: [ + State { + name: "Pressed" + when: mouseRegion.pressed == true + PropertyChanges { target: pressed; opacity: 1 } + } + ] +} diff --git a/examples/positioning/geoflickr/flickrmobile/GeoTab.qml b/examples/positioning/geoflickr/flickrmobile/GeoTab.qml new file mode 100644 index 0000000..4505319 --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/GeoTab.qml @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtPositioning 5.2 + +Rectangle { + id: container + property int maxX: parent.width; property int maxY: parent.height +//! [props] + property variant coordinate +//! [props] + + Binding { + target: container + property: "coordinate" + value: positionSource.position.coordinate + } + + width: 300; height: 130 + color: "blue" + opacity: 0.7 + border.color: "black" + border.width: 1 + radius: 5 + gradient: Gradient { + GradientStop {position: 0.0; color: "grey"} + GradientStop {position: 1.0; color: "black"} + } + MouseArea { + anchors.fill: parent + drag.target: parent + drag.axis: Drag.XandYAxis + drag.minimumX: -(parent.width * (2/3)); drag.maximumX: parent.maxX - (parent.width/3) + drag.minimumY: -(parent.height/2); drag.maximumY: parent.maxY - (parent.height/2) + } +//! [locatebutton-top] + Button { + id: locateButton + text: "Locate & update" +//! [locatebutton-top] + anchors {left: parent.left; leftMargin: 5} + y: 3; height: 32; width: parent.width - 10 +//! [locatebutton-clicked] + onClicked: { + if (positionSource.supportedPositioningMethods === + PositionSource.NoPositioningMethods) { + positionSource.nmeaSource = "nmealog.txt"; + sourceText.text = "(filesource): " + printableMethod(positionSource.supportedPositioningMethods); + } + positionSource.update(); + } + } +//! [locatebutton-clicked] +//! [possrc] + PositionSource { + id: positionSource + onPositionChanged: { planet.source = "images/sun.png"; } + + onSourceErrorChanged: { + if (sourceError == PositionSource.NoError) + return + + console.log("Source error: " + sourceError) + activityText.fadeOut = true + stop() + } + + onUpdateTimeout: { + activityText.fadeOut = true + } + } +//! [possrc] + function printableMethod(method) { + if (method === PositionSource.SatellitePositioningMethods) + return "Satellite"; + else if (method === PositionSource.NoPositioningMethods) + return "Not available" + else if (method === PositionSource.NonSatellitePositioningMethods) + return "Non-satellite" + else if (method === PositionSource.AllPositioningMethods) + return "Multiple" + return "source error"; + } + + Grid { + id: locationGrid + columns: 2 + anchors {left: parent.left; leftMargin: 5; top: locateButton.bottom; topMargin: 5} + spacing: 5 + Text {color: "white"; font.bold: true + text: "Lat:"; style: Text.Raised; styleColor: "black" + } + Text {id: latitudeValue; color: "white"; font.bold: true + text: positionSource.position.coordinate.latitude; style: Text.Raised; styleColor: "black"; + } + Text {color: "white"; font.bold: true + text: "Lon:"; style: Text.Raised; styleColor: "black" + } + Text {id: longitudeValue; color: "white"; font.bold: true + text: positionSource.position.coordinate.longitude; style: Text.Raised; styleColor: "black" + } + } + Image { + id: planet + anchors {top: locationGrid.bottom; left: parent.left; leftMargin: locationGrid.anchors.leftMargin} + source: "images/moon.png" + width: 30; height: 30 + } + Text {id: sourceText; color: "white"; font.bold: true; + anchors {left: planet.right; leftMargin: 5; verticalCenter: planet.verticalCenter} + text: "Source: " + printableMethod(positionSource.supportedPositioningMethods); style: Text.Raised; styleColor: "black"; + } + + Text { + id: activityText; color: "white"; font.bold: true; + anchors { top: planet.bottom; horizontalCenter: parent.horizontalCenter } + property bool fadeOut: false + + text: { + if (fadeOut) + return qsTr("Timeout occurred!"); + else if (positionSource.active) + return qsTr("Retrieving update...") + else + return "" + } + + Timer { + id: fadeoutTimer; repeat: false; interval: 3000; running: activityText.fadeOut + onTriggered: { activityText.fadeOut = false; } + } + } +} diff --git a/examples/positioning/geoflickr/flickrmobile/GridDelegate.qml b/examples/positioning/geoflickr/flickrmobile/GridDelegate.qml new file mode 100644 index 0000000..362317f --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/GridDelegate.qml @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Window 2.0 + + Component { + id: photoDelegate + Item { + id: wrapper; width: 79; height: 79 + + function photoClicked() { + imageDetails.photoTitle = title; + imageDetails.photoDate = datetaken; + imageDetails.photoUrl = "http://farm" + farm + ".static.flickr.com/" + server + "/" + id + "_" + secret + ".jpg"; + console.log(imageDetails.photoUrl); + scaleMe.state = "Details"; + } + + Item { + anchors.centerIn: parent + scale: 0.0 + Behavior on scale { NumberAnimation { easing.type: Easing.InOutQuad} } + id: scaleMe + + Rectangle { height: 79; width: 79; id: blackRect; anchors.centerIn: parent; color: "black"; smooth: true } + Rectangle { + id: whiteRect; width: 76; height: 76; anchors.centerIn: parent; color: "#dddddd"; smooth: true + Image { id: thumb; + // source: imagePath; + source: imageDetails.photoUrl = "http://farm" + farm + ".static.flickr.com/" + server + "/" + id + "_" + secret + "_t.jpg" + width: parent.width; height: parent.height + x: 1; y: 1; smooth: true} + Image { source: "images/gloss.png" } + } + + Connections { + target: toolBar + onButton2Clicked: if (scaleMe.state == 'Details' ) scaleMe.state = 'Show' + } + + states: [ + State { + name: "Show"; when: thumb.status == Image.Ready + PropertyChanges { target: scaleMe; scale: Math.round(Screen.pixelDensity / 4) } + }, + State { + name: "Details" + PropertyChanges { target: scaleMe; scale: Math.round(Screen.pixelDensity / 4)} + ParentChange { target: wrapper; parent: imageDetails.frontContainer } + PropertyChanges { target: wrapper; x: 20; y: 60; z: 1000 } + PropertyChanges { target: background; state: "DetailedView" } + } + ] + transitions: [ + Transition { + from: "Show"; to: "Details" + ParentAnimation { + NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad } + } + }, + Transition { + from: "Details"; to: "Show" + SequentialAnimation { + ParentAnimation { + NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad } + } + PropertyAction { targets: wrapper; properties: "z" } + } + } + ] + } + MouseArea { anchors.fill: wrapper; onClicked: { photoClicked() } } + } + } diff --git a/examples/positioning/geoflickr/flickrmobile/ImageDetails.qml b/examples/positioning/geoflickr/flickrmobile/ImageDetails.qml new file mode 100644 index 0000000..c11c0aa --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/ImageDetails.qml @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import "../flickrcommon" as Common + +Flipable { + id: container + + property variant frontContainer: containerFront + property string photoTitle: "" + property string photoDate + property string photoUrl + property variant prevScale: 1.0 + + signal closed + + transform: Rotation { + id: itemRotation + origin.x: container.width / 2; + axis.y: 1; axis.z: 0 + } + + front: Item { + id: containerFront; anchors.fill: container + + Rectangle { + anchors.fill: parent + color: "black"; opacity: 0.4 + } + + Column { + spacing: 10 + anchors { + left: parent.left; leftMargin: 20 + right: parent.right; rightMargin: 20 + top: parent.top; topMargin: 180 + } + Text { font.bold: true; color: "white"; elide: Text.ElideRight; text: container.photoTitle } + Text { color: "white"; elide: Text.ElideRight; text: "Published: " + container.photoDate } + } + } + + back: Item { + anchors.fill: container + + Rectangle { anchors.fill: parent; color: "black"; opacity: 0.4 } + + Common.Progress { + anchors.centerIn: parent; width: 200; height: 18 + progress: bigImage.progress; visible: bigImage.status != Image.Ready + } + + Flickable { + id: flickable; anchors.fill: parent; clip: true + contentWidth: imageContainer.width; contentHeight: imageContainer.height + + Item { + id: imageContainer + width: Math.max(bigImage.width * bigImage.scale, flickable.width); + height: Math.max(bigImage.height * bigImage.scale, flickable.height); + + Image { + id: bigImage; // source: container.photoUrl + source: container.photoUrl + scale: slider.value + anchors.centerIn: parent; smooth: !flickable.movingVertically + onStatusChanged : { + // Default scale shows the entire image. + if (status == Image.Ready && width != 0) { + slider.minimum = Math.min(flickable.width / width, flickable.height / height); + prevScale = Math.min(slider.minimum, 1); + slider.value = prevScale; + } + } + } + } + } + + Text { + text: "Image Unavailable" + visible: bigImage.status == Image.Error + anchors.centerIn: parent; color: "white"; font.bold: true + } + + Common.Slider { + id: slider; visible: { bigImage.status == Image.Ready && maximum > minimum } + anchors { + bottom: parent.bottom; bottomMargin: 65 + left: parent.left; leftMargin: 25 + right: parent.right; rightMargin: 25 + } + onValueChanged: { + if (bigImage.width * value > flickable.width) { + var xoff = (flickable.width/2 + flickable.contentX) * value / prevScale; + flickable.contentX = xoff - flickable.width/2; + } + if (bigImage.height * value > flickable.height) { + var yoff = (flickable.height/2 + flickable.contentY) * value / prevScale; + flickable.contentY = yoff - flickable.height/2; + } + prevScale = value; + } + } + } + + states: State { + name: "Back" + PropertyChanges { target: itemRotation; angle: 180 } + } + + transitions: Transition { + SequentialAnimation { + PropertyAction { target: bigImage; property: "smooth"; value: false } + NumberAnimation { easing.type: Easing.InOutQuad; properties: "angle"; duration: 500 } + PropertyAction { target: bigImage; property: "smooth"; value: !flickable.movingVertically } + } + } +} diff --git a/examples/positioning/geoflickr/flickrmobile/ListDelegate.qml b/examples/positioning/geoflickr/flickrmobile/ListDelegate.qml new file mode 100644 index 0000000..c10c859 --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/ListDelegate.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + Component { + Item { + id: wrapper; width: wrapper.ListView.view.width; height: 86 + Item { + id: moveMe + Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 } + Rectangle { + x: 6; y: 4; width: 76; height: 76; color: "white"; smooth: true + + Image { + //source: imagePath; + source: "http://farm" + farm + ".static.flickr.com/" + server + "/" + id + "_" + secret + "_t.jpg" + width: parent.width; height: parent.height + x: 0; y: 0 } + + Image { source: "images/gloss.png" } + } + Column { + x: 92; width: wrapper.ListView.view.width - 95; y: 15; spacing: 2 + Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black" } + Text { text: datetaken; width: parent.width; elide: Text.ElideRight; color: "#cccccc"; style: Text.Raised; styleColor: "black" } + } + } + } +} diff --git a/examples/positioning/geoflickr/flickrmobile/TitleBar.qml b/examples/positioning/geoflickr/flickrmobile/TitleBar.qml new file mode 100644 index 0000000..7fd7262 --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/TitleBar.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: titleBar + BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 } + + Item { + id: container + width: (parent.width * 2) - 55 ; height: parent.height + + Image { + id: quitButton + anchors.left: parent.left//; anchors.leftMargin: 0 + anchors.verticalCenter: parent.verticalCenter + source: "images/quit.png" + MouseArea { + anchors.fill: parent + onClicked: Qt.quit() + } + } + + Text { + id: categoryText + anchors { + left: quitButton.right; leftMargin: 10; rightMargin: 10 + verticalCenter: parent.verticalCenter + } + elide: Text.ElideLeft + text: "GeoFlickr (QML)" + font.bold: true; color: "White"; style: Text.Raised; styleColor: "Black" + } + } + + transitions: Transition { + NumberAnimation { properties: "x"; easing.type: Easing.InOutQuad } + } +} diff --git a/examples/positioning/geoflickr/flickrmobile/ToolBar.qml b/examples/positioning/geoflickr/flickrmobile/ToolBar.qml new file mode 100644 index 0000000..1c921cb --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/ToolBar.qml @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: toolbar + + property alias button1Label: button1.text + property alias button2Label: button2.text + signal button1Clicked + signal button2Clicked + + BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 } + + Button { + id: button1 + anchors.left: parent.left; anchors.leftMargin: 5; y: 3; width: 140; height: 32 + onClicked: toolbar.button1Clicked() + } + + Button { + id: button2 + anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 140; height: 32 + onClicked: toolbar.button2Clicked() + } +} diff --git a/examples/positioning/geoflickr/flickrmobile/images/gloss.png b/examples/positioning/geoflickr/flickrmobile/images/gloss.png new file mode 100644 index 0000000..dff2bd3 Binary files /dev/null and b/examples/positioning/geoflickr/flickrmobile/images/gloss.png differ diff --git a/examples/positioning/geoflickr/flickrmobile/images/lineedit.png b/examples/positioning/geoflickr/flickrmobile/images/lineedit.png new file mode 100644 index 0000000..a6afb51 Binary files /dev/null and b/examples/positioning/geoflickr/flickrmobile/images/lineedit.png differ diff --git a/examples/positioning/geoflickr/flickrmobile/images/lineedit.sci b/examples/positioning/geoflickr/flickrmobile/images/lineedit.sci new file mode 100644 index 0000000..054bff7 --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/images/lineedit.sci @@ -0,0 +1,5 @@ +border.left: 10 +border.top: 10 +border.bottom: 10 +border.right: 10 +source: lineedit.png diff --git a/examples/positioning/geoflickr/flickrmobile/images/moon.png b/examples/positioning/geoflickr/flickrmobile/images/moon.png new file mode 100644 index 0000000..1583ac8 Binary files /dev/null and b/examples/positioning/geoflickr/flickrmobile/images/moon.png differ diff --git a/examples/positioning/geoflickr/flickrmobile/images/quit.png b/examples/positioning/geoflickr/flickrmobile/images/quit.png new file mode 100644 index 0000000..aef7385 Binary files /dev/null and b/examples/positioning/geoflickr/flickrmobile/images/quit.png differ diff --git a/examples/positioning/geoflickr/flickrmobile/images/star.png b/examples/positioning/geoflickr/flickrmobile/images/star.png new file mode 100644 index 0000000..bdcd369 Binary files /dev/null and b/examples/positioning/geoflickr/flickrmobile/images/star.png differ diff --git a/examples/positioning/geoflickr/flickrmobile/images/stripes.png b/examples/positioning/geoflickr/flickrmobile/images/stripes.png new file mode 100644 index 0000000..75d2bf6 Binary files /dev/null and b/examples/positioning/geoflickr/flickrmobile/images/stripes.png differ diff --git a/examples/positioning/geoflickr/flickrmobile/images/sun.png b/examples/positioning/geoflickr/flickrmobile/images/sun.png new file mode 100644 index 0000000..c5fd36e Binary files /dev/null and b/examples/positioning/geoflickr/flickrmobile/images/sun.png differ diff --git a/examples/positioning/geoflickr/flickrmobile/images/titlebar.png b/examples/positioning/geoflickr/flickrmobile/images/titlebar.png new file mode 100644 index 0000000..aa35c9e Binary files /dev/null and b/examples/positioning/geoflickr/flickrmobile/images/titlebar.png differ diff --git a/examples/positioning/geoflickr/flickrmobile/images/titlebar.sci b/examples/positioning/geoflickr/flickrmobile/images/titlebar.sci new file mode 100644 index 0000000..0418d94 --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/images/titlebar.sci @@ -0,0 +1,5 @@ +border.left: 10 +border.top: 12 +border.bottom: 12 +border.right: 10 +source: titlebar.png diff --git a/examples/positioning/geoflickr/flickrmobile/images/toolbutton.png b/examples/positioning/geoflickr/flickrmobile/images/toolbutton.png new file mode 100644 index 0000000..1131001 Binary files /dev/null and b/examples/positioning/geoflickr/flickrmobile/images/toolbutton.png differ diff --git a/examples/positioning/geoflickr/flickrmobile/images/toolbutton.sci b/examples/positioning/geoflickr/flickrmobile/images/toolbutton.sci new file mode 100644 index 0000000..9e4f965 --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/images/toolbutton.sci @@ -0,0 +1,5 @@ +border.left: 15 +border.top: 4 +border.bottom: 4 +border.right: 15 +source: toolbutton.png diff --git a/examples/positioning/geoflickr/flickrmobile/nmealog.txt b/examples/positioning/geoflickr/flickrmobile/nmealog.txt new file mode 100644 index 0000000..8c8286d --- /dev/null +++ b/examples/positioning/geoflickr/flickrmobile/nmealog.txt @@ -0,0 +1,1403 @@ +$GPGGA,222437.000,2734.33926,S,15305.44310,E,1,07,1.3,50.6,M,39.2,M,,*72 +$GPGLL,2734.33926,S,15305.44310,E,222437.000,A,A*49 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222437.000,13.3,7.4,6.6,85.1,6.0,6.8,13.7*56 +$GPGSV,3,1,10,16,49,115,42,25,39,269,36,23,58,176,29,20,72,335,35*75 +$GPGSV,3,2,10,19,02,028,,04,06,241,22,13,30,223,30,27,19,284,35*78 +$GPGSV,3,3,10,11,06,337,30,03,13,055,25*7C +$GPRMC,222437.000,A,2734.33926,S,15305.44310,E,33.9,157.8,030308,11.2,W,A*0F +$GPVTG,157.8,T,169.0,M,33.9,N,62.9,K,A*22 +$GPGGA,222438.000,2734.34821,S,15305.44697,E,1,07,1.2,50.8,M,39.2,M,,*79 +$GPGLL,2734.34821,S,15305.44697,E,222438.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222438.000,12.4,6.4,9.3,16.2,6.1,8.3,16.4*5F +$GPGSV,3,1,10,16,49,115,41,25,39,269,36,23,58,176,28,20,72,335,36*74 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,28,27,19,284,35*73 +$GPGSV,3,3,10,11,06,337,28,03,13,055,25*75 +$GPRMC,222438.000,A,2734.34821,S,15305.44697,E,33.8,158.3,030308,11.2,W,A*0E +$GPVTG,158.3,T,169.5,M,33.8,N,62.5,K,A*2E +$GPGGA,222439.000,2734.35696,S,15305.45072,E,1,06,1.7,51.2,M,39.2,M,,*78 +$GPGLL,2734.35696,S,15305.45072,E,222439.000,A,A*43 +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222439.000,10.3,9.1,12.2,44.6,9.8,9.9,25.2*62 +$GPGSV,3,1,10,16,49,115,34,25,39,269,36,23,58,175,29,20,72,335,35*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,27,27,19,284,32*7B +$GPGSV,3,3,10,11,06,337,28,03,14,055,25*72 +$GPRMC,222439.000,A,2734.35696,S,15305.45072,E,33.2,158.7,030308,11.2,W,A*0E +$GPVTG,158.7,T,169.9,M,33.2,N,61.5,K,A*2F +$GPGGA,222440.000,2734.36580,S,15305.45446,E,1,07,1.3,52.0,M,39.2,M,,*76 +$GPGLL,2734.36580,S,15305.45446,E,222440.000,A,A*49 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222440.000,13.0,8.0,13.4,6.2,7.4,12.2,20.9*64 +$GPGSV,3,1,10,16,49,115,40,25,39,269,38,23,58,175,31,20,72,335,34*72 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,26,27,19,284,30*78 +$GPGSV,3,3,10,11,06,337,26,03,14,055,25*7C +$GPRMC,222440.000,A,2734.36580,S,15305.45446,E,33.7,159.1,030308,11.2,W,A*06 +$GPVTG,159.1,T,170.3,M,33.7,N,62.4,K,A*2D +$GPGGA,222441.000,2734.37483,S,15305.45825,E,1,07,1.3,52.7,M,39.2,M,,*7A +$GPGLL,2734.37483,S,15305.45825,E,222441.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222441.000,14.0,7.6,14.1,17.6,7.7,12.5,21.0*51 +$GPGSV,3,1,10,16,49,115,41,25,39,269,39,23,58,175,29,20,72,335,35*7A +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,24,27,19,284,30*7A +$GPGSV,3,3,10,11,06,337,28,03,14,055,25*72 +$GPRMC,222441.000,A,2734.37483,S,15305.45825,E,34.6,159.4,030308,11.2,W,A*0E +$GPVTG,159.4,T,170.6,M,34.6,N,64.1,K,A*28 +$GPGGA,222442.000,2734.38407,S,15305.46216,E,1,06,1.3,53.3,M,39.2,M,,*77 +$GPGLL,2734.38407,S,15305.46216,E,222442.000,A,A*4B +$GPGSA,A,3,16,25,20,13,27,11,,,,,,,2.3,1.3,1.9*3C +$GPGST,222442.000,16.6,7.0,14.4,14.6,7.0,12.8,21.6*5A +$GPGSV,3,1,10,16,49,115,40,25,39,269,38,23,58,175,22,20,72,335,35*71 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,25,27,19,284,29*73 +$GPGSV,3,3,10,11,06,337,27,03,14,055,25*7D +$GPRMC,222442.000,A,2734.38407,S,15305.46216,E,35.5,159.3,030308,11.2,W,A*02 +$GPVTG,159.3,T,170.5,M,35.5,N,65.8,K,A*26 +$GPGGA,222443.000,2734.39347,S,15305.46609,E,1,05,1.8,53.8,M,39.2,M,,*7D +$GPGLL,2734.39347,S,15305.46609,E,222443.000,A,A*42 +$GPGSA,A,3,16,25,20,27,11,,,,,,,,2.8,1.8,2.1*35 +$GPGST,222443.000,11.3,6.5,14.6,14.5,6.6,13.0,18.4*5A +$GPGSV,3,1,10,16,49,115,40,25,39,269,38,23,58,175,22,20,72,335,36*72 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,26,27,19,284,31*79 +$GPGSV,3,3,10,11,06,337,28,03,14,055,25*72 +$GPRMC,222443.000,A,2734.39347,S,15305.46609,E,36.2,159.4,030308,11.2,W,A*08 +$GPVTG,159.4,T,170.6,M,36.2,N,67.0,K,A*2C +$GPGGA,222444.000,2734.40297,S,15305.47000,E,1,06,1.3,54.1,M,39.2,M,,*70 +$GPGLL,2734.40297,S,15305.47000,E,222444.000,A,A*49 +$GPGSA,A,3,16,25,20,13,27,11,,,,,,,2.3,1.3,1.9*3C +$GPGST,222444.000,17.6,6.3,12.7,14.4,6.3,11.4,16.2*55 +$GPGSV,3,1,10,16,49,115,38,25,39,269,38,23,58,175,22,20,72,335,35*7E +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,25,27,19,284,29*73 +$GPGSV,3,3,10,11,06,337,25,03,14,055,23*79 +$GPRMC,222444.000,A,2734.40297,S,15305.47000,E,36.5,159.5,030308,11.2,W,A*05 +$GPVTG,159.5,T,170.8,M,36.5,N,67.5,K,A*21 +$GPGGA,222445.000,2734.41247,S,15305.47390,E,1,07,1.3,54.2,M,39.2,M,,*75 +$GPGLL,2734.41247,S,15305.47390,E,222445.000,A,A*4E +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222445.000,16.0,7.0,14.4,10.4,6.7,13.0,20.7*52 +$GPGSV,3,1,10,16,49,115,36,25,39,269,36,23,58,175,22,20,72,335,34*7F +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,26,27,19,284,31*79 +$GPGSV,3,3,10,11,06,337,26,03,14,055,23*7A +$GPRMC,222445.000,A,2734.41247,S,15305.47390,E,36.6,159.7,030308,11.2,W,A*03 +$GPVTG,159.7,T,170.9,M,36.6,N,67.8,K,A*2C +$GPGGA,222446.000,2734.42201,S,15305.47790,E,1,07,1.3,54.4,M,39.2,M,,*75 +$GPGLL,2734.42201,S,15305.47790,E,222446.000,A,A*48 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222446.000,13.0,7.4,12.3,6.6,6.9,11.2,17.9*60 +$GPGSV,3,1,10,16,49,115,36,25,39,269,37,23,58,175,27,20,72,335,35*7A +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,30,223,30,27,19,284,32*7E +$GPGSV,3,3,10,11,06,337,27,03,14,055,23*7B +$GPRMC,222446.000,A,2734.42201,S,15305.47790,E,36.6,159.3,030308,11.2,W,A*01 +$GPVTG,159.3,T,170.5,M,36.6,N,67.7,K,A*2B +$GPGGA,222447.000,2734.43157,S,15305.48195,E,1,07,1.3,54.3,M,39.2,M,,*7E +$GPGLL,2734.43157,S,15305.48195,E,222447.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222447.000,10.7,6.7,10.5,6.6,6.2,9.6,15.5*5B +$GPGSV,3,1,11,16,49,115,32,25,39,269,37,23,58,175,28,20,72,335,33*76 +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,30,223,30,27,19,284,32*7F +$GPGSV,3,3,11,11,06,337,29,01,,,19,03,14,055,23*7D +$GPRMC,222447.000,A,2734.43157,S,15305.48195,E,36.7,159.1,030308,11.2,W,A*0E +$GPVTG,159.1,T,170.3,M,36.7,N,67.9,K,A*20 +$GPGGA,222448.000,2734.44111,S,15305.48610,E,1,08,1.1,54.1,M,39.2,M,,*71 +$GPGLL,2734.44111,S,15305.48610,E,222448.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222448.000,20.4,10.5,8.8,52.5,8.7,9.1,15.2*6C +$GPGSV,3,1,11,16,49,115,27,25,39,269,38,23,58,175,26,20,72,335,31*71 +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,30,223,37,27,19,284,27*7C +$GPGSV,3,3,11,11,06,337,27,01,,,19,03,14,055,23*73 +$GPRMC,222448.000,A,2734.44111,S,15305.48610,E,36.8,158.7,030308,11.2,W,A*06 +$GPVTG,158.7,T,169.9,M,36.8,N,68.2,K,A*2E +$GPGGA,222449.000,2734.45068,S,15305.49044,E,1,08,1.1,53.6,M,39.2,M,,*78 +$GPGLL,2734.45068,S,15305.49044,E,222449.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222449.000,17.1,8.8,10.2,14.2,8.2,9.3,17.4*6D +$GPGSV,3,1,11,16,49,115,28,25,39,269,37,23,58,175,25,20,72,335,28*7A +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,30,223,37,27,19,284,32*78 +$GPGSV,3,3,11,11,06,337,27,01,,,19,03,14,055,24*74 +$GPRMC,222449.000,A,2734.45068,S,15305.49044,E,37.2,157.8,030308,11.2,W,A*04 +$GPVTG,157.8,T,169.0,M,37.2,N,68.9,K,A*27 +$GPGGA,222450.000,2734.46041,S,15305.49485,E,1,08,1.1,53.3,M,39.2,M,,*74 +$GPGLL,2734.46041,S,15305.49485,E,222450.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222450.000,17.4,8.9,12.7,10.1,11.5,8.2,16.5*5E +$GPGSV,3,1,11,16,49,115,25,25,39,269,36,23,58,175,30,20,72,336,28*71 +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,38,27,19,284,34*73 +$GPGSV,3,3,11,11,06,337,27,01,,,19,03,14,055,22*72 +$GPRMC,222450.000,A,2734.46041,S,15305.49485,E,37.7,157.9,030308,11.2,W,A*09 +$GPVTG,157.9,T,169.1,M,37.7,N,69.8,K,A*22 +$GPGGA,222451.000,2734.47033,S,15305.49924,E,1,08,1.1,53.1,M,39.2,M,,*75 +$GPGLL,2734.47033,S,15305.49924,E,222451.000,A,A*47 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222451.000,14.1,8.0,10.5,14.3,9.5,7.5,15.0*61 +$GPGSV,3,1,11,16,49,115,27,25,39,269,38,23,58,175,28,20,72,336,25*79 +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,38,27,19,284,34*73 +$GPGSV,3,3,11,11,06,337,24,01,,,19,03,14,055,25*76 +$GPRMC,222451.000,A,2734.47033,S,15305.49924,E,38.1,158.1,030308,11.2,W,A*04 +$GPVTG,158.1,T,169.3,M,38.1,N,70.5,K,A*2B +$GPGGA,222452.000,2734.48022,S,15305.50375,E,1,08,1.1,52.5,M,39.2,M,,*7A +$GPGLL,2734.48022,S,15305.50375,E,222452.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222452.000,24.1,13.9,9.7,80.6,12.7,9.0,21.0*54 +$GPGSV,3,1,11,16,49,115,29,25,39,269,38,23,58,175,27,20,72,336,30*7C +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,35,27,19,284,34*7E +$GPGSV,3,3,11,11,06,337,22,01,,,19,03,14,055,24*71 +$GPRMC,222452.000,A,2734.48022,S,15305.50375,E,38.3,157.9,030308,11.2,W,A*0B +$GPVTG,157.9,T,169.1,M,38.3,N,70.9,K,A*20 +$GPGGA,222453.000,2734.49019,S,15305.50802,E,1,06,1.7,52.1,M,39.2,M,,*75 +$GPGLL,2734.49019,S,15305.50802,E,222453.000,A,A*4E +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222453.000,10.4,15.4,9.3,66.3,13.4,9.6,24.6*52 +$GPGSV,3,1,11,16,49,115,31,25,39,269,36,23,58,175,28,20,71,336,25*73 +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,33,27,19,284,31*7D +$GPGSV,3,3,11,11,06,337,22,01,,,19,03,14,055,24*71 +$GPRMC,222453.000,A,2734.49019,S,15305.50802,E,38.3,159.1,030308,11.2,W,A*0E +$GPVTG,159.1,T,170.3,M,38.3,N,70.9,K,A*2C +$GPGGA,222454.000,2734.50008,S,15305.51221,E,1,07,1.3,52.1,M,39.2,M,,*75 +$GPGLL,2734.50008,S,15305.51221,E,222454.000,A,A*4B +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222454.000,12.5,11.7,8.3,70.6,10.4,8.0,19.0*5E +$GPGSV,3,1,11,16,49,115,30,25,39,269,36,23,58,175,26,20,71,336,28*71 +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,32,27,19,284,30*7D +$GPGSV,3,3,11,11,06,337,24,01,,,18,03,14,055,24*76 +$GPRMC,222454.000,A,2734.50008,S,15305.51221,E,38.1,159.4,030308,11.2,W,A*0C +$GPVTG,159.4,T,170.6,M,38.1,N,70.5,K,A*22 +$GPGGA,222455.000,2734.50992,S,15305.51642,E,1,07,1.3,52.2,M,39.2,M,,*7C +$GPGLL,2734.50992,S,15305.51642,E,222455.000,A,A*41 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222455.000,11.5,10.8,9.3,83.5,9.9,8.6,23.3*65 +$GPGSV,3,1,11,16,49,115,33,25,39,269,36,23,58,175,32,20,71,336,31*7F +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,29,27,19,284,29*7F +$GPGSV,3,3,11,11,06,337,28,01,,,18,03,14,055,24*7A +$GPRMC,222455.000,A,2734.50992,S,15305.51642,E,37.8,159.0,030308,11.2,W,A*04 +$GPVTG,159.0,T,170.2,M,37.8,N,70.0,K,A*21 +$GPGGA,222456.000,2734.51963,S,15305.52059,E,1,07,1.3,52.5,M,39.2,M,,*78 +$GPGLL,2734.51963,S,15305.52059,E,222456.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222456.000,11.3,9.0,13.1,11.0,8.4,11.9,20.9*55 +$GPGSV,3,1,11,16,49,115,31,25,39,269,37,23,58,175,27,20,71,336,33*7A +$GPGSV,3,2,11,19,02,028,,04,06,241,19,13,30,223,29,27,19,284,32*7E +$GPGSV,3,3,11,11,06,337,30,01,,,18,03,14,055,24*73 +$GPRMC,222456.000,A,2734.51963,S,15305.52059,E,37.3,158.8,030308,11.2,W,A*05 +$GPVTG,158.8,T,170.0,M,37.3,N,69.1,K,A*28 +$GPGGA,222457.000,2734.52908,S,15305.52467,E,1,06,1.3,53.2,M,39.2,M,,*79 +$GPGLL,2734.52908,S,15305.52467,E,222457.000,A,A*44 +$GPGSA,A,3,16,25,20,13,27,11,,,,,,,2.3,1.3,1.9*3C +$GPGST,222457.000,20.4,7.8,12.0,8.1,7.3,10.9,17.9*63 +$GPGSV,3,1,11,16,49,115,37,25,39,269,37,23,58,175,24,20,71,336,35*79 +$GPGSV,3,2,11,19,02,028,,04,06,241,19,13,30,223,29,27,19,284,32*7E +$GPGSV,3,3,11,11,06,337,28,01,,,18,03,14,055,23*7D +$GPRMC,222457.000,A,2734.52908,S,15305.52467,E,36.2,158.7,030308,11.2,W,A*0C +$GPVTG,158.7,T,169.9,M,36.2,N,67.1,K,A*28 +$GPGGA,222458.000,2734.53845,S,15305.52866,E,1,06,1.6,54.2,M,39.2,M,,*70 +$GPGLL,2734.53845,S,15305.52866,E,222458.000,A,A*4F +$GPGSA,A,3,16,25,23,20,27,11,,,,,,,2.6,1.6,2.1*34 +$GPGST,222458.000,16.7,7.3,13.9,11.0,7.0,12.5,17.9*5D +$GPGSV,3,1,11,16,49,115,36,25,39,269,37,23,58,175,24,20,71,336,35*78 +$GPGSV,3,2,11,19,02,028,19,04,06,241,19,13,30,223,26,27,19,284,31*7A +$GPGSV,3,3,11,11,06,337,23,01,,,18,03,14,055,23*76 +$GPRMC,222458.000,A,2734.53845,S,15305.52866,E,35.9,159.1,030308,11.2,W,A*08 +$GPVTG,159.1,T,170.3,M,35.9,N,66.5,K,A*20 +$GPGGA,222459.000,2734.54772,S,15305.53309,E,1,08,1.1,55.6,M,39.2,M,,*72 +$GPGLL,2734.54772,S,15305.53309,E,222459.000,A,A*41 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222459.000,17.5,6.5,9.3,15.5,6.1,8.3,15.2*5C +$GPGSV,3,1,11,16,49,115,38,25,39,268,36,23,58,175,35,20,71,336,35*76 +$GPGSV,3,2,11,19,02,028,19,04,06,241,19,13,30,223,33,27,19,284,34*7B +$GPGSV,3,3,11,11,06,337,29,01,,,18,03,14,055,22*7D +$GPRMC,222459.000,A,2734.54772,S,15305.53309,E,35.9,156.8,030308,11.2,W,A*00 +$GPVTG,156.8,T,168.0,M,35.9,N,66.4,K,A*2D +$GPGGA,222500.000,2734.55655,S,15305.53845,E,1,08,1.1,56.1,M,39.2,M,,*7D +$GPGLL,2734.55655,S,15305.53845,E,222500.000,A,A*4A +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222500.000,14.5,9.8,7.9,83.3,7.3,9.0,14.3*5C +$GPGSV,3,1,11,16,49,115,36,25,39,268,31,23,58,175,39,20,71,336,33*75 +$GPGSV,3,2,11,19,02,028,21,04,06,241,19,13,30,223,30,27,19,284,29*7F +$GPGSV,3,3,11,11,06,337,25,01,,,18,03,14,055,28*7B +$GPRMC,222500.000,A,2734.55655,S,15305.53845,E,35.9,151.6,030308,11.2,W,A*02 +$GPVTG,151.6,T,162.8,M,35.9,N,66.5,K,A*27 +$GPGGA,222501.000,2734.56495,S,15305.54489,E,1,08,1.1,57.0,M,39.2,M,,*7A +$GPGLL,2734.56495,S,15305.54489,E,222501.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222501.000,14.3,8.0,10.9,27.0,8.0,9.5,15.6*64 +$GPGSV,3,1,11,16,49,115,41,25,39,268,31,23,58,175,36,20,71,336,31*78 +$GPGSV,3,2,11,19,02,028,21,04,06,241,19,13,30,223,27,27,19,284,29*79 +$GPGSV,3,3,11,11,06,337,22,01,,,18,03,14,055,31*74 +$GPRMC,222501.000,A,2734.56495,S,15305.54489,E,36.5,145.7,030308,11.2,W,A*0E +$GPVTG,145.7,T,156.9,M,36.5,N,67.5,K,A*2B +$GPGGA,222502.000,2734.57337,S,15305.55181,E,1,06,1.5,57.9,M,39.2,M,,*78 +$GPGLL,2734.57337,S,15305.55181,E,222502.000,A,A*4C +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222502.000,14.5,7.0,11.9,20.7,7.1,10.5,15.0*5F +$GPGSV,3,1,11,16,49,115,43,25,39,268,35,23,58,175,37,20,71,336,34*7A +$GPGSV,3,2,11,19,02,028,21,04,06,241,19,13,30,223,23,27,19,284,33*76 +$GPGSV,3,3,11,11,06,337,22,01,,,18,03,14,055,34*71 +$GPRMC,222502.000,A,2734.57337,S,15305.55181,E,37.4,143.8,030308,11.2,W,A*06 +$GPVTG,143.8,T,155.0,M,37.4,N,69.3,K,A*20 +$GPGGA,222503.000,2734.58184,S,15305.55887,E,1,08,1.1,58.5,M,39.2,M,,*7A +$GPGLL,2734.58184,S,15305.55887,E,222503.000,A,A*47 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222503.000,13.4,6.4,14.1,0.3,5.9,12.9,21.5*60 +$GPGSV,3,1,11,16,49,115,43,25,39,268,35,23,58,175,38,20,71,336,35*74 +$GPGSV,3,2,11,19,02,028,19,04,06,241,19,13,30,223,23,27,19,284,32*7C +$GPGSV,3,3,11,11,06,337,26,01,,,17,03,14,055,34*7A +$GPRMC,222503.000,A,2734.58184,S,15305.55887,E,37.8,143.4,030308,11.2,W,A*0D +$GPVTG,143.4,T,154.6,M,37.8,N,70.0,K,A*2C +$GPGGA,222504.000,2734.59032,S,15305.56580,E,1,07,1.2,58.9,M,39.2,M,,*79 +$GPGLL,2734.59032,S,15305.56580,E,222504.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222504.000,24.6,6.2,13.3,3.6,5.7,12.2,20.2*67 +$GPGSV,3,1,11,16,49,115,43,25,39,268,35,23,58,175,39,20,71,336,35*75 +$GPGSV,3,2,11,19,02,028,19,04,06,241,19,13,30,223,22,27,19,284,31*7E +$GPGSV,3,3,11,11,06,337,25,01,,,17,03,14,055,30*7D +$GPRMC,222504.000,A,2734.59032,S,15305.56580,E,37.6,143.6,030308,11.2,W,A*02 +$GPVTG,143.6,T,154.8,M,37.6,N,69.7,K,A*21 +$GPGGA,222505.000,2734.59874,S,15305.57271,E,1,06,1.5,59.4,M,39.2,M,,*70 +$GPGLL,2734.59874,S,15305.57271,E,222505.000,A,A*47 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222505.000,17.4,5.5,11.8,3.4,5.0,10.8,17.3*61 +$GPGSV,3,1,11,16,49,115,44,25,39,268,35,23,58,175,39,20,71,336,36*71 +$GPGSV,3,2,11,19,02,028,21,04,06,241,19,13,30,223,24,27,19,284,31*73 +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,29*72 +$GPRMC,222505.000,A,2734.59874,S,15305.57271,E,37.3,143.7,030308,11.2,W,A*05 +$GPVTG,143.7,T,154.9,M,37.3,N,69.1,K,A*22 +$GPGGA,222506.000,2734.60703,S,15305.57943,E,1,07,1.2,60.1,M,39.2,M,,*75 +$GPGLL,2734.60703,S,15305.57943,E,222506.000,A,A*4B +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222506.000,16.1,6.2,11.7,15.3,6.1,10.4,17.4*54 +$GPGSV,3,1,11,16,49,115,43,25,39,268,34,23,58,175,37,20,71,336,36*79 +$GPGSV,3,2,11,19,02,028,21,04,06,241,,13,30,223,24,27,19,284,31*7B +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,28*73 +$GPRMC,222506.000,A,2734.60703,S,15305.57943,E,36.5,143.9,030308,11.2,W,A*00 +$GPVTG,143.9,T,155.1,M,36.5,N,67.6,K,A*2B +$GPGGA,222507.000,2734.61507,S,15305.58593,E,1,07,1.2,60.9,M,39.2,M,,*75 +$GPGLL,2734.61507,S,15305.58593,E,222507.000,A,A*43 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222507.000,14.0,6.8,11.8,10.9,6.4,10.7,18.5*54 +$GPGSV,3,1,11,16,49,115,43,25,39,268,34,23,58,175,37,20,71,336,34*7B +$GPGSV,3,2,11,19,02,028,21,04,06,241,,13,30,223,29,27,19,284,34*73 +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,29*72 +$GPRMC,222507.000,A,2734.61507,S,15305.58593,E,35.4,143.9,030308,11.2,W,A*0A +$GPVTG,143.9,T,155.1,M,35.4,N,65.5,K,A*28 +$GPGGA,222508.000,2734.62275,S,15305.59221,E,1,06,1.7,61.8,M,39.2,M,,*70 +$GPGLL,2734.62275,S,15305.59221,E,222508.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222508.000,12.5,9.3,16.3,19.5,9.4,14.4,27.5*51 +$GPGSV,3,1,11,16,49,115,43,25,39,268,33,23,58,175,38,20,71,336,31*76 +$GPGSV,3,2,11,19,02,028,21,04,06,241,,13,30,223,30,27,19,284,35*7A +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,28*73 +$GPRMC,222508.000,A,2734.62275,S,15305.59221,E,33.9,143.9,030308,11.2,W,A*00 +$GPVTG,143.9,T,155.1,M,33.9,N,62.9,K,A*28 +$GPGGA,222509.000,2734.63006,S,15305.59817,E,1,06,1.7,62.7,M,39.2,M,,*75 +$GPGLL,2734.63006,S,15305.59817,E,222509.000,A,A*4B +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222509.000,10.4,8.1,14.2,21.9,8.4,12.3,23.7*52 +$GPGSV,3,1,11,16,49,115,44,25,39,268,32,23,58,175,37,20,71,336,29*76 +$GPGSV,3,2,11,19,02,028,21,04,06,241,,13,30,223,28,27,19,284,35*73 +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,30*7A +$GPRMC,222509.000,A,2734.63006,S,15305.59817,E,32.2,143.9,030308,11.2,W,A*03 +$GPVTG,143.9,T,155.1,M,32.2,N,59.7,K,A*24 +$GPGGA,222510.000,2734.63706,S,15305.60376,E,1,06,1.7,63.5,M,39.2,M,,*7F +$GPGLL,2734.63706,S,15305.60376,E,222510.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222510.000,12.4,8.3,12.9,28.0,8.7,11.0,21.6*57 +$GPGSV,3,1,11,16,48,115,43,25,39,268,32,23,58,175,37,20,71,336,29*70 +$GPGSV,3,2,11,19,02,028,20,04,06,241,,13,30,223,31,27,19,284,35*7A +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,25*7E +$GPRMC,222510.000,A,2734.63706,S,15305.60376,E,30.6,144.3,030308,11.2,W,A*01 +$GPVTG,144.3,T,155.5,M,30.6,N,56.7,K,A*24 +$GPGGA,222511.000,2734.64376,S,15305.60904,E,1,07,1.2,64.4,M,39.2,M,,*77 +$GPGLL,2734.64376,S,15305.60904,E,222511.000,A,A*48 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222511.000,14.6,5.7,10.5,2.7,5.2,9.6,15.0*5C +$GPGSV,3,1,11,16,48,115,44,25,39,268,32,23,58,175,37,20,71,336,28*76 +$GPGSV,3,2,11,19,02,028,20,04,06,241,23,13,30,223,29,27,19,284,36*71 +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,29*72 +$GPRMC,222511.000,A,2734.64376,S,15305.60904,E,29.1,144.2,030308,11.2,W,A*05 +$GPVTG,144.2,T,155.4,M,29.1,N,53.9,K,A*20 +$GPGGA,222512.000,2734.64992,S,15305.61405,E,1,07,1.2,65.4,M,39.2,M,,*78 +$GPGLL,2734.64992,S,15305.61405,E,222512.000,A,A*46 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222512.000,13.4,17.0,5.7,85.6,5.3,15.5,23.6*5A +$GPGSV,3,1,11,16,48,115,45,25,39,268,33,23,58,175,38,20,71,336,28*79 +$GPGSV,3,2,11,19,02,028,20,04,06,241,23,13,30,223,26,27,19,284,33*7B +$GPGSV,3,3,11,11,06,337,24,01,,,17,03,14,055,27*7A +$GPRMC,222512.000,A,2734.64992,S,15305.61405,E,27.2,143.6,030308,11.2,W,A*05 +$GPVTG,143.6,T,154.8,M,27.2,N,50.5,K,A*2C +$GPGGA,222513.000,2734.65572,S,15305.61884,E,1,07,1.2,66.2,M,39.2,M,,*7A +$GPGLL,2734.65572,S,15305.61884,E,222513.000,A,A*41 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222513.000,12.3,7.0,14.8,2.4,6.5,13.5,21.4*6D +$GPGSV,3,1,10,16,48,115,44,25,39,268,35,23,58,175,38,20,71,336,28*7F +$GPGSV,3,2,10,19,02,028,20,04,06,241,23,13,30,223,23,27,19,284,33*7F +$GPGSV,3,3,10,11,06,337,24,03,14,055,28*73 +$GPRMC,222513.000,A,2734.65572,S,15305.61884,E,25.8,143.6,030308,11.2,W,A*0A +$GPVTG,143.6,T,154.8,M,25.8,N,47.9,K,A*2E +$GPGGA,222514.000,2734.66155,S,15305.62364,E,1,06,1.5,67.0,M,39.2,M,,*7C +$GPGLL,2734.66155,S,15305.62364,E,222514.000,A,A*42 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222514.000,25.5,6.1,14.4,3.1,5.6,13.2,19.2*6A +$GPGSV,3,1,10,16,48,115,44,25,39,268,33,23,58,175,38,20,71,336,26*77 +$GPGSV,3,2,10,19,02,028,18,04,06,241,23,13,30,223,23,27,19,284,34*73 +$GPGSV,3,3,10,11,06,337,28,03,14,055,29*7E +$GPRMC,222514.000,A,2734.66155,S,15305.62364,E,25.9,143.6,030308,11.2,W,A*08 +$GPVTG,143.6,T,154.8,M,25.9,N,48.0,K,A*29 +$GPGGA,222515.000,2734.66761,S,15305.62860,E,1,06,1.5,67.5,M,39.2,M,,*76 +$GPGLL,2734.66761,S,15305.62860,E,222515.000,A,A*4D +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222515.000,20.1,5.5,13.0,3.0,5.1,11.8,17.4*68 +$GPGSV,3,1,10,16,48,115,44,25,39,268,32,23,58,175,38,20,71,336,26*76 +$GPGSV,3,2,10,19,02,028,18,04,06,241,23,13,30,223,24,27,19,284,34*74 +$GPGSV,3,3,10,11,06,337,28,03,14,055,24*73 +$GPRMC,222515.000,A,2734.66761,S,15305.62860,E,26.9,143.7,030308,11.2,W,A*05 +$GPVTG,143.7,T,154.9,M,26.9,N,49.8,K,A*23 +$GPGGA,222516.000,2734.67384,S,15305.63376,E,1,06,1.5,68.2,M,39.2,M,,*7E +$GPGLL,2734.67384,S,15305.63376,E,222516.000,A,A*4D +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222516.000,16.4,5.8,11.5,4.5,5.3,10.5,17.3*6A +$GPGSV,3,1,10,16,48,115,44,25,39,268,32,23,58,175,38,20,71,336,30*71 +$GPGSV,3,2,10,19,02,028,18,04,06,241,23,13,30,223,24,27,19,284,33*73 +$GPGSV,3,3,10,11,06,337,28,03,14,055,28*7F +$GPRMC,222516.000,A,2734.67384,S,15305.63376,E,27.7,143.8,030308,11.2,W,A*05 +$GPVTG,143.8,T,155.0,M,27.7,N,51.4,K,A*2E +$GPGGA,222517.000,2734.68035,S,15305.63901,E,1,06,1.5,68.8,M,39.2,M,,*79 +$GPGLL,2734.68035,S,15305.63901,E,222517.000,A,A*40 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222517.000,19.1,6.2,12.1,7.2,5.8,11.0,15.3*66 +$GPGSV,3,1,10,16,48,115,44,25,39,268,34,23,58,175,38,20,71,336,32*75 +$GPGSV,3,2,10,19,02,028,20,04,06,241,23,13,30,223,24,27,19,284,34*7F +$GPGSV,3,3,10,11,06,337,24,03,14,055,29*72 +$GPRMC,222517.000,A,2734.68035,S,15305.63901,E,28.6,144.1,030308,11.2,W,A*08 +$GPVTG,144.1,T,155.3,M,28.6,N,53.0,K,A*2B +$GPGGA,222518.000,2734.68718,S,15305.64446,E,1,07,1.4,69.1,M,39.2,M,,*7F +$GPGLL,2734.68718,S,15305.64446,E,222518.000,A,A*4E +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222518.000,13.8,5.5,10.6,5.8,5.1,9.6,13.4*54 +$GPGSV,3,1,10,16,48,115,43,25,39,268,33,23,58,175,37,20,71,336,35*7D +$GPGSV,3,2,10,19,02,028,20,04,06,241,18,13,30,223,24,27,19,284,33*70 +$GPGSV,3,3,10,11,06,337,22,03,14,055,33*7F +$GPRMC,222518.000,A,2734.68718,S,15305.64446,E,29.9,144.4,030308,11.2,W,A*0D +$GPVTG,144.4,T,155.6,M,29.9,N,55.3,K,A*20 +$GPGGA,222519.000,2734.69424,S,15305.65010,E,1,07,1.4,69.5,M,39.2,M,,*71 +$GPGLL,2734.69424,S,15305.65010,E,222519.000,A,A*44 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222519.000,14.0,13.4,5.0,89.4,4.6,12.3,18.8*58 +$GPGSV,3,1,10,16,48,115,44,25,39,268,34,23,58,175,37,20,71,336,37*7F +$GPGSV,3,2,10,19,02,028,20,04,06,241,18,13,30,223,23,27,19,284,31*75 +$GPGSV,3,3,10,11,06,337,26,03,14,055,35*7D +$GPRMC,222519.000,A,2734.69424,S,15305.65010,E,31.0,144.4,030308,11.2,W,A*07 +$GPVTG,144.4,T,155.6,M,31.0,N,57.5,K,A*24 +$GPGGA,222520.000,2734.70163,S,15305.65604,E,1,07,1.4,69.6,M,39.2,M,,*75 +$GPGLL,2734.70163,S,15305.65604,E,222520.000,A,A*43 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222520.000,9.8,11.6,4.7,89.0,4.3,10.6,15.9*6A +$GPGSV,3,1,10,16,48,115,44,25,39,268,35,23,58,175,39,20,71,336,36*71 +$GPGSV,3,2,10,19,02,028,20,04,06,241,19,13,30,223,23,27,19,284,31*74 +$GPGSV,3,3,10,11,06,337,31,03,14,055,37*79 +$GPRMC,222520.000,A,2734.70163,S,15305.65604,E,32.5,144.1,030308,11.2,W,A*03 +$GPVTG,144.1,T,155.3,M,32.5,N,60.2,K,A*21 +$GPGGA,222521.000,2734.70923,S,15305.66218,E,1,07,1.4,69.5,M,39.2,M,,*71 +$GPGLL,2734.70923,S,15305.66218,E,222521.000,A,A*44 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222521.000,11.1,6.2,10.8,9.6,5.8,9.8,16.8*53 +$GPGSV,3,1,10,16,48,115,44,25,39,268,36,23,58,175,40,20,71,336,38*72 +$GPGSV,3,2,10,19,02,028,20,04,06,241,19,13,30,223,23,27,19,284,26*72 +$GPGSV,3,3,10,11,06,338,31,03,14,055,37*76 +$GPRMC,222521.000,A,2734.70923,S,15305.66218,E,33.5,144.0,030308,11.2,W,A*04 +$GPVTG,144.0,T,155.3,M,33.5,N,62.0,K,A*21 +$GPGGA,222522.000,2734.71700,S,15305.66845,E,1,06,1.5,69.1,M,39.2,M,,*7A +$GPGLL,2734.71700,S,15305.66845,E,222522.000,A,A*4B +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222522.000,15.0,5.7,9.9,5.5,5.2,9.0,15.4*68 +$GPGSV,3,1,10,16,48,115,43,25,39,268,36,23,58,175,40,20,71,336,37*7A +$GPGSV,3,2,10,19,02,028,20,04,06,241,24,13,30,223,23,27,19,284,26*7C +$GPGSV,3,3,10,11,06,338,25,03,14,055,37*73 +$GPRMC,222522.000,A,2734.71700,S,15305.66845,E,34.2,144.1,030308,11.2,W,A*0A +$GPVTG,144.1,T,155.3,M,34.2,N,63.4,K,A*25 +$GPGGA,222523.000,2734.72487,S,15305.67483,E,1,07,1.4,68.6,M,39.2,M,,*75 +$GPGLL,2734.72487,S,15305.67483,E,222523.000,A,A*42 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222523.000,13.8,5.2,10.1,3.9,4.8,9.2,13.8*5B +$GPGSV,3,1,10,16,48,115,44,25,39,268,37,23,58,175,41,20,71,336,35*7F +$GPGSV,3,2,10,19,02,028,20,04,06,241,24,13,30,223,23,27,19,284,26*7C +$GPGSV,3,3,10,11,06,338,23,03,14,055,31*73 +$GPRMC,222523.000,A,2734.72487,S,15305.67483,E,34.7,144.2,030308,11.2,W,A*05 +$GPVTG,144.2,T,155.4,M,34.7,N,64.3,K,A*24 +$GPGGA,222524.000,2734.73280,S,15305.68126,E,1,07,1.4,68.1,M,39.2,M,,*70 +$GPGLL,2734.73280,S,15305.68126,E,222524.000,A,A*40 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222524.000,10.5,4.9,9.4,3.5,4.5,8.6,12.8*60 +$GPGSV,3,1,10,16,48,115,44,25,39,268,37,23,58,175,41,20,71,336,35*7F +$GPGSV,3,2,10,19,02,028,20,04,06,241,22,13,30,223,23,27,19,284,26*7A +$GPGSV,3,3,10,11,06,338,25,03,14,055,29*7C +$GPRMC,222524.000,A,2734.73280,S,15305.68126,E,35.0,144.2,030308,11.2,W,A*01 +$GPVTG,144.2,T,155.4,M,35.0,N,64.9,K,A*28 +$GPGGA,222525.000,2734.74083,S,15305.68778,E,1,07,1.4,67.7,M,39.2,M,,*73 +$GPGLL,2734.74083,S,15305.68778,E,222525.000,A,A*4A +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222525.000,10.3,5.2,13.4,3.6,4.8,12.3,20.4*6B +$GPGSV,3,1,10,16,48,115,43,25,39,268,38,23,58,175,40,20,71,336,36*75 +$GPGSV,3,2,10,19,02,028,20,04,06,241,22,13,30,223,23,27,19,284,23*7F +$GPGSV,3,3,10,11,06,338,27,03,14,055,36*70 +$GPRMC,222525.000,A,2734.74083,S,15305.68778,E,35.6,144.2,030308,11.2,W,A*0D +$GPVTG,144.2,T,155.4,M,35.6,N,65.9,K,A*2F +$GPGGA,222526.000,2734.74894,S,15305.69428,E,1,06,1.5,67.2,M,39.2,M,,*7C +$GPGLL,2734.74894,S,15305.69428,E,222526.000,A,A*40 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222526.000,8.0,5.7,12.0,2.6,5.2,10.9,17.4*54 +$GPGSV,3,1,10,16,48,115,43,25,39,268,37,23,58,175,40,20,71,336,35*79 +$GPGSV,3,2,10,19,02,028,20,04,06,241,22,13,30,223,23,27,19,284,24*78 +$GPGSV,3,3,10,11,06,338,27,03,14,055,39*7F +$GPRMC,222526.000,A,2734.74894,S,15305.69428,E,35.8,144.5,030308,11.2,W,A*0E +$GPVTG,144.5,T,155.7,M,35.8,N,66.3,K,A*2C +$GPGGA,222527.000,2734.75707,S,15305.70075,E,1,05,1.7,66.8,M,39.2,M,,*77 +$GPGLL,2734.75707,S,15305.70075,E,222527.000,A,A*41 +$GPGSA,A,3,16,25,23,20,03,,,,,,,,2.9,1.7,2.4*39 +$GPGST,222527.000,13.9,6.3,10.9,6.3,5.9,10.0,18.2*60 +$GPGSV,3,1,10,16,48,115,44,25,39,268,38,23,58,175,40,20,71,336,33*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,30,223,23,27,19,284,26*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,36*75 +$GPRMC,222527.000,A,2734.75707,S,15305.70075,E,35.8,144.6,030308,11.2,W,A*0C +$GPVTG,144.6,T,155.8,M,35.8,N,66.2,K,A*21 +$GPGGA,222528.000,2734.76518,S,15305.70724,E,1,06,1.5,66.1,M,39.2,M,,*7C +$GPGLL,2734.76518,S,15305.70724,E,222528.000,A,A*42 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222528.000,11.3,5.6,10.1,4.5,5.2,9.2,16.1*51 +$GPGSV,3,1,10,16,48,115,43,25,39,268,39,23,58,175,39,20,71,336,28*75 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,30,223,23,27,19,284,26*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,36*75 +$GPRMC,222528.000,A,2734.76518,S,15305.70724,E,35.7,144.4,030308,11.2,W,A*02 +$GPVTG,144.4,T,155.6,M,35.7,N,66.2,K,A*22 +$GPGGA,222529.000,2734.77313,S,15305.71385,E,1,06,1.5,66.1,M,39.2,M,,*7F +$GPGLL,2734.77313,S,15305.71385,E,222529.000,A,A*41 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222529.000,10.9,5.6,12.5,5.4,5.2,11.4,20.9*6F +$GPGSV,3,1,10,16,48,115,41,25,39,268,40,23,58,175,36,20,71,336,28*76 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,30,223,23,27,19,284,24*7D +$GPGSV,3,3,10,11,06,338,27,03,14,055,30*76 +$GPRMC,222529.000,A,2734.77313,S,15305.71385,E,35.6,143.5,030308,11.2,W,A*06 +$GPVTG,143.5,T,154.7,M,35.6,N,65.8,K,A*2C +$GPGGA,222530.000,2734.78106,S,15305.72042,E,1,06,1.5,66.0,M,39.2,M,,*74 +$GPGLL,2734.78106,S,15305.72042,E,222530.000,A,A*4B +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222530.000,9.4,5.4,18.9,2.4,4.9,17.3,30.6*54 +$GPGSV,3,1,10,16,48,115,40,25,39,268,40,23,58,175,36,20,71,336,28*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,30,223,23,27,19,284,26*7F +$GPGSV,3,3,10,11,06,338,27,03,14,055,29*7E +$GPRMC,222530.000,A,2734.78106,S,15305.72042,E,35.5,143.7,030308,11.2,W,A*0D +$GPVTG,143.7,T,155.0,M,35.5,N,65.8,K,A*2B +$GPGGA,222531.000,2734.78918,S,15305.72691,E,1,05,4.4,66.0,M,39.2,M,,*7D +$GPGLL,2734.78918,S,15305.72691,E,222531.000,A,A*45 +$GPGSA,A,3,16,25,23,27,11,,,,,,,,9.3,4.4,8.2*36 +$GPGST,222531.000,9.1,8.5,53.9,3.2,8.2,49.2,81.3*56 +$GPGSV,3,1,10,16,48,115,40,25,39,268,39,23,58,175,37,20,71,336,28*78 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,31,223,23,27,19,284,25*7D +$GPGSV,3,3,10,11,06,338,24,03,14,055,22*76 +$GPRMC,222531.000,A,2734.78918,S,15305.72691,E,35.9,144.5,030308,11.2,W,A*0A +$GPVTG,144.5,T,155.7,M,35.9,N,66.4,K,A*2A +$GPGGA,222532.000,2734.79737,S,15305.73347,E,1,06,1.5,66.0,M,39.2,M,,*74 +$GPGLL,2734.79737,S,15305.73347,E,222532.000,A,A*4B +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222532.000,11.0,6.8,38.7,1.2,6.3,35.3,58.4*69 +$GPGSV,3,1,10,16,48,115,40,25,39,268,39,23,58,175,36,20,71,336,28*79 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,31,223,24,27,19,284,23*7C +$GPGSV,3,3,10,11,06,338,24,03,14,055,30*75 +$GPRMC,222532.000,A,2734.79737,S,15305.73347,E,36.1,144.5,030308,11.2,W,A*0F +$GPVTG,144.5,T,155.7,M,36.1,N,66.9,K,A*2C +$GPGGA,222533.000,2734.80571,S,15305.74004,E,1,06,4.1,66.1,M,39.2,M,,*70 +$GPGLL,2734.80571,S,15305.74004,E,222533.000,A,A*4F +$GPGSA,A,3,16,25,23,27,11,03,,,,,,,8.3,4.1,7.3*3F +$GPGST,222533.000,9.4,6.1,45.5,0.4,5.6,41.6,69.5*50 +$GPGSV,3,1,10,16,48,115,40,25,39,268,39,23,58,175,37,20,71,336,28*78 +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,31,223,24,27,19,284,25*7C +$GPGSV,3,3,10,11,06,338,22,03,14,055,25*77 +$GPRMC,222533.000,A,2734.80571,S,15305.74004,E,36.6,145.0,030308,11.2,W,A*08 +$GPVTG,145.0,T,156.2,M,36.6,N,67.7,K,A*26 +$GPGGA,222534.000,2734.81441,S,15305.74656,E,1,06,1.8,65.2,M,39.2,M,,*79 +$GPGLL,2734.81441,S,15305.74656,E,222534.000,A,A*4A +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222534.000,20.2,5.8,45.7,1.7,5.4,41.7,71.3*6C +$GPGSV,3,1,10,16,48,115,40,25,39,268,38,23,58,175,37,20,71,336,28*79 +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,31,223,25,27,19,284,25*7D +$GPGSV,3,3,10,11,06,338,22,03,14,055,31*72 +$GPRMC,222534.000,A,2734.81441,S,15305.74656,E,37.6,146.2,030308,11.2,W,A*0D +$GPVTG,146.2,T,157.5,M,37.6,N,69.7,K,A*2E +$GPGGA,222535.000,2734.82349,S,15305.75307,E,1,05,1.9,63.5,M,39.2,M,,*77 +$GPGLL,2734.82349,S,15305.75307,E,222535.000,A,A*47 +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.6,1.9,3.1*3D +$GPGST,222535.000,27.6,7.0,40.6,3.1,6.7,37.1,68.4*6C +$GPGSV,3,1,10,16,48,115,40,25,39,268,36,23,58,175,37,20,71,336,28*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,31,223,25,27,19,284,23*78 +$GPGSV,3,3,10,11,06,338,22,03,14,055,26*74 +$GPRMC,222535.000,A,2734.82349,S,15305.75307,E,38.7,147.3,030308,11.2,W,A*0E +$GPVTG,147.3,T,158.6,M,38.7,N,71.7,K,A*25 +$GPGGA,222536.000,2734.83215,S,15305.75969,E,1,05,1.7,63.5,M,39.2,M,,*71 +$GPGLL,2734.83215,S,15305.75969,E,222536.000,A,A*4F +$GPGSA,A,3,16,25,23,20,03,,,,,,,,2.9,1.7,2.4*39 +$GPGST,222536.000,7.9,6.3,97.2,3.9,8.3,88.7,161.0*62 +$GPGSV,3,1,10,16,48,115,40,25,39,268,37,23,58,175,36,20,71,336,28*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,31,223,25,27,19,284,23*78 +$GPGSV,3,3,10,11,06,338,22,03,14,055,26*74 +$GPRMC,222536.000,A,2734.83215,S,15305.75969,E,37.6,145.6,030308,11.2,W,A*0F +$GPVTG,145.6,T,156.8,M,37.6,N,69.7,K,A*25 +$GPGGA,222537.000,2734.84076,S,15305.76655,E,1,05,1.7,63.5,M,39.2,M,,*73 +$GPGLL,2734.84076,S,15305.76655,E,222537.000,A,A*4D +$GPGSA,A,3,16,25,23,20,03,,,,,,,,2.9,1.7,2.4*39 +$GPGST,222537.000,16.0,7.8,110.8,2.1,8.0,101.2,209.1*57 +$GPGSV,3,1,10,16,48,115,39,25,39,268,36,23,58,175,34,20,71,336,28*7A +$GPGSV,3,2,10,19,02,028,,04,06,241,22,13,31,223,25,27,19,284,23*7A +$GPGSV,3,3,10,11,06,338,22,03,14,055,25*77 +$GPRMC,222537.000,A,2734.84076,S,15305.76655,E,37.9,144.6,030308,11.2,W,A*03 +$GPVTG,144.6,T,155.8,M,37.9,N,70.3,K,A*24 +$GPGGA,222538.000,2734.84945,S,15305.77356,E,1,05,1.9,63.5,M,39.2,M,,*7C +$GPGLL,2734.84945,S,15305.77356,E,222538.000,A,A*4C +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.6,1.9,3.1*3D +$GPGST,222538.000,13.1,8.0,61.7,1.6,7.5,56.4,113.0*51 +$GPGSV,3,1,10,16,48,115,40,25,39,268,37,23,58,175,32,20,71,336,*79 +$GPGSV,3,2,10,19,02,028,,04,06,241,22,13,31,223,25,27,19,284,23*7A +$GPGSV,3,3,10,11,06,338,22,03,14,055,28*7A +$GPRMC,222538.000,A,2734.84945,S,15305.77356,E,38.4,144.2,030308,11.2,W,A*04 +$GPVTG,144.2,T,155.4,M,38.4,N,71.1,K,A*2D +$GPGGA,222539.000,2734.85792,S,15305.78022,E,1,05,1.9,63.5,M,39.2,M,,*77 +$GPGLL,2734.85792,S,15305.78022,E,222539.000,A,A*47 +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.6,1.9,3.1*3D +$GPGST,222539.000,6.4,7.5,72.7,1.5,7.1,66.5,137.2*68 +$GPGSV,3,1,10,16,48,115,40,25,39,268,38,23,58,175,32,20,71,336,*76 +$GPGSV,3,2,10,19,02,028,,04,06,241,22,13,31,223,25,27,19,284,23*7A +$GPGSV,3,3,10,11,06,338,22,03,14,055,28*7A +$GPRMC,222539.000,A,2734.85792,S,15305.78022,E,37.1,144.9,030308,11.2,W,A*0E +$GPVTG,144.9,T,156.1,M,37.1,N,68.7,K,A*24 +$GPGGA,222540.000,2734.86604,S,15305.78646,E,1,05,4.4,63.5,M,39.2,M,,*78 +$GPGLL,2734.86604,S,15305.78646,E,222540.000,A,A*40 +$GPGSA,A,3,16,25,23,27,11,,,,,,,,9.3,4.4,8.2*36 +$GPGST,222540.000,13.6,8.3,67.7,1.8,7.8,61.9,111.1*55 +$GPGSV,3,1,10,16,48,115,40,25,39,268,38,23,58,175,32,20,71,336,*76 +$GPGSV,3,2,10,19,02,028,,04,06,241,26,13,31,223,22,27,19,284,22*78 +$GPGSV,3,3,10,11,06,338,20,03,14,055,28*78 +$GPRMC,222540.000,A,2734.86604,S,15305.78646,E,35.3,145.6,030308,11.2,W,A*07 +$GPVTG,145.6,T,156.8,M,35.3,N,65.4,K,A*2D +$GPGGA,222541.000,2734.87421,S,15305.79222,E,1,06,1.8,63.5,M,39.2,M,,*70 +$GPGLL,2734.87421,S,15305.79222,E,222541.000,A,A*42 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222541.000,11.7,33.3,8.1,87.4,7.5,30.4,54.6*51 +$GPGSV,3,1,10,16,48,115,39,25,39,268,33,23,58,175,36,20,71,336,*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,26,13,31,223,22,27,19,284,22*78 +$GPGSV,3,3,10,11,06,338,20,03,14,055,26*76 +$GPRMC,222541.000,A,2734.87421,S,15305.79222,E,34.6,147.7,030308,11.2,W,A*02 +$GPVTG,147.7,T,158.9,M,34.6,N,64.1,K,A*21 +$GPGGA,222542.000,2734.88135,S,15305.79765,E,1,06,1.8,63.5,M,39.2,M,,*7A +$GPGLL,2734.88135,S,15305.79765,E,222542.000,A,A*48 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222542.000,23.5,7.9,53.0,0.2,7.2,48.5,78.4*6F +$GPGSV,3,1,10,16,48,115,40,25,39,268,36,23,58,175,35,20,71,336,*7F +$GPGSV,3,2,10,19,02,028,,04,06,241,27,13,31,223,23,27,19,284,25*7F +$GPGSV,3,3,10,11,06,338,20,03,14,055,26*76 +$GPRMC,222542.000,A,2734.88135,S,15305.79765,E,31.0,145.8,030308,11.2,W,A*06 +$GPVTG,145.8,T,157.0,M,31.0,N,57.4,K,A*2C +$GPGGA,222543.000,2734.88798,S,15305.80287,E,1,07,1.2,63.0,M,39.2,M,,*7B +$GPGLL,2734.88798,S,15305.80287,E,222543.000,A,A*47 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222543.000,18.8,6.7,28.4,0.5,6.1,26.0,41.8*62 +$GPGSV,3,1,10,16,48,115,40,25,39,268,39,23,58,175,35,20,71,336,21*73 +$GPGSV,3,2,10,19,02,028,,04,06,241,37,13,31,223,22,27,19,284,24*7E +$GPGSV,3,3,10,11,06,338,20,03,14,055,32*73 +$GPRMC,222543.000,A,2734.88798,S,15305.80287,E,29.0,144.8,030308,11.2,W,A*01 +$GPVTG,144.8,T,156.0,M,29.0,N,53.8,K,A*2D +$GPGGA,222544.000,2734.89328,S,15305.80767,E,1,06,1.8,62.9,M,39.2,M,,*7A +$GPGLL,2734.89328,S,15305.80767,E,222544.000,A,A*45 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222544.000,14.9,35.2,5.8,89.5,5.4,32.2,52.6*52 +$GPGSV,3,1,10,16,48,115,43,25,39,268,40,23,58,175,25,20,71,336,21*7F +$GPGSV,3,2,10,19,02,028,,04,06,241,28,13,31,223,30,27,19,284,29*7E +$GPGSV,3,3,10,11,06,338,20,03,14,055,33*72 +$GPRMC,222544.000,A,2734.89328,S,15305.80767,E,24.5,140.9,030308,11.2,W,A*0E +$GPVTG,140.9,T,152.1,M,24.5,N,45.3,K,A*29 +$GPGGA,222545.000,2734.89633,S,15305.81084,E,1,05,1.9,62.9,M,39.2,M,,*7D +$GPGLL,2734.89633,S,15305.81084,E,222545.000,A,A*40 +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.6,1.9,3.1*3D +$GPGST,222545.000,19.5,6.0,33.0,1.0,5.5,30.2,52.4*69 +$GPGSV,3,1,10,16,48,115,41,25,39,268,34,23,58,175,29,20,71,336,30*72 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,31,223,29,27,19,284,30*73 +$GPGSV,3,3,10,11,06,338,20,03,14,055,30*71 +$GPRMC,222545.000,A,2734.89633,S,15305.81084,E,14.6,136.6,030308,11.2,W,A*05 +$GPVTG,136.6,T,147.8,M,14.6,N,27.0,K,A*2D +$GPGGA,222546.000,2734.89236,S,15305.81130,E,1,06,1.3,62.6,M,39.2,M,,*77 +$GPGLL,2734.89236,S,15305.81130,E,222546.000,A,A*4C +$GPGSA,A,3,16,25,23,20,13,03,,,,,,,2.3,1.3,1.9*3B +$GPGST,222546.000,11.5,5.6,15.6,0.9,5.2,14.3,26.4*6E +$GPGSV,3,1,10,16,48,115,35,25,39,268,40,23,58,175,41,20,71,336,38*74 +$GPGSV,3,2,10,19,02,028,,04,06,241,26,13,31,223,33,27,19,284,26*7C +$GPGSV,3,3,10,11,06,338,20,03,14,055,28*78 +$GPRMC,222546.000,A,2734.89236,S,15305.81130,E,16.9,2.1,030308,11.2,W,A*05 +$GPVTG,2.1,T,13.3,M,16.9,N,31.2,K,A*1F +$GPGGA,222547.000,2734.89429,S,15305.81239,E,1,05,2.3,62.5,M,39.2,M,,*77 +$GPGLL,2734.89429,S,15305.81239,E,222547.000,A,A*4F +$GPGSA,A,3,16,23,13,27,03,,,,,,,,4.6,2.3,3.9*39 +$GPGST,222547.000,11.4,38.3,9.7,69.8,14.7,33.0,49.2*6B +$GPGSV,3,1,10,16,48,115,32,25,39,268,37,23,58,175,42,20,71,336,37*7F +$GPGSV,3,2,10,19,02,028,,04,06,241,26,13,31,223,36,27,19,284,29*76 +$GPGSV,3,3,10,11,06,338,20,03,14,055,34*75 +$GPRMC,222547.000,A,2734.89429,S,15305.81239,E,8.4,154.5,030308,11.2,W,A*32 +$GPVTG,154.5,T,165.7,M,8.4,N,15.6,K,A*1D +$GPGGA,222548.000,2734.89474,S,15305.81253,E,1,07,1.2,62.0,M,39.2,M,,*79 +$GPGLL,2734.89474,S,15305.81253,E,222548.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222548.000,11.0,12.3,7.9,86.0,7.3,11.3,20.6*5F +$GPGSV,3,1,10,16,48,115,34,25,39,268,36,23,58,175,42,20,71,336,38*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,31,223,36,27,19,284,29*75 +$GPGSV,3,3,10,11,06,338,20,03,14,055,33*72 +$GPRMC,222548.000,A,2734.89474,S,15305.81253,E,0.3,353.0,030308,11.2,W,A*36 +$GPVTG,353.0,T,4.3,M,0.3,N,0.5,K,A*27 +$GPGGA,222549.000,2734.89490,S,15305.81265,E,1,04,2.0,61.8,M,39.2,M,,*7E +$GPGLL,2734.89490,S,15305.81265,E,222549.000,A,A*4A +$GPGSA,A,3,25,23,13,03,,,,,,,,,3.9,2.0,3.3*3D +$GPGST,222549.000,17.0,16.1,8.8,81.3,8.3,14.6,29.3*57 +$GPGSV,3,1,11,16,48,115,33,25,39,268,37,23,58,175,42,20,71,336,36*7E +$GPGSV,3,2,11,19,02,028,,04,06,241,25,13,31,223,35,27,19,284,30*7F +$GPGSV,3,3,11,11,06,338,20,01,,,21,03,14,055,33*71 +$GPRMC,222549.000,A,2734.89490,S,15305.81265,E,0.2,330.7,030308,11.2,W,A*3B +$GPVTG,330.7,T,341.9,M,0.2,N,0.3,K,A*2A +$GPGGA,222550.000,2734.89526,S,15305.81278,E,1,04,2.6,61.7,M,39.2,M,,*7F +$GPGLL,2734.89526,S,15305.81278,E,222550.000,A,A*42 +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.1,2.6,5.6*31 +$GPGST,222550.000,13.4,12.4,27.3,43.1,18.9,19.8,52.9*5A +$GPGSV,3,1,11,16,48,115,30,25,39,268,38,23,58,175,42,20,71,336,37*73 +$GPGSV,3,2,11,19,02,028,,04,06,241,25,13,31,223,36,27,19,284,31*7D +$GPGSV,3,3,11,11,06,338,,01,,,21,03,14,055,32*72 +$GPRMC,222550.000,A,2734.89526,S,15305.81278,E,0.1,350.7,030308,11.2,W,A*36 +$GPVTG,350.7,T,1.9,M,0.1,N,0.2,K,A*29 +$GPGGA,222551.000,2734.89528,S,15305.81279,E,1,05,2.3,61.7,M,39.2,M,,*75 +$GPGLL,2734.89528,S,15305.81279,E,222551.000,A,A*4C +$GPGSA,A,3,16,23,13,27,03,,,,,,,,4.6,2.3,3.9*39 +$GPGST,222551.000,13.7,31.0,11.1,60.5,16.5,25.2,39.3*5F +$GPGSV,3,1,11,16,48,115,30,25,39,268,39,23,58,175,41,20,71,336,35*73 +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,31,223,36,27,19,284,31*7B +$GPGSV,3,3,11,11,06,338,,01,,,20,03,14,055,30*71 +$GPRMC,222551.000,A,2734.89528,S,15305.81279,E,0.1,345.0,030308,11.2,W,A*3B +$GPVTG,345.0,T,356.2,M,0.1,N,0.2,K,A*20 +$GPGGA,222552.000,2734.89550,S,15305.81288,E,1,05,2.1,61.7,M,39.2,M,,*75 +$GPGLL,2734.89550,S,15305.81288,E,222552.000,A,A*4E +$GPGSA,A,3,16,25,23,13,27,,,,,,,,4.7,2.1,4.2*32 +$GPGST,222552.000,11.7,11.5,20.8,20.0,11.8,18.2,39.1*55 +$GPGSV,3,1,11,16,48,115,31,25,39,268,40,23,58,175,42,20,71,336,35*7F +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,31,223,38,27,19,284,31*75 +$GPGSV,3,3,11,11,06,338,,01,,,20,03,14,055,30*71 +$GPRMC,222552.000,A,2734.89550,S,15305.81288,E,0.1,11.2,030308,11.2,W,A*09 +$GPVTG,11.2,T,22.5,M,0.1,N,0.2,K,A*27 +$GPGGA,222553.000,2734.89573,S,15305.81294,E,1,05,2.1,61.5,M,39.2,M,,*7A +$GPGLL,2734.89573,S,15305.81294,E,222553.000,A,A*43 +$GPGSA,A,3,16,25,23,13,27,,,,,,,,4.7,2.1,4.2*32 +$GPGST,222553.000,9.8,10.3,17.6,19.1,10.4,15.6,33.7*6C +$GPGSV,3,1,10,16,48,115,29,25,39,268,38,23,58,175,41,20,71,336,37*79 +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,31,223,39,27,19,284,30*74 +$GPGSV,3,3,10,11,06,338,,03,14,055,29*7B +$GPRMC,222553.000,A,2734.89573,S,15305.81294,E,0.1,351.8,030308,11.2,W,A*39 +$GPVTG,351.8,T,3.0,M,0.1,N,0.2,K,A*2C +$GPGGA,222554.000,2734.89591,S,15305.81298,E,1,04,2.6,61.4,M,39.2,M,,*7A +$GPGLL,2734.89591,S,15305.81298,E,222554.000,A,A*44 +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.1,2.6,5.6*31 +$GPGST,222554.000,16.9,10.4,17.8,12.8,10.0,16.1,37.3*5F +$GPGSV,3,1,10,16,48,115,32,25,39,268,38,23,58,175,41,20,71,336,36*72 +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,31,223,38,27,19,284,31*74 +$GPGSV,3,3,10,11,06,338,,03,14,055,26*74 +$GPRMC,222554.000,A,2734.89591,S,15305.81298,E,0.1,334.9,030308,11.2,W,A*3C +$GPVTG,334.9,T,346.1,M,0.1,N,0.2,K,A*2D +$GPGGA,222555.000,2734.89607,S,15305.81301,E,1,04,2.6,61.2,M,39.2,M,,*70 +$GPGLL,2734.89607,S,15305.81301,E,222555.000,A,A*48 +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.1,2.6,5.6*31 +$GPGST,222555.000,14.4,11.9,23.3,40.8,16.2,17.6,44.5*56 +$GPGSV,3,1,11,16,48,115,32,25,39,268,37,23,58,175,40,20,71,336,38*73 +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,31,223,37,27,19,284,30*7B +$GPGSV,3,3,11,11,06,338,,01,,,20,03,14,055,25*75 +$GPRMC,222555.000,A,2734.89607,S,15305.81301,E,0.1,6.2,030308,11.2,W,A*39 +$GPVTG,6.2,T,17.4,M,0.1,N,0.2,K,A*16 +$GPGGA,222556.000,2734.89612,S,15305.81301,E,1,04,2.6,61.1,M,39.2,M,,*74 +$GPGLL,2734.89612,S,15305.81301,E,222556.000,A,A*4F +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.1,2.6,5.6*31 +$GPGST,222556.000,12.4,15.8,24.1,4.1,14.5,22.0,39.9*69 +$GPGSV,3,1,11,16,48,115,33,25,39,268,38,23,58,174,41,20,71,336,38*7D +$GPGSV,3,2,11,19,02,028,,04,06,242,23,13,31,223,38,27,19,284,32*75 +$GPGSV,3,3,11,11,06,338,,01,,,20,03,14,055,28*78 +$GPRMC,222556.000,A,2734.89612,S,15305.81301,E,0.1,21.8,030308,11.2,W,A*01 +$GPVTG,21.8,T,33.0,M,0.1,N,0.2,K,A*2B +$GPGGA,222557.000,2734.89635,S,15305.81337,E,1,05,2.1,61.0,M,39.2,M,,*72 +$GPGLL,2734.89635,S,15305.81337,E,222557.000,A,A*4E +$GPGSA,A,3,16,25,23,13,27,,,,,,,,4.7,2.1,4.2*32 +$GPGST,222557.000,10.3,13.0,15.0,5.2,11.9,13.7,32.7*6B +$GPGSV,3,1,10,16,48,115,33,25,39,268,38,23,58,174,41,20,71,336,36*72 +$GPGSV,3,2,10,19,02,028,,04,06,242,23,13,31,223,39,27,19,284,28*7E +$GPGSV,3,3,10,11,06,338,,03,14,055,31*72 +$GPRMC,222557.000,A,2734.89635,S,15305.81337,E,1.2,96.1,030308,11.2,W,A*07 +$GPVTG,96.1,T,107.3,M,1.2,N,2.2,K,A*1B +$GPGGA,222558.000,2734.89638,S,15305.81517,E,1,06,1.8,60.6,M,39.2,M,,*7A +$GPGLL,2734.89638,S,15305.81517,E,222558.000,A,A*48 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222558.000,18.6,12.9,7.5,72.4,7.5,11.4,21.9*57 +$GPGSV,3,1,10,16,48,115,39,25,39,268,38,23,58,174,37,20,71,336,26*78 +$GPGSV,3,2,10,19,02,028,,04,06,242,23,13,31,223,34,27,19,284,29*72 +$GPGSV,3,3,10,11,06,338,,03,14,055,30*73 +$GPRMC,222558.000,A,2734.89638,S,15305.81517,E,5.6,82.0,030308,11.2,W,A*05 +$GPVTG,82.0,T,93.2,M,5.6,N,10.3,K,A*10 +$GPGGA,222559.000,2734.89631,S,15305.81911,E,1,05,2.2,60.5,M,39.2,M,,*71 +$GPGLL,2734.89631,S,15305.81911,E,222559.000,A,A*4A +$GPGSA,A,3,16,25,23,20,27,,,,,,,,3.6,2.2,2.9*3A +$GPGST,222559.000,17.0,15.1,33.1,15.1,15.5,29.4,59.0*59 +$GPGSV,3,1,10,16,48,115,34,25,39,268,35,23,58,174,30,20,71,336,29*70 +$GPGSV,3,2,10,19,02,028,,04,06,242,23,13,31,223,35,27,19,284,28*72 +$GPGSV,3,3,10,11,06,338,,03,14,055,27*75 +$GPRMC,222559.000,A,2734.89631,S,15305.81911,E,12.5,87.6,030308,11.2,W,A*31 +$GPVTG,87.6,T,98.8,M,12.5,N,23.2,K,A*26 +$GPGGA,222600.000,2734.89436,S,15305.82359,E,1,06,1.8,61.2,M,39.2,M,,*72 +$GPGLL,2734.89436,S,15305.82359,E,222600.000,A,A*45 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222600.000,14.4,14.9,6.9,79.1,6.7,13.4,28.4*57 +$GPGSV,3,1,10,16,48,115,37,25,39,268,36,23,58,174,29,20,71,336,33*73 +$GPGSV,3,2,10,19,02,028,,04,06,242,23,13,31,223,39,27,19,284,28*7E +$GPGSV,3,3,10,11,06,338,,03,14,055,28*7A +$GPRMC,222600.000,A,2734.89436,S,15305.82359,E,15.9,62.5,030308,11.2,W,A*3D +$GPVTG,62.5,T,73.7,M,15.9,N,29.5,K,A*22 +$GPGGA,222601.000,2734.89190,S,15305.82850,E,1,06,1.8,60.5,M,39.2,M,,*7E +$GPGLL,2734.89190,S,15305.82850,E,222601.000,A,A*4F +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.6,1.8,3.1*39 +$GPGST,222601.000,11.5,13.4,6.1,78.5,6.0,12.0,24.9*56 +$GPGSV,3,1,10,16,48,115,40,25,39,268,27,23,58,174,35,20,71,336,28*74 +$GPGSV,3,2,10,19,02,028,,04,06,242,,13,31,223,39,27,19,284,27*70 +$GPGSV,3,3,10,11,06,338,,03,14,055,23*71 +$GPRMC,222601.000,A,2734.89190,S,15305.82850,E,18.0,58.9,030308,11.2,W,A*36 +$GPVTG,58.9,T,70.1,M,18.0,N,33.4,K,A*2C +$GPGGA,222602.000,2734.88904,S,15305.83361,E,1,05,1.6,60.0,M,39.2,M,,*79 +$GPGLL,2734.88904,S,15305.83361,E,222602.000,A,A*40 +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222602.000,11.3,17.1,6.5,54.9,10.2,13.2,18.6*62 +$GPGSV,3,1,10,16,48,115,27,25,39,268,29,23,58,174,33,20,71,336,33*77 +$GPGSV,3,2,10,19,02,028,,04,06,242,,13,31,223,35,27,19,284,32*78 +$GPGSV,3,3,10,11,06,338,,03,14,055,24*76 +$GPRMC,222602.000,A,2734.88904,S,15305.83361,E,19.8,55.1,030308,11.2,W,A*35 +$GPVTG,55.1,T,66.3,M,19.8,N,36.7,K,A*23 +$GPGGA,222603.000,2734.88556,S,15305.83944,E,1,04,3.8,58.8,M,39.2,M,,*70 +$GPGLL,2734.88556,S,15305.83944,E,222603.000,A,A*47 +$GPGSA,A,3,25,23,20,27,,,,,,,,,6.5,3.8,5.2*3C +$GPGST,222603.000,12.6,48.6,15.6,66.9,41.3,21.9,62.5*59 +$GPGSV,3,1,10,16,48,115,23,25,39,268,29,23,58,174,31,20,71,337,37*74 +$GPGSV,3,2,10,19,02,028,,04,06,242,,13,31,223,34,27,19,284,26*7C +$GPGSV,3,3,10,11,06,338,,03,14,055,28*7A +$GPRMC,222603.000,A,2734.88556,S,15305.83944,E,22.7,54.4,030308,11.2,W,A*31 +$GPVTG,54.4,T,65.6,M,22.7,N,42.1,K,A*23 +$GPGGA,222604.000,2734.88238,S,15305.84546,E,1,04,4.4,57.8,M,39.2,M,,*75 +$GPGLL,2734.88238,S,15305.84546,E,222604.000,A,A*46 +$GPGSA,A,3,25,20,13,27,,,,,,,,,7.2,4.4,5.7*37 +$GPGST,222604.000,10.4,46.8,10.9,81.3,42.4,11.8,57.5*57 +$GPGSV,3,1,10,16,48,115,27,25,39,268,32,23,58,174,32,20,71,337,37*79 +$GPGSV,3,2,10,19,02,028,,04,06,242,,13,31,223,34,27,19,284,34*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,29*7B +$GPRMC,222604.000,A,2734.88238,S,15305.84546,E,23.3,54.5,030308,11.2,W,A*34 +$GPVTG,54.5,T,65.7,M,23.3,N,43.2,K,A*24 +$GPGGA,222605.000,2734.87917,S,15305.85182,E,1,04,4.4,56.6,M,39.2,M,,*7F +$GPGLL,2734.87917,S,15305.85182,E,222605.000,A,A*43 +$GPGSA,A,3,25,20,13,27,,,,,,,,,7.2,4.4,5.7*37 +$GPGST,222605.000,14.3,40.3,10.1,81.5,36.5,10.7,49.8*58 +$GPGSV,3,1,10,16,48,115,24,25,39,268,32,23,58,174,33,20,71,337,37*7B +$GPGSV,3,2,10,19,02,028,,04,06,242,20,13,31,223,35,27,19,284,32*7A +$GPGSV,3,3,10,11,06,338,,03,14,055,26*74 +$GPRMC,222605.000,A,2734.87917,S,15305.85182,E,24.5,55.0,030308,11.2,W,A*34 +$GPVTG,55.0,T,66.2,M,24.5,N,45.3,K,A*20 +$GPGGA,222606.000,2734.87588,S,15305.85846,E,1,05,3.6,55.8,M,39.2,M,,*7E +$GPGLL,2734.87588,S,15305.85846,E,222606.000,A,A*4B +$GPGSA,A,3,25,23,20,13,27,,,,,,,,6.3,3.6,5.2*36 +$GPGST,222606.000,11.7,30.4,8.7,77.7,27.2,9.8,40.6*59 +$GPGSV,3,1,10,16,48,115,24,25,39,268,31,23,58,174,32,20,71,337,34*7A +$GPGSV,3,2,10,19,02,029,,04,06,242,20,13,31,223,35,27,19,284,34*7D +$GPGSV,3,3,10,11,06,338,,03,14,055,24*76 +$GPRMC,222606.000,A,2734.87588,S,15305.85846,E,25.3,55.9,030308,11.2,W,A*32 +$GPVTG,55.9,T,67.1,M,25.3,N,46.9,K,A*25 +$GPGGA,222607.000,2734.87218,S,15305.86543,E,1,06,1.8,55.5,M,39.2,M,,*78 +$GPGLL,2734.87218,S,15305.86543,E,222607.000,A,A*4F +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.6,1.8,3.1*39 +$GPGST,222607.000,11.2,13.8,8.5,86.1,7.8,12.6,27.3*52 +$GPGSV,3,1,10,16,48,115,29,25,39,268,26,23,58,174,34,20,71,337,32*71 +$GPGSV,3,2,10,19,02,029,,04,06,242,27,13,31,223,36,27,19,284,30*7D +$GPGSV,3,3,10,11,06,338,,03,14,055,24*76 +$GPRMC,222607.000,A,2734.87218,S,15305.86543,E,26.0,57.6,030308,11.2,W,A*3B +$GPVTG,57.6,T,68.8,M,26.0,N,48.1,K,A*28 +$GPGGA,222608.000,2734.86867,S,15305.87251,E,1,06,1.8,55.1,M,39.2,M,,*75 +$GPGLL,2734.86867,S,15305.87251,E,222608.000,A,A*46 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.6,1.8,3.1*39 +$GPGST,222608.000,15.1,15.8,7.1,68.8,8.0,13.6,36.7*5C +$GPGSV,3,1,10,16,48,115,39,25,39,268,28,23,58,174,35,20,71,337,30*7D +$GPGSV,3,2,10,19,02,029,,04,06,242,27,13,31,223,40,27,19,284,28*75 +$GPGSV,3,3,10,11,06,338,,03,14,055,28*7A +$GPRMC,222608.000,A,2734.86867,S,15305.87251,E,25.9,60.7,030308,11.2,W,A*3D +$GPVTG,60.7,T,71.9,M,25.9,N,47.9,K,A*29 +$GPGGA,222609.000,2734.86555,S,15305.87973,E,1,06,1.8,54.7,M,39.2,M,,*74 +$GPGLL,2734.86555,S,15305.87973,E,222609.000,A,A*40 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.6,1.8,3.1*39 +$GPGST,222609.000,10.9,10.9,5.1,85.4,4.7,10.0,22.0*55 +$GPGSV,3,1,10,16,48,116,34,25,39,268,39,23,58,174,29,20,71,337,33*7D +$GPGSV,3,2,10,19,02,029,,04,06,242,24,13,31,223,42,27,19,284,23*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,26*74 +$GPRMC,222609.000,A,2734.86555,S,15305.87973,E,25.7,64.3,030308,11.2,W,A*35 +$GPVTG,64.3,T,75.6,M,25.7,N,47.5,K,A*20 +$GPGGA,222610.000,2734.86253,S,15305.88695,E,1,05,1.9,54.1,M,39.2,M,,*71 +$GPGLL,2734.86253,S,15305.88695,E,222610.000,A,A*41 +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.7,1.9,3.1*3C +$GPGST,222610.000,11.1,14.6,7.4,64.7,8.3,12.4,28.7*57 +$GPGSV,3,1,10,16,48,116,29,25,39,268,42,23,58,174,28,20,71,337,32*7D +$GPGSV,3,2,10,19,02,029,,04,06,242,24,13,31,223,42,27,19,284,23*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,24*76 +$GPRMC,222610.000,A,2734.86253,S,15305.88695,E,25.3,65.0,030308,11.2,W,A*32 +$GPVTG,65.0,T,76.3,M,25.3,N,46.8,K,A*2C +$GPGGA,222611.000,2734.85924,S,15305.89387,E,1,05,2.2,53.4,M,39.2,M,,*75 +$GPGLL,2734.85924,S,15305.89387,E,222611.000,A,A*4F +$GPGSA,A,3,16,25,23,20,13,,,,,,,,5.3,2.2,4.8*39 +$GPGST,222611.000,17.7,8.4,21.7,17.4,9.4,19.0,57.8*57 +$GPGSV,3,1,10,16,48,116,39,25,39,268,32,23,58,174,35,20,71,337,26*72 +$GPGSV,3,2,10,19,02,029,,04,06,242,31,13,31,223,39,27,19,284,24*70 +$GPGSV,3,3,10,11,06,338,,03,14,055,26*74 +$GPRMC,222611.000,A,2734.85924,S,15305.89387,E,24.9,61.4,030308,11.2,W,A*37 +$GPVTG,61.4,T,72.6,M,24.9,N,46.1,K,A*2F +$GPGGA,222612.000,2734.85516,S,15305.90007,E,1,07,1.2,53.3,M,39.2,M,,*7E +$GPGLL,2734.85516,S,15305.90007,E,222612.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222612.000,15.5,16.3,8.2,77.8,8.0,14.7,27.8*50 +$GPGSV,3,1,10,16,48,116,29,25,39,268,29,23,58,174,30,20,71,337,34*7F +$GPGSV,3,2,10,19,02,029,,04,06,242,27,13,31,223,35,27,19,284,28*77 +$GPGSV,3,3,10,11,06,338,,03,14,055,25*77 +$GPRMC,222612.000,A,2734.85516,S,15305.90007,E,24.5,53.1,030308,11.2,W,A*32 +$GPVTG,53.1,T,64.3,M,24.5,N,45.4,K,A*23 +$GPGGA,222613.000,2734.85043,S,15305.90565,E,1,05,1.9,53.2,M,39.2,M,,*73 +$GPGLL,2734.85043,S,15305.90565,E,222613.000,A,A*47 +$GPGSA,A,3,16,25,20,13,27,,,,,,,,3.7,1.9,3.2*3A +$GPGST,222613.000,21.1,11.0,20.9,21.8,11.7,18.1,48.5*55 +$GPGSV,3,1,10,16,48,116,30,25,39,268,32,23,58,174,24,20,71,337,36*7A +$GPGSV,3,2,10,19,02,029,,04,06,242,22,13,31,223,35,27,19,284,29*73 +$GPGSV,3,3,10,11,06,338,,03,14,055,29*7B +$GPRMC,222613.000,A,2734.85043,S,15305.90565,E,24.9,45.4,030308,11.2,W,A*39 +$GPVTG,45.4,T,56.6,M,24.9,N,46.1,K,A*2F +$GPGGA,222614.000,2734.84523,S,15305.91064,E,1,05,1.9,53.2,M,39.2,M,,*73 +$GPGLL,2734.84523,S,15305.91064,E,222614.000,A,A*47 +$GPGSA,A,3,16,25,20,13,27,,,,,,,,3.7,1.9,3.2*3A +$GPGST,222614.000,18.8,16.8,28.3,28.1,18.2,24.0,43.4*54 +$GPGSV,3,1,10,16,48,116,27,25,39,268,30,23,58,174,32,20,71,337,35*7A +$GPGSV,3,2,10,19,02,029,,04,06,242,28,13,31,223,26,27,19,284,32*71 +$GPGSV,3,3,10,11,06,338,,03,14,055,30*73 +$GPRMC,222614.000,A,2734.84523,S,15305.91064,E,24.7,40.2,030308,11.2,W,A*34 +$GPVTG,40.2,T,51.4,M,24.7,N,45.7,K,A*22 +$GPGGA,222615.000,2734.84002,S,15305.91547,E,1,07,1.2,53.0,M,39.2,M,,*7B +$GPGLL,2734.84002,S,15305.91547,E,222615.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222615.000,19.7,18.9,7.9,71.0,8.8,16.5,18.9*52 +$GPGSV,3,1,10,16,48,116,25,25,39,268,26,23,58,174,35,20,71,337,34*79 +$GPGSV,3,2,10,19,02,029,,04,06,242,24,13,31,223,25,27,19,284,30*7C +$GPGSV,3,3,10,11,06,338,,03,14,055,29*7B +$GPRMC,222615.000,A,2734.84002,S,15305.91547,E,24.1,38.7,030308,11.2,W,A*3B +$GPVTG,38.7,T,49.9,M,24.1,N,44.7,K,A*2B +$GPGGA,222616.000,2734.83488,S,15305.92024,E,1,07,1.2,53.1,M,39.2,M,,*7B +$GPGLL,2734.83488,S,15305.92024,E,222616.000,A,A*45 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222616.000,18.1,15.8,11.2,70.8,10.8,14.1,19.9*51 +$GPGSV,3,1,10,16,48,116,27,25,39,268,29,23,58,174,34,20,71,337,30*71 +$GPGSV,3,2,10,19,02,029,,04,06,242,27,13,31,223,24,27,19,284,28*77 +$GPGSV,3,3,10,11,06,338,,03,14,055,32*71 +$GPRMC,222616.000,A,2734.83488,S,15305.92024,E,24.0,39.3,030308,11.2,W,A*3E +$GPVTG,39.3,T,50.5,M,24.0,N,44.5,K,A*29 +$GPGGA,222617.000,2734.82955,S,15305.92505,E,1,07,1.2,53.2,M,39.2,M,,*73 +$GPGLL,2734.82955,S,15305.92505,E,222617.000,A,A*4E +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222617.000,14.7,13.3,9.2,70.7,8.9,11.8,16.8*5B +$GPGSV,3,1,10,16,48,116,23,25,39,268,30,23,58,174,35,20,71,337,33*7F +$GPGSV,3,2,10,19,02,029,,04,06,242,25,13,31,223,25,27,19,284,26*7A +$GPGSV,3,3,10,11,06,338,,03,14,055,32*71 +$GPRMC,222617.000,A,2734.82955,S,15305.92505,E,24.7,38.8,030308,11.2,W,A*38 +$GPVTG,38.8,T,50.0,M,24.7,N,45.7,K,A*22 +$GPGGA,222618.000,2734.82405,S,15305.92991,E,1,07,1.2,53.5,M,39.2,M,,*72 +$GPGLL,2734.82405,S,15305.92991,E,222618.000,A,A*48 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222618.000,13.7,14.7,7.8,77.2,7.6,13.2,24.3*54 +$GPGSV,3,1,10,16,48,116,27,25,39,268,30,23,58,174,36,20,71,337,32*79 +$GPGSV,3,2,10,19,02,029,,04,06,242,31,13,31,223,25,27,19,283,23*7D +$GPGSV,3,3,10,11,06,338,,03,14,056,32*72 +$GPRMC,222618.000,A,2734.82405,S,15305.92991,E,25.3,38.3,030308,11.2,W,A*30 +$GPVTG,38.3,T,49.5,M,25.3,N,46.8,K,A*2D +$GPGGA,222619.000,2734.81867,S,15305.93485,E,1,07,1.2,53.8,M,39.2,M,,*7C +$GPGLL,2734.81867,S,15305.93485,E,222619.000,A,A*4B +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222619.000,20.5,18.3,9.9,85.5,9.1,16.7,27.9*5A +$GPGSV,3,1,10,16,48,116,27,25,39,268,30,23,58,174,35,20,71,337,33*7B +$GPGSV,3,2,10,19,02,029,,04,06,242,29,13,31,223,23,27,19,283,23*72 +$GPGSV,3,3,10,11,06,338,,03,14,056,32*72 +$GPRMC,222619.000,A,2734.81867,S,15305.93485,E,25.3,39.2,030308,11.2,W,A*33 +$GPVTG,39.2,T,50.4,M,25.3,N,46.8,K,A*24 +$GPGGA,222620.000,2734.81344,S,15305.93979,E,1,05,1.6,53.8,M,39.2,M,,*74 +$GPGLL,2734.81344,S,15305.93979,E,222620.000,A,A*45 +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222620.000,18.2,14.7,21.1,9.8,19.1,13.7,29.8*64 +$GPGSV,3,1,10,16,48,116,26,25,39,268,30,23,58,174,33,20,71,337,34*7B +$GPGSV,3,2,10,19,02,029,,04,06,242,24,13,31,223,25,27,19,283,29*73 +$GPGSV,3,3,10,11,06,338,,03,14,056,33*73 +$GPRMC,222620.000,A,2734.81344,S,15305.93979,E,24.7,39.5,030308,11.2,W,A*3F +$GPVTG,39.5,T,50.7,M,24.7,N,45.8,K,A*26 +$GPGGA,222621.000,2734.80838,S,15305.94469,E,1,06,1.3,53.5,M,39.2,M,,*74 +$GPGLL,2734.80838,S,15305.94469,E,222621.000,A,A*4E +$GPGSA,A,3,16,25,23,20,13,03,,,,,,,2.3,1.3,1.9*3B +$GPGST,222621.000,14.6,11.8,13.4,39.2,11.7,11.4,21.8*5D +$GPGSV,3,1,10,16,48,116,25,25,39,268,31,23,58,174,33,20,71,337,37*7A +$GPGSV,3,2,10,19,03,029,,04,06,242,24,13,31,223,24,27,19,283,36*7D +$GPGSV,3,3,10,11,06,338,,03,14,056,32*72 +$GPRMC,222621.000,A,2734.80838,S,15305.94469,E,24.1,40.1,030308,11.2,W,A*38 +$GPVTG,40.1,T,51.3,M,24.1,N,44.7,K,A*21 +$GPGGA,222622.000,2734.80354,S,15305.94956,E,1,06,1.7,53.3,M,39.2,M,,*75 +$GPGLL,2734.80354,S,15305.94956,E,222622.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.9*3B +$GPGST,222622.000,13.2,10.2,17.1,41.6,12.5,13.2,30.8*59 +$GPGSV,3,1,10,16,48,116,26,25,39,268,31,23,58,174,26,20,71,337,39*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,24,13,31,223,28,27,19,283,36*71 +$GPGSV,3,3,10,11,06,338,,03,14,056,35*75 +$GPRMC,222622.000,A,2734.80354,S,15305.94956,E,23.6,41.3,030308,11.2,W,A*38 +$GPVTG,41.3,T,52.5,M,23.6,N,43.7,K,A*20 +$GPGGA,222623.000,2734.79878,S,15305.95470,E,1,05,1.9,52.8,M,39.2,M,,*78 +$GPGLL,2734.79878,S,15305.95470,E,222623.000,A,A*47 +$GPGSA,A,3,16,25,20,13,27,,,,,,,,3.7,1.9,3.2*3A +$GPGST,222623.000,14.7,24.8,16.6,50.3,19.9,18.6,39.3*5E +$GPGSV,3,1,11,16,48,116,24,25,39,268,32,23,58,174,24,20,71,337,38*70 +$GPGSV,3,2,11,19,03,029,,04,06,242,24,13,31,223,32,27,19,283,34*79 +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,34*7D +$GPRMC,222623.000,A,2734.79878,S,15305.95470,E,24.0,43.4,030308,11.2,W,A*36 +$GPVTG,43.4,T,54.6,M,24.0,N,44.4,K,A*25 +$GPGGA,222624.000,2734.79400,S,15305.96019,E,1,05,1.9,52.3,M,39.2,M,,*7F +$GPGLL,2734.79400,S,15305.96019,E,222624.000,A,A*4B +$GPGSA,A,3,16,25,20,27,03,,,,,,,,2.7,1.9,2.0*39 +$GPGST,222624.000,12.3,24.0,7.9,80.2,8.0,21.7,15.3*5C +$GPGSV,3,1,11,16,48,116,23,25,39,268,32,23,58,174,26,20,71,337,37*7A +$GPGSV,3,2,11,19,03,029,,04,06,242,24,13,31,223,35,27,19,283,25*7E +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,31*78 +$GPRMC,222624.000,A,2734.79400,S,15305.96019,E,24.7,45.3,030308,11.2,W,A*3C +$GPVTG,45.3,T,56.6,M,24.7,N,45.7,K,A*23 +$GPGGA,222625.000,2734.78953,S,15305.96595,E,1,05,1.9,51.8,M,39.2,M,,*7D +$GPGLL,2734.78953,S,15305.96595,E,222625.000,A,A*41 +$GPGSA,A,3,16,25,20,13,27,,,,,,,,3.7,1.9,3.2*3A +$GPGST,222625.000,24.0,12.2,19.9,37.5,14.2,16.0,36.1*57 +$GPGSV,3,1,11,16,48,116,30,25,39,268,32,23,58,174,23,20,71,337,37*7D +$GPGSV,3,2,11,19,03,029,,04,06,242,25,13,31,223,36,27,19,283,25*7C +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,24*7C +$GPRMC,222625.000,A,2734.78953,S,15305.96595,E,24.8,47.9,030308,11.2,W,A*31 +$GPVTG,47.9,T,59.1,M,24.8,N,46.0,K,A*28 +$GPGGA,222626.000,2734.78516,S,15305.97172,E,1,05,2.5,51.1,M,39.2,M,,*79 +$GPGLL,2734.78516,S,15305.97172,E,222626.000,A,A*43 +$GPGSA,A,3,16,25,20,04,13,,,,,,,,4.2,2.5,3.3*37 +$GPGST,222626.000,20.2,12.6,23.1,19.8,13.0,20.2,38.4*5F +$GPGSV,3,1,11,16,48,116,31,25,39,268,32,23,58,174,25,20,71,337,38*75 +$GPGSV,3,2,11,19,03,029,,04,06,242,25,13,31,223,36,27,19,283,23*7A +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,24*7C +$GPRMC,222626.000,A,2734.78516,S,15305.97172,E,24.7,48.3,030308,11.2,W,A*39 +$GPVTG,48.3,T,59.5,M,24.7,N,45.7,K,A*22 +$GPGGA,222627.000,2734.78079,S,15305.97737,E,1,04,2.5,50.5,M,39.2,M,,*77 +$GPGLL,2734.78079,S,15305.97737,E,222627.000,A,A*49 +$GPGSA,A,3,16,23,20,13,,,,,,,,,5.8,2.5,5.2*39 +$GPGST,222627.000,16.3,12.4,42.2,11.3,13.5,37.9,90.0*51 +$GPGSV,3,1,11,16,48,116,28,25,39,268,32,23,58,174,25,20,71,337,37*72 +$GPGSV,3,2,11,19,03,029,,04,06,242,29,13,31,223,37,27,19,283,30*75 +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,24*7C +$GPRMC,222627.000,A,2734.78079,S,15305.97737,E,24.3,48.1,030308,11.2,W,A*35 +$GPVTG,48.1,T,59.3,M,24.3,N,45.1,K,A*24 +$GPGGA,222628.000,2734.77637,S,15305.98293,E,1,07,1.3,50.2,M,39.2,M,,*7E +$GPGLL,2734.77637,S,15305.98293,E,222628.000,A,A*41 +$GPGSA,A,3,16,25,23,04,13,27,03,,,,,,2.2,1.3,1.8*38 +$GPGST,222628.000,13.2,14.5,8.8,76.9,8.4,13.0,22.0*5F +$GPGSV,3,1,11,16,48,116,30,25,39,268,32,23,58,174,27,20,71,337,37*79 +$GPGSV,3,2,11,19,03,029,,04,06,242,32,13,31,223,37,27,19,283,28*76 +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,25*7D +$GPRMC,222628.000,A,2734.77637,S,15305.98293,E,23.9,48.5,030308,11.2,W,A*34 +$GPVTG,48.5,T,59.7,M,23.9,N,44.3,K,A*2A +$GPGGA,222629.000,2734.77226,S,15305.98850,E,1,08,1.1,49.5,M,39.2,M,,*7C +$GPGLL,2734.77226,S,15305.98850,E,222629.000,A,A*41 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222629.000,11.0,9.5,7.3,89.6,6.7,8.6,14.3*5E +$GPGSV,3,1,11,16,48,116,31,25,39,268,32,23,58,174,25,20,71,337,36*7B +$GPGSV,3,2,11,19,03,029,,04,06,242,30,13,31,223,37,27,19,283,28*74 +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,27*7F +$GPRMC,222629.000,A,2734.77226,S,15305.98850,E,23.5,49.4,030308,11.2,W,A*38 +$GPVTG,49.4,T,60.6,M,23.5,N,43.5,K,A*2C +$GPGGA,222630.000,2734.76859,S,15305.99361,E,1,04,3.5,49.4,M,39.2,M,,*74 +$GPGLL,2734.76859,S,15305.99361,E,222630.000,A,A*42 +$GPGSA,A,3,16,25,20,27,,,,,,,,,4.9,3.5,3.4*39 +$GPGST,222630.000,13.4,7.9,50.0,19.9,17.0,43.1,69.5*66 +$GPGSV,3,1,11,16,48,116,31,25,39,268,30,23,58,174,22,20,71,337,36*7E +$GPGSV,3,2,11,19,03,029,,04,06,242,32,13,31,223,35,27,19,283,24*78 +$GPGSV,3,3,11,11,06,338,18,01,,,18,03,14,056,29*78 +$GPRMC,222630.000,A,2734.76859,S,15305.99361,E,21.1,50.3,030308,11.2,W,A*32 +$GPVTG,50.3,T,61.5,M,21.1,N,39.1,K,A*2E +$GPGGA,222631.000,2734.76498,S,15305.99809,E,1,08,1.1,48.2,M,39.2,M,,*7C +$GPGLL,2734.76498,S,15305.99809,E,222631.000,A,A*47 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222631.000,18.4,10.8,5.8,77.6,5.6,9.7,13.2*63 +$GPGSV,3,1,11,16,48,116,32,25,39,268,31,23,58,174,22,20,71,337,35*7F +$GPGSV,3,2,11,19,03,029,,04,06,242,30,13,31,223,36,27,19,283,25*78 +$GPGSV,3,3,11,11,06,338,18,01,,,18,03,14,056,33*73 +$GPRMC,222631.000,A,2734.76498,S,15305.99809,E,19.4,47.4,030308,11.2,W,A*38 +$GPVTG,47.4,T,58.6,M,19.4,N,35.9,K,A*2C +$GPGGA,222632.000,2734.76359,S,15306.00162,E,1,08,1.1,49.6,M,39.2,M,,*77 +$GPGLL,2734.76359,S,15306.00162,E,222632.000,A,A*49 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222632.000,18.1,14.9,6.7,53.4,9.5,11.5,16.1*5A +$GPGSV,3,1,11,16,48,116,30,25,39,268,31,23,58,174,31,20,71,337,31*7B +$GPGSV,3,2,11,19,03,029,,04,06,242,22,13,31,223,37,27,19,283,29*76 +$GPGSV,3,3,11,11,06,338,24,01,,,18,03,14,056,25*7B +$GPRMC,222632.000,A,2734.76359,S,15306.00162,E,12.4,65.5,030308,11.2,W,A*3C +$GPVTG,65.5,T,76.7,M,12.4,N,22.9,K,A*2D +$GPGGA,222633.000,2734.76254,S,15306.00553,E,1,08,1.1,49.0,M,39.2,M,,*7A +$GPGLL,2734.76254,S,15306.00553,E,222633.000,A,A*42 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222633.000,13.9,12.3,5.8,55.3,7.8,9.7,13.7*62 +$GPGSV,3,1,10,16,48,116,35,25,39,268,35,23,58,174,30,20,71,337,35*7E +$GPGSV,3,2,10,19,03,029,,04,06,242,26,13,31,223,39,27,19,283,26*72 +$GPGSV,3,3,10,11,06,338,24,03,14,056,30*76 +$GPRMC,222633.000,A,2734.76254,S,15306.00553,E,12.9,72.5,030308,11.2,W,A*3C +$GPVTG,72.5,T,83.7,M,12.9,N,23.9,K,A*2D +$GPGGA,222634.000,2734.76305,S,15306.00850,E,1,08,1.1,48.4,M,39.2,M,,*73 +$GPGLL,2734.76305,S,15306.00850,E,222634.000,A,A*4E +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222634.000,11.3,10.3,5.3,58.0,6.5,8.4,12.0*62 +$GPGSV,3,1,10,16,48,116,33,25,39,268,38,23,58,174,30,20,71,337,30*70 +$GPGSV,3,2,10,19,03,029,,04,06,242,29,13,31,223,34,27,19,283,30*77 +$GPGSV,3,3,10,11,06,338,23,03,14,056,25*75 +$GPRMC,222634.000,A,2734.76305,S,15306.00850,E,9.4,99.3,030308,11.2,W,A*04 +$GPVTG,99.3,T,110.5,M,9.4,N,17.3,K,A*2D +$GPGGA,222635.000,2734.76418,S,15306.01089,E,1,08,1.1,47.9,M,39.2,M,,*76 +$GPGLL,2734.76418,S,15306.01089,E,222635.000,A,A*49 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222635.000,13.4,9.3,7.7,66.3,7.3,8.3,14.0*50 +$GPGSV,3,1,10,16,48,116,36,25,39,268,31,23,58,174,37,20,71,337,36*7D +$GPGSV,3,2,10,19,03,029,,04,06,242,31,13,31,223,34,27,19,283,31*7F +$GPGSV,3,3,10,11,06,338,23,03,14,056,23*73 +$GPRMC,222635.000,A,2734.76418,S,15306.01089,E,8.3,116.7,030308,11.2,W,A*37 +$GPVTG,116.7,T,127.9,M,8.3,N,15.4,K,A*14 +$GPGGA,222636.000,2734.76577,S,15306.01258,E,1,07,1.7,47.9,M,39.2,M,,*7A +$GPGLL,2734.76577,S,15306.01258,E,222636.000,A,A*4C +$GPGSA,A,3,16,25,23,20,04,13,27,,,,,,2.8,1.7,2.3*3F +$GPGST,222636.000,10.6,11.9,8.1,45.4,9.3,9.3,18.8*65 +$GPGSV,3,1,10,16,48,116,41,25,39,268,35,23,58,174,40,20,71,337,33*7C +$GPGSV,3,2,10,19,03,029,,04,06,242,32,13,31,223,28,27,19,283,34*74 +$GPGSV,3,3,10,11,06,338,25,03,14,056,23*75 +$GPRMC,222636.000,A,2734.76577,S,15306.01258,E,7.6,135.7,030308,11.2,W,A*39 +$GPVTG,135.7,T,146.9,M,7.6,N,14.1,K,A*1C +$GPGGA,222637.000,2734.76759,S,15306.01422,E,1,07,1.7,47.8,M,39.2,M,,*7F +$GPGLL,2734.76759,S,15306.01422,E,222637.000,A,A*48 +$GPGSA,A,3,16,25,23,20,04,13,27,,,,,,2.8,1.7,2.3*3F +$GPGST,222637.000,8.9,7.2,10.9,44.4,8.4,8.5,17.1*59 +$GPGSV,3,1,10,16,48,116,44,25,39,268,36,23,58,174,33,20,71,337,33*7E +$GPGSV,3,2,10,19,03,029,,04,06,242,24,13,31,223,29,27,19,283,36*70 +$GPGSV,3,3,10,11,06,338,25,03,14,056,23*75 +$GPRMC,222637.000,A,2734.76759,S,15306.01422,E,8.0,140.6,030308,11.2,W,A*37 +$GPVTG,140.6,T,151.8,M,8.0,N,14.8,K,A*18 +$GPGGA,222638.000,2734.76957,S,15306.01592,E,1,06,2.0,47.6,M,39.2,M,,*71 +$GPGLL,2734.76957,S,15306.01592,E,222638.000,A,A*4D +$GPGSA,A,3,16,25,23,20,04,13,,,,,,,3.2,2.0,2.6*30 +$GPGST,222638.000,10.4,8.9,16.3,14.1,8.7,14.6,19.9*51 +$GPGSV,3,1,10,16,48,116,38,25,39,268,30,23,58,174,29,20,71,337,29*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,29*7B +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222638.000,A,2734.76957,S,15306.01592,E,8.8,142.8,030308,11.2,W,A*36 +$GPVTG,142.8,T,154.0,M,8.8,N,16.2,K,A*19 +$GPGGA,222639.000,2734.77109,S,15306.01748,E,1,07,1.7,47.8,M,39.2,M,,*7C +$GPGLL,2734.77109,S,15306.01748,E,222639.000,A,A*4B +$GPGSA,A,3,16,25,23,20,04,13,27,,,,,,2.8,1.7,2.3*3F +$GPGST,222639.000,9.5,9.6,14.7,43.8,11.3,11.5,19.8*51 +$GPGSV,3,1,10,16,48,116,37,25,39,268,32,23,58,174,37,20,71,337,29*71 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,27*75 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222639.000,A,2734.77109,S,15306.01748,E,7.1,137.2,030308,11.2,W,A*3E +$GPVTG,137.2,T,148.4,M,7.1,N,13.1,K,A*18 +$GPGGA,222640.000,2734.77216,S,15306.02018,E,1,04,2.6,47.8,M,39.2,M,,*7F +$GPGLL,2734.77216,S,15306.02018,E,222640.000,A,A*49 +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.2,2.6,5.6*32 +$GPGST,222640.000,20.0,11.7,22.3,7.0,10.9,20.3,46.8*65 +$GPGSV,3,1,10,16,48,116,32,25,39,268,29,23,58,174,24,20,71,337,25*70 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,25*77 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222640.000,A,2734.77216,S,15306.02018,E,9.4,114.2,030308,11.2,W,A*36 +$GPVTG,114.2,T,125.4,M,9.4,N,17.4,K,A*18 +$GPGGA,222641.000,2734.77543,S,15306.02149,E,1,04,2.6,47.7,M,39.2,M,,*73 +$GPGLL,2734.77543,S,15306.02149,E,222641.000,A,A*4A +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.2,2.6,5.6*32 +$GPGST,222641.000,18.3,40.3,13.2,79.5,13.7,36.3,59.1*5E +$GPGSV,3,1,10,16,48,116,34,25,39,268,23,23,58,174,26,20,71,337,27*7C +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222641.000,A,2734.77543,S,15306.02149,E,12.5,160.9,030308,11.2,W,A*06 +$GPVTG,160.9,T,172.1,M,12.5,N,23.1,K,A*2E +$GPGGA,222642.000,2734.77709,S,15306.02300,E,1,04,2.6,47.7,M,39.2,M,,*73 +$GPGLL,2734.77709,S,15306.02300,E,222642.000,A,A*4A +$GPGSA,A,3,16,20,04,13,,,,,,,,,4.3,2.6,3.4*35 +$GPGST,222642.000,15.8,14.5,71.8,20.7,26.3,61.6,97.2*58 +$GPGSV,3,1,10,16,48,116,41,25,40,268,23,23,58,174,27,20,71,337,34*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222642.000,A,2734.77709,S,15306.02300,E,7.5,140.7,030308,11.2,W,A*3E +$GPVTG,140.7,T,151.9,M,7.5,N,13.9,K,A*14 +$GPGGA,222643.000,2734.77831,S,15306.02427,E,1,04,2.6,47.5,M,39.2,M,,*76 +$GPGLL,2734.77831,S,15306.02427,E,222643.000,A,A*4D +$GPGSA,A,3,16,20,04,13,,,,,,,,,4.3,2.6,3.4*35 +$GPGST,222643.000,12.9,15.5,112.8,21.4,39.9,96.1,154.3*5C +$GPGSV,3,1,10,16,48,116,41,25,40,268,23,23,58,174,26,20,71,337,35*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222643.000,A,2734.77831,S,15306.02427,E,5.6,136.2,030308,11.2,W,A*3C +$GPVTG,136.2,T,147.4,M,5.6,N,10.4,K,A*15 +$GPGGA,222644.000,2734.77900,S,15306.02522,E,1,04,2.5,47.4,M,39.2,M,,*74 +$GPGLL,2734.77900,S,15306.02522,E,222644.000,A,A*4D +$GPGSA,A,3,16,23,20,13,,,,,,,,,5.8,2.5,5.2*39 +$GPGST,222644.000,11.9,32.3,39.9,23.1,35.5,30.7,165.7*69 +$GPGSV,3,1,10,16,48,116,38,25,40,268,23,23,58,174,25,20,71,337,37*7C +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,26*74 +$GPRMC,222644.000,A,2734.77900,S,15306.02522,E,3.7,127.8,030308,11.2,W,A*31 +$GPVTG,127.8,T,139.0,M,3.7,N,6.9,K,A*2F +$GPGGA,222645.000,2734.77991,S,15306.02594,E,1,04,3.4,47.4,M,39.2,M,,*70 +$GPGLL,2734.77991,S,15306.02594,E,222645.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.4,5.0*30 +$GPGST,222645.000,15.3,40.1,15.0,66.6,34.1,19.2,69.1*50 +$GPGSV,3,1,10,16,48,116,33,25,40,268,23,23,58,174,23,20,71,337,35*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,30*73 +$GPRMC,222645.000,A,2734.77991,S,15306.02594,E,3.9,145.4,030308,11.2,W,A*33 +$GPVTG,145.4,T,156.6,M,3.9,N,7.2,K,A*2C +$GPGGA,222646.000,2734.78074,S,15306.02652,E,1,04,3.4,47.4,M,39.2,M,,*77 +$GPGLL,2734.78074,S,15306.02652,E,222646.000,A,A*4E +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.4,5.0*30 +$GPGST,222646.000,14.8,53.5,15.6,78.9,48.1,16.9,76.9*50 +$GPGSV,3,1,11,16,48,116,32,25,40,268,23,23,58,174,26,20,71,337,32*71 +$GPGSV,3,2,11,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*70 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,34*4D +$GPRMC,222646.000,A,2734.78074,S,15306.02652,E,3.5,149.5,030308,11.2,W,A*35 +$GPVTG,149.5,T,160.7,M,3.5,N,6.6,K,A*2C +$GPGGA,222647.000,2734.78140,S,15306.02704,E,1,04,3.4,47.3,M,39.2,M,,*75 +$GPGLL,2734.78140,S,15306.02704,E,222647.000,A,A*4B +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.4,5.0*30 +$GPGST,222647.000,11.7,42.4,13.1,77.7,38.0,14.3,60.9*53 +$GPGSV,3,1,11,16,48,116,37,25,40,268,23,23,58,174,31,20,71,337,36*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*70 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,34*4D +$GPRMC,222647.000,A,2734.78140,S,15306.02704,E,2.8,145.4,030308,11.2,W,A*31 +$GPVTG,145.4,T,156.6,M,2.8,N,5.1,K,A*2D +$GPGGA,222648.000,2734.78183,S,15306.02753,E,1,04,3.5,47.2,M,39.2,M,,*77 +$GPGLL,2734.78183,S,15306.02753,E,222648.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222648.000,11.3,35.2,16.9,76.3,31.5,16.9,53.8*53 +$GPGSV,3,1,11,16,48,116,35,25,40,267,23,23,58,174,37,20,71,337,35*7E +$GPGSV,3,2,11,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*70 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,35*4C +$GPRMC,222648.000,A,2734.78183,S,15306.02753,E,2.1,135.8,030308,11.2,W,A*31 +$GPVTG,135.8,T,147.1,M,2.1,N,3.9,K,A*26 +$GPGGA,222649.000,2734.78197,S,15306.02773,E,1,04,3.5,46.8,M,39.2,M,,*7A +$GPGLL,2734.78197,S,15306.02773,E,222649.000,A,A*4F +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222649.000,13.9,60.8,14.8,84.0,55.3,14.7,79.7*52 +$GPGSV,3,1,11,16,48,116,31,25,40,267,23,23,58,174,36,20,71,337,31*7F +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,19,283,23*78 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,29*41 +$GPRMC,222649.000,A,2734.78197,S,15306.02773,E,0.6,148.6,030308,11.2,W,A*36 +$GPVTG,148.6,T,159.8,M,0.6,N,1.2,K,A*28 +$GPGGA,222650.000,2734.78195,S,15306.02785,E,1,04,3.5,46.4,M,39.2,M,,*75 +$GPGLL,2734.78195,S,15306.02785,E,222650.000,A,A*4C +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222650.000,11.4,48.0,12.9,83.3,43.6,12.8,63.8*5B +$GPGSV,3,1,11,16,48,116,30,25,40,267,23,23,58,174,33,20,71,337,30*7A +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,19,283,23*78 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,26*4E +$GPRMC,222650.000,A,2734.78195,S,15306.02785,E,0.2,6.4,030308,11.2,W,A*38 +$GPVTG,6.4,T,17.6,M,0.2,N,0.3,K,A*10 +$GPGGA,222651.000,2734.78191,S,15306.02798,E,1,04,3.5,45.9,M,39.2,M,,*72 +$GPGLL,2734.78191,S,15306.02798,E,222651.000,A,A*45 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222651.000,9.8,40.0,12.0,82.4,36.3,11.9,53.8*6E +$GPGSV,3,1,11,16,48,116,28,25,40,267,,23,58,174,35,20,71,337,26*73 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,19,283,*79 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,28*40 +$GPRMC,222651.000,A,2734.78191,S,15306.02798,E,0.1,352.6,030308,11.2,W,A*32 +$GPVTG,352.6,T,3.8,M,0.1,N,0.3,K,A*28 +$GPGGA,222652.000,2734.78198,S,15306.02797,E,1,04,3.5,45.9,M,39.2,M,,*77 +$GPGLL,2734.78198,S,15306.02797,E,222652.000,A,A*40 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222652.000,21.7,41.2,15.0,83.8,37.5,14.2,91.6*58 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,23,20,71,337,26*78 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,19,283,*79 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,24*4C +$GPRMC,222652.000,A,2734.78198,S,15306.02797,E,0.2,263.5,030308,11.2,W,A*34 +$GPVTG,263.5,T,274.7,M,0.2,N,0.3,K,A*26 +$GPGGA,222653.000,2734.78226,S,15306.02793,E,1,04,3.5,45.9,M,39.2,M,,*74 +$GPGLL,2734.78226,S,15306.02793,E,222653.000,A,A*43 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222653.000,18.8,36.4,20.7,81.4,33.0,19.3,78.6*5F +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,25,20,71,337,25*7D +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,24*4C +$GPRMC,222653.000,A,2734.78226,S,15306.02793,E,0.8,188.1,030308,11.2,W,A*3F +$GPVTG,188.1,T,199.3,M,0.8,N,1.5,K,A*2D +$GPGGA,222654.000,2734.78231,S,15306.02789,E,1,04,3.5,45.9,M,39.2,M,,*7E +$GPGLL,2734.78231,S,15306.02789,E,222654.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222654.000,14.4,23.3,16.5,69.8,20.7,16.0,57.9*5D +$GPGSV,3,1,11,16,48,116,34,25,40,267,,23,58,174,34,20,71,337,31*79 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,31*48 +$GPRMC,222654.000,A,2734.78231,S,15306.02789,E,0.1,145.6,030308,11.2,W,A*3A +$GPVTG,145.6,T,156.8,M,0.1,N,0.2,K,A*2C +$GPGGA,222655.000,2734.78251,S,15306.02806,E,1,04,3.5,45.8,M,39.2,M,,*70 +$GPGLL,2734.78251,S,15306.02806,E,222655.000,A,A*46 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222655.000,12.0,28.1,14.0,78.7,25.3,13.6,52.5*54 +$GPGSV,3,1,11,16,48,116,40,25,40,267,,23,58,174,38,20,71,337,35*72 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,36*4F +$GPRMC,222655.000,A,2734.78251,S,15306.02806,E,0.7,135.5,030308,11.2,W,A*37 +$GPVTG,135.5,T,146.8,M,0.7,N,1.2,K,A*2E +$GPGGA,222656.000,2734.78273,S,15306.02823,E,1,04,3.5,45.7,M,39.2,M,,*7B +$GPGLL,2734.78273,S,15306.02823,E,222656.000,A,A*42 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222656.000,9.9,24.8,12.2,76.6,22.2,12.0,44.0*69 +$GPGSV,3,1,11,16,48,116,38,25,40,267,,23,58,174,36,20,71,337,30*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,35*4C +$GPRMC,222656.000,A,2734.78273,S,15306.02823,E,0.5,135.5,030308,11.2,W,A*31 +$GPVTG,135.5,T,146.7,M,0.5,N,1.0,K,A*21 +$GPGGA,222657.000,2734.78312,S,15306.02858,E,1,04,3.5,45.5,M,39.2,M,,*72 +$GPGLL,2734.78312,S,15306.02858,E,222657.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222657.000,8.4,22.4,10.9,74.9,19.9,11.0,38.1*60 +$GPGSV,3,1,11,16,48,116,37,25,40,267,,23,58,174,36,20,71,337,30*79 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,34*4D +$GPRMC,222657.000,A,2734.78312,S,15306.02858,E,1.3,137.6,030308,11.2,W,A*3C +$GPVTG,137.6,T,148.8,M,1.3,N,2.4,K,A*21 +$GPGGA,222658.000,2734.78370,S,15306.02910,E,1,04,3.5,45.4,M,39.2,M,,*75 +$GPGLL,2734.78370,S,15306.02910,E,222658.000,A,A*4F +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222658.000,11.5,25.4,19.7,45.8,20.9,20.7,46.1*53 +$GPGSV,3,1,11,16,48,116,34,25,40,267,18,23,58,174,36,20,71,337,32*71 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,32*48 +$GPRMC,222658.000,A,2734.78370,S,15306.02910,E,2.7,141.8,030308,11.2,W,A*32 +$GPVTG,141.8,T,153.0,M,2.7,N,5.0,K,A*28 +$GPGGA,222659.000,2734.78463,S,15306.02956,E,1,04,3.5,45.4,M,39.2,M,,*73 +$GPGLL,2734.78463,S,15306.02956,E,222659.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222659.000,10.9,34.8,17.8,79.2,31.4,17.1,52.2*5E +$GPGSV,3,1,11,16,48,116,32,25,40,267,18,23,58,174,37,20,71,337,32*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,26*4D +$GPRMC,222659.000,A,2734.78463,S,15306.02956,E,3.6,157.2,030308,11.2,W,A*39 +$GPVTG,157.2,T,168.4,M,3.6,N,6.7,K,A*2D +$GPGGA,222700.000,2734.78553,S,15306.02974,E,1,04,3.5,45.3,M,39.2,M,,*7B +$GPGLL,2734.78553,S,15306.02974,E,222700.000,A,A*46 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222700.000,13.4,30.5,15.4,80.9,27.6,14.6,58.2*5C +$GPGSV,3,1,11,16,48,116,38,25,40,267,18,23,58,174,42,20,71,337,34*78 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,30*4A +$GPRMC,222700.000,A,2734.78553,S,15306.02974,E,3.1,171.1,030308,11.2,W,A*36 +$GPVTG,171.1,T,182.3,M,3.1,N,5.7,K,A*2D +$GPGGA,222701.000,2734.78678,S,15306.02887,E,1,05,1.6,45.4,M,39.2,M,,*7A +$GPGLL,2734.78678,S,15306.02887,E,222701.000,A,A*40 +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222701.000,18.6,22.3,33.4,25.2,29.0,22.6,46.2*53 +$GPGSV,3,1,11,16,48,116,30,25,40,267,18,23,58,174,33,20,71,337,27*74 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,20,27,20,283,*71 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,27*4C +$GPRMC,222701.000,A,2734.78678,S,15306.02887,E,5.1,212.6,030308,11.2,W,A*37 +$GPVTG,212.6,T,223.8,M,5.1,N,9.5,K,A*27 +$GPGGA,222702.000,2734.78726,S,15306.02769,E,1,04,3.5,45.3,M,39.2,M,,*7B +$GPGLL,2734.78726,S,15306.02769,E,222702.000,A,A*46 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222702.000,14.7,49.5,20.8,84.3,45.1,19.5,72.8*5F +$GPGSV,3,1,11,16,48,116,36,25,40,267,18,23,58,174,40,20,71,337,31*71 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,20,27,20,283,*71 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,28*43 +$GPRMC,222702.000,A,2734.78726,S,15306.02769,E,4.2,246.4,030308,11.2,W,A*30 +$GPVTG,246.4,T,257.6,M,4.2,N,7.7,K,A*27 +$GPGGA,222703.000,2734.78745,S,15306.02617,E,1,05,1.6,45.3,M,39.2,M,,*77 +$GPGLL,2734.78745,S,15306.02617,E,222703.000,A,A*4A +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222703.000,12.3,16.0,23.0,21.5,20.3,15.6,33.1*53 +$GPGSV,3,1,11,16,48,116,31,25,40,267,18,23,58,174,29,20,70,337,23*7B +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,27*4C +$GPRMC,222703.000,A,2734.78745,S,15306.02617,E,4.9,265.5,030308,11.2,W,A*37 +$GPVTG,265.5,T,276.7,M,4.9,N,9.1,K,A*26 +$GPGGA,222704.000,2734.78730,S,15306.02555,E,1,04,3.5,45.3,M,39.2,M,,*77 +$GPGLL,2734.78730,S,15306.02555,E,222704.000,A,A*4A +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.1*30 +$GPGST,222704.000,9.5,34.0,22.1,80.5,30.8,20.6,55.7*69 +$GPGSV,3,1,11,16,48,116,31,25,40,267,18,23,58,174,29,20,70,337,23*7B +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,31*4B +$GPRMC,222704.000,A,2734.78730,S,15306.02555,E,2.1,286.5,030308,11.2,W,A*34 +$GPVTG,286.5,T,297.7,M,2.1,N,3.9,K,A*28 +$GPGGA,222705.000,2734.78698,S,15306.02452,E,1,04,3.5,45.3,M,39.2,M,,*73 +$GPGLL,2734.78698,S,15306.02452,E,222705.000,A,A*4E +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.1*30 +$GPGST,222705.000,93.8,65.1,31.9,84.0,59.3,29.7,94.1*5F +$GPGSV,3,1,11,16,48,116,29,25,40,267,18,23,58,174,29,20,70,337,23*72 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,30*4A +$GPRMC,222705.000,A,2734.78698,S,15306.02452,E,3.6,290.3,030308,11.2,W,A*37 +$GPVTG,290.3,T,301.5,M,3.6,N,6.8,K,A*27 +$GPGGA,222706.000,2734.78686,S,15306.02339,E,1,04,3.5,45.3,M,39.2,M,,*75 +$GPGLL,2734.78686,S,15306.02339,E,222706.000,A,A*48 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.1*30 +$GPGST,222706.000,114.3,62.0,48.3,70.3,55.4,45.7,116.3*5B +$GPGSV,3,1,11,16,48,116,24,25,40,267,18,23,58,174,29,20,70,337,23*7F +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222706.000,A,2734.78686,S,15306.02339,E,3.4,277.7,030308,11.2,W,A*3E +$GPVTG,277.7,T,288.9,M,3.4,N,6.3,K,A*2F +$GPGGA,222707.000,2734.78679,S,15306.02251,E,1,04,3.5,45.3,M,39.2,M,,*7B +$GPGLL,2734.78679,S,15306.02251,E,222707.000,A,A*46 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.1*30 +$GPGST,222707.000,128.0,90.0,67.0,53.0,75.4,69.6,158.6*55 +$GPGSV,3,1,11,16,48,116,24,25,40,267,18,23,58,174,29,20,70,337,23*7F +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222707.000,A,2734.78679,S,15306.02251,E,,,030308,,,A*79 +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222708.000,2734.78673,S,15306.02181,E,1,05,1.6,45.3,M,39.2,M,,*70 +$GPGLL,2734.78673,S,15306.02181,E,222708.000,A,A*4D +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222708.000,66.8,93.0,70.5,62.6,69.3,81.1,141.7*6F +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,29,20,70,337,23*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222708.000,A,2734.78673,S,15306.02181,E,,,030308,,,A*72 +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222709.000,2734.78668,S,15306.02124,E,1,05,1.6,45.3,M,39.2,M,,*74 +$GPGLL,2734.78668,S,15306.02124,E,222709.000,A,A*49 +$GPGSA,A,2,16,23,20,13,03,,,,,,,,1.8,1.6,0.9*31 +$GPGST,222709.000,89.5,61.2,117.7,37.9,91.7,79.5,4.3*54 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,29,20,70,337,23*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222709.000,A,2734.78668,S,15306.02124,E,,,030308,,,A*76 +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222710.000,2734.78664,S,15306.02080,E,1,05,1.6,45.3,M,39.2,M,,*7F +$GPGLL,2734.78664,S,15306.02080,E,222710.000,A,A*42 +$GPGSA,A,2,16,23,20,13,03,,,,,,,,1.8,1.6,0.9*31 +$GPGST,222710.000,117.0,82.3,157.6,39.0,121.7,107.9,3.9*62 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,29,20,70,337,23*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222710.000,A,2734.78664,S,15306.02080,E,,,030308,,,A*7D +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222711.000,2734.78660,S,15306.02044,E,1,05,1.6,45.3,M,39.2,M,,*72 +$GPGLL,2734.78660,S,15306.02044,E,222711.000,A,A*4F +$GPGSA,A,2,16,23,20,13,03,,,,,,,,1.8,1.6,0.9*31 +$GPGST,222711.000,128.0,107.6,205.2,40.2,156.7,142.6,3.5*58 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,29,20,70,337,23*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222711.000,A,2734.78660,S,15306.02044,E,,,030308,,,A*70 +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222712.000,2734.78658,S,15306.02015,E,1,05,1.6,45.3,M,39.2,M,,*7E +$GPGLL,2734.78658,S,15306.02015,E,222712.000,A,A*43 +$GPGSA,A,2,16,23,20,13,03,,,,,,,,1.8,1.6,0.9*31 +$GPGST,222712.000,128.0,137.2,261.1,41.4,197.4,183.9,3.2*51 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,173,29,20,70,337,23*71 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222712.000,A,2734.78658,S,15306.02015,E,,,030308,,,A*7C \ No newline at end of file diff --git a/examples/positioning/geoflickr/geoflickr.pro b/examples/positioning/geoflickr/geoflickr.pro new file mode 100644 index 0000000..4bbb795 --- /dev/null +++ b/examples/positioning/geoflickr/geoflickr.pro @@ -0,0 +1,15 @@ +TEMPLATE = app +TARGET = geoflickr + +QT += qml quick network positioning +SOURCES += qmllocationflickr.cpp + +RESOURCES += \ + flickr.qrc + +OTHER_FILES += flickr.qml \ + flickrcommon/* \ + flickrmobile/* + +target.path = $$[QT_INSTALL_EXAMPLES]/positioning/geoflickr +INSTALLS += target diff --git a/examples/positioning/geoflickr/geoflickr.qmlproject b/examples/positioning/geoflickr/geoflickr.qmlproject new file mode 100644 index 0000000..d4909f8 --- /dev/null +++ b/examples/positioning/geoflickr/geoflickr.qmlproject @@ -0,0 +1,16 @@ +import QmlProject 1.0 + +Project { + /* Include .qml, .js, and image files from current directory and subdirectories */ + QmlFiles { + directory: "." + } + JavaScriptFiles { + directory: "." + } + ImageFiles { + directory: "." + } + /* List of plugin directories passed to QML runtime */ + // importPaths: [ " ../exampleplugin " ] +} diff --git a/examples/positioning/geoflickr/qmllocationflickr.cpp b/examples/positioning/geoflickr/qmllocationflickr.cpp new file mode 100644 index 0000000..2ad9ce6 --- /dev/null +++ b/examples/positioning/geoflickr/qmllocationflickr.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QGuiApplication application(argc, argv); + const QString mainQmlApp = QStringLiteral("qrc:///flickr.qml"); + QQuickView view; + view.setSource(QUrl(mainQmlApp)); + view.setResizeMode(QQuickView::SizeRootObjectToView); + // Qt.quit() called in embedded .qml by default only emits + // quit() signal, so do this (optionally use Qt.exit()). + QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit())); + view.setGeometry(QRect(100, 100, 360, 640)); + view.show(); + return application.exec(); +} diff --git a/examples/positioning/logfilepositionsource/clientapplication.cpp b/examples/positioning/logfilepositionsource/clientapplication.cpp new file mode 100644 index 0000000..a37ee00 --- /dev/null +++ b/examples/positioning/logfilepositionsource/clientapplication.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include + +#include "logfilepositionsource.h" +#include "clientapplication.h" + +ClientApplication::ClientApplication(QWidget *parent) + : QMainWindow(parent) +{ + textEdit = new QTextEdit; + setCentralWidget(textEdit); + + LogFilePositionSource *source = new LogFilePositionSource(this); + connect(source, SIGNAL(positionUpdated(QGeoPositionInfo)), + this, SLOT(positionUpdated(QGeoPositionInfo))); + + source->startUpdates(); +} + +void ClientApplication::positionUpdated(const QGeoPositionInfo &info) +{ + textEdit->append(QString("Position updated: Date/time = %1, Coordinate = %2").arg(info.timestamp().toString()).arg(info.coordinate().toString())); +} diff --git a/examples/positioning/logfilepositionsource/clientapplication.h b/examples/positioning/logfilepositionsource/clientapplication.h new file mode 100644 index 0000000..0e67c53 --- /dev/null +++ b/examples/positioning/logfilepositionsource/clientapplication.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef CLIENTAPPLICATION_H +#define CLIENTAPPLICATION_H + +#include + +QT_BEGIN_NAMESPACE +class QGeoPositionInfo; +class QTextEdit; +QT_END_NAMESPACE + +class ClientApplication : public QMainWindow +{ + Q_OBJECT +public: + ClientApplication(QWidget *parent = 0); + +private slots: + void positionUpdated(const QGeoPositionInfo &info); + +private: + QTextEdit *textEdit; +}; + + +#endif diff --git a/examples/positioning/logfilepositionsource/doc/src/logfilepositionsource.qdoc b/examples/positioning/logfilepositionsource/doc/src/logfilepositionsource.qdoc new file mode 100644 index 0000000..6b008af --- /dev/null +++ b/examples/positioning/logfilepositionsource/doc/src/logfilepositionsource.qdoc @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\example logfilepositionsource +\title Log File Position Source (C++) +\ingroup qtpositioning-examples + +\brief The Logfile Position Source shows how to create and work with a custom NMEA position source, + for platforms without GPS. + +The data is read from a file which has positional data in NMEA format. The resulting time and +position information is then displayed to the screen as simple text in date/time and +latitude/longitude format. + +This example class reads position data from a text file, \e log.txt. The file specifies position +data using a simple text format: it contains one position update per line, where each line contains +a date/time, a latitude and a longitude, separated by spaces. The date/time is in ISO 8601 format +and the latitude and longitude are in degrees decimal format. Here is an excerpt from \e log.txt: + +\code +2009-08-24T22:25:01 -27.576082 153.092415 +2009-08-24T22:25:02 -27.576223 153.092530 +2009-08-24T22:25:03 -27.576364 153.092648 +\endcode + +The class reads this data and distributes it via the +\l{QGeoPositionInfoSource::positionUpdated()}{positionUpdated()} signal. + +Here is the definition of the \c LogFilePositionSource class: + +\quotefromfile logfilepositionsource/logfilepositionsource.h +\skipto class LogFilePositionSource +\printuntil }; + +The main methods overrided by the subclass are: + +\list + \li \l{QGeoPositionInfoSource::startUpdates()}{startUpdates()}: called by client applications + to start regular position updates. + \li \l{QGeoPositionInfoSource::stopUpdates()}{stopUpdates()}: called by client applications to + stop regular position updates. + \li \l{QGeoPositionInfoSource::requestUpdate()}{requestUpdate()}: called by client applications + to request a single update, with a specified timeout. +\endlist + +When a position update is available, the subclass emits the +\l{QGeoPositionInfoSource::positionUpdated()}{positionUpdated()} signal. + +Here are the key methods in the class implementation: + +\quotefromfile logfilepositionsource/logfilepositionsource.cpp +\skipto LogFilePositionSource::LogFilePositionSource +\printuntil /^\}/ +\skipto LogFilePositionSource::startUpdates +\printuntil /^\}/ +\skipto LogFilePositionSource::stopUpdates +\printuntil /^\}/ +\skipto LogFilePositionSource::requestUpdate +\printuntil /^\}/ +\printuntil LogFilePositionSource::readNextPosition +\printuntil /^\}/ +*/ diff --git a/examples/positioning/logfilepositionsource/logfile.qrc b/examples/positioning/logfilepositionsource/logfile.qrc new file mode 100644 index 0000000..6121394 --- /dev/null +++ b/examples/positioning/logfilepositionsource/logfile.qrc @@ -0,0 +1,5 @@ + + + simplelog.txt + + diff --git a/examples/positioning/logfilepositionsource/logfilepositionsource.cpp b/examples/positioning/logfilepositionsource/logfilepositionsource.cpp new file mode 100644 index 0000000..d299a66 --- /dev/null +++ b/examples/positioning/logfilepositionsource/logfilepositionsource.cpp @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include + +#include "logfilepositionsource.h" + +LogFilePositionSource::LogFilePositionSource(QObject *parent) + : QGeoPositionInfoSource(parent), + logFile(new QFile(this)), + timer(new QTimer(this)) +{ + connect(timer, SIGNAL(timeout()), this, SLOT(readNextPosition())); + + logFile->setFileName(":/simplelog.txt"); + if (!logFile->open(QIODevice::ReadOnly)) + qWarning() << "Error: cannot open source file" << logFile->fileName(); +} + +QGeoPositionInfo LogFilePositionSource::lastKnownPosition(bool /*fromSatellitePositioningMethodsOnly*/) const +{ + return lastPosition; +} + +LogFilePositionSource::PositioningMethods LogFilePositionSource::supportedPositioningMethods() const +{ + return AllPositioningMethods; +} + +int LogFilePositionSource::minimumUpdateInterval() const +{ + return 500; +} + +void LogFilePositionSource::startUpdates() +{ + int interval = updateInterval(); + if (interval < minimumUpdateInterval()) + interval = minimumUpdateInterval(); + + timer->start(interval); +} + +void LogFilePositionSource::stopUpdates() +{ + timer->stop(); +} + +void LogFilePositionSource::requestUpdate(int /*timeout*/) +{ + // For simplicity, ignore timeout - assume that if data is not available + // now, no data will be added to the file later + if (logFile->canReadLine()) + readNextPosition(); + else + emit updateTimeout(); +} + +void LogFilePositionSource::readNextPosition() +{ + QByteArray line = logFile->readLine().trimmed(); + if (!line.isEmpty()) { + QList data = line.split(' '); + double latitude; + double longitude; + bool hasLatitude = false; + bool hasLongitude = false; + QDateTime timestamp = QDateTime::fromString(QString(data.value(0)), Qt::ISODate); + latitude = data.value(1).toDouble(&hasLatitude); + longitude = data.value(2).toDouble(&hasLongitude); + + if (hasLatitude && hasLongitude && timestamp.isValid()) { + QGeoCoordinate coordinate(latitude, longitude); + QGeoPositionInfo info(coordinate, timestamp); + if (info.isValid()) { + lastPosition = info; + emit positionUpdated(info); + } + } + } +} + +QGeoPositionInfoSource::Error LogFilePositionSource::error() const +{ + return QGeoPositionInfoSource::NoError; +} diff --git a/examples/positioning/logfilepositionsource/logfilepositionsource.h b/examples/positioning/logfilepositionsource/logfilepositionsource.h new file mode 100644 index 0000000..099531f --- /dev/null +++ b/examples/positioning/logfilepositionsource/logfilepositionsource.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef LOGFILEPOSITIONSOURCE_H +#define LOGFILEPOSITIONSOURCE_H + +#include + +QT_BEGIN_NAMESPACE +class QFile; +class QTimer; +QT_END_NAMESPACE + +class LogFilePositionSource : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + LogFilePositionSource(QObject *parent = 0); + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + + PositioningMethods supportedPositioningMethods() const; + int minimumUpdateInterval() const; + Error error() const; + +public slots: + virtual void startUpdates(); + virtual void stopUpdates(); + + virtual void requestUpdate(int timeout = 5000); + +private slots: + void readNextPosition(); + +private: + QFile *logFile; + QTimer *timer; + QGeoPositionInfo lastPosition; +}; + +#endif diff --git a/examples/positioning/logfilepositionsource/logfilepositionsource.pro b/examples/positioning/logfilepositionsource/logfilepositionsource.pro new file mode 100644 index 0000000..cb9e30a --- /dev/null +++ b/examples/positioning/logfilepositionsource/logfilepositionsource.pro @@ -0,0 +1,16 @@ +TEMPLATE = app +TARGET = logfilepositionsource +QT = positioning core widgets + + +HEADERS = logfilepositionsource.h \ + clientapplication.h +SOURCES = logfilepositionsource.cpp \ + clientapplication.cpp \ + main.cpp + +RESOURCES += \ + logfile.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/positioning/logfilepositionsource +INSTALLS += target diff --git a/examples/positioning/logfilepositionsource/main.cpp b/examples/positioning/logfilepositionsource/main.cpp new file mode 100644 index 0000000..03338cf --- /dev/null +++ b/examples/positioning/logfilepositionsource/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include + +#include "clientapplication.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + ClientApplication client; + client.show(); + + return app.exec(); +} diff --git a/examples/positioning/logfilepositionsource/simplelog.txt b/examples/positioning/logfilepositionsource/simplelog.txt new file mode 100644 index 0000000..d016b2a --- /dev/null +++ b/examples/positioning/logfilepositionsource/simplelog.txt @@ -0,0 +1,156 @@ +2009-08-24T22:24:37 -27.572321 153.090718 +2009-08-24T22:24:38 -27.572470 153.090783 +2009-08-24T22:24:39 -27.572616 153.090845 +2009-08-24T22:24:40 -27.572763 153.090908 +2009-08-24T22:24:41 -27.572914 153.090971 +2009-08-24T22:24:42 -27.573068 153.091036 +2009-08-24T22:24:43 -27.573224 153.091102 +2009-08-24T22:24:44 -27.573383 153.091167 +2009-08-24T22:24:45 -27.573541 153.091232 +2009-08-24T22:24:46 -27.573700 153.091298 +2009-08-24T22:24:47 -27.573860 153.091366 +2009-08-24T22:24:48 -27.574019 153.091435 +2009-08-24T22:24:49 -27.574178 153.091507 +2009-08-24T22:24:50 -27.574340 153.091581 +2009-08-24T22:24:51 -27.574506 153.091654 +2009-08-24T22:24:52 -27.574670 153.091729 +2009-08-24T22:24:53 -27.574836 153.091800 +2009-08-24T22:24:54 -27.575001 153.091870 +2009-08-24T22:24:55 -27.575165 153.091940 +2009-08-24T22:24:56 -27.575327 153.092010 +2009-08-24T22:24:57 -27.575485 153.092078 +2009-08-24T22:24:58 -27.575641 153.092144 +2009-08-24T22:24:59 -27.575795 153.092218 +2009-08-24T22:25:00 -27.575942 153.092308 +2009-08-24T22:25:01 -27.576082 153.092415 +2009-08-24T22:25:02 -27.576223 153.092530 +2009-08-24T22:25:03 -27.576364 153.092648 +2009-08-24T22:25:04 -27.576505 153.092763 +2009-08-24T22:25:05 -27.576646 153.092879 +2009-08-24T22:25:06 -27.576784 153.092990 +2009-08-24T22:25:07 -27.576918 153.093099 +2009-08-24T22:25:08 -27.577046 153.093204 +2009-08-24T22:25:09 -27.577168 153.093303 +2009-08-24T22:25:10 -27.577284 153.093396 +2009-08-24T22:25:11 -27.577396 153.093484 +2009-08-24T22:25:12 -27.577499 153.093568 +2009-08-24T22:25:13 -27.577595 153.093647 +2009-08-24T22:25:14 -27.577692 153.093727 +2009-08-24T22:25:15 -27.577793 153.093810 +2009-08-24T22:25:16 -27.577897 153.093896 +2009-08-24T22:25:17 -27.578006 153.093984 +2009-08-24T22:25:18 -27.578120 153.094074 +2009-08-24T22:25:19 -27.578237 153.094168 +2009-08-24T22:25:20 -27.578360 153.094267 +2009-08-24T22:25:21 -27.578487 153.094370 +2009-08-24T22:25:22 -27.578617 153.094474 +2009-08-24T22:25:23 -27.578748 153.094581 +2009-08-24T22:25:24 -27.578880 153.094688 +2009-08-24T22:25:25 -27.579014 153.094796 +2009-08-24T22:25:26 -27.579149 153.094905 +2009-08-24T22:25:27 -27.579285 153.095012 +2009-08-24T22:25:28 -27.579420 153.095121 +2009-08-24T22:25:29 -27.579552 153.095231 +2009-08-24T22:25:30 -27.579684 153.095340 +2009-08-24T22:25:31 -27.579820 153.095449 +2009-08-24T22:25:32 -27.579956 153.095558 +2009-08-24T22:25:33 -27.580095 153.095667 +2009-08-24T22:25:34 -27.580240 153.095776 +2009-08-24T22:25:35 -27.580392 153.095885 +2009-08-24T22:25:36 -27.580536 153.095995 +2009-08-24T22:25:37 -27.580679 153.096109 +2009-08-24T22:25:38 -27.580824 153.096226 +2009-08-24T22:25:39 -27.580965 153.096337 +2009-08-24T22:25:40 -27.581101 153.096441 +2009-08-24T22:25:41 -27.581237 153.096537 +2009-08-24T22:25:42 -27.581356 153.096628 +2009-08-24T22:25:43 -27.581466 153.096714 +2009-08-24T22:25:44 -27.581555 153.096795 +2009-08-24T22:25:45 -27.581606 153.096847 +2009-08-24T22:25:46 -27.581539 153.096855 +2009-08-24T22:25:47 -27.581572 153.096873 +2009-08-24T22:25:48 -27.581579 153.096875 +2009-08-24T22:25:49 -27.581582 153.096878 +2009-08-24T22:25:50 -27.581588 153.096880 +2009-08-24T22:25:51 -27.581588 153.096880 +2009-08-24T22:25:52 -27.581592 153.096881 +2009-08-24T22:25:53 -27.581596 153.096882 +2009-08-24T22:25:54 -27.581599 153.096883 +2009-08-24T22:25:55 -27.581601 153.096883 +2009-08-24T22:25:56 -27.581602 153.096883 +2009-08-24T22:25:57 -27.581606 153.096890 +2009-08-24T22:25:58 -27.581606 153.096919 +2009-08-24T22:25:59 -27.581605 153.096985 +2009-08-24T22:26:00 -27.581573 153.097060 +2009-08-24T22:26:01 -27.581532 153.097142 +2009-08-24T22:26:02 -27.581484 153.097227 +2009-08-24T22:26:03 -27.581426 153.097324 +2009-08-24T22:26:04 -27.581373 153.097424 +2009-08-24T22:26:05 -27.581320 153.097530 +2009-08-24T22:26:06 -27.581265 153.097641 +2009-08-24T22:26:07 -27.581203 153.097757 +2009-08-24T22:26:08 -27.581144 153.097875 +2009-08-24T22:26:09 -27.581093 153.097995 +2009-08-24T22:26:10 -27.581042 153.098116 +2009-08-24T22:26:11 -27.580987 153.098231 +2009-08-24T22:26:12 -27.580919 153.098334 +2009-08-24T22:26:13 -27.580841 153.098428 +2009-08-24T22:26:14 -27.580754 153.098511 +2009-08-24T22:26:15 -27.580667 153.098591 +2009-08-24T22:26:16 -27.580581 153.098671 +2009-08-24T22:26:17 -27.580492 153.098751 +2009-08-24T22:26:18 -27.580401 153.098832 +2009-08-24T22:26:19 -27.580311 153.098914 +2009-08-24T22:26:20 -27.580224 153.098996 +2009-08-24T22:26:21 -27.580140 153.099078 +2009-08-24T22:26:22 -27.580059 153.099159 +2009-08-24T22:26:23 -27.579980 153.099245 +2009-08-24T22:26:24 -27.579900 153.099336 +2009-08-24T22:26:25 -27.579826 153.099433 +2009-08-24T22:26:26 -27.579753 153.099529 +2009-08-24T22:26:27 -27.579680 153.099623 +2009-08-24T22:26:28 -27.579606 153.099716 +2009-08-24T22:26:29 -27.579538 153.099808 +2009-08-24T22:26:30 -27.579477 153.099893 +2009-08-24T22:26:31 -27.579416 153.099968 +2009-08-24T22:26:32 -27.579393 153.100027 +2009-08-24T22:26:33 -27.579376 153.100092 +2009-08-24T22:26:34 -27.579384 153.100142 +2009-08-24T22:26:35 -27.579403 153.100181 +2009-08-24T22:26:36 -27.579429 153.100210 +2009-08-24T22:26:37 -27.579460 153.100237 +2009-08-24T22:26:38 -27.579493 153.100265 +2009-08-24T22:26:39 -27.579518 153.100291 +2009-08-24T22:26:40 -27.579536 153.100336 +2009-08-24T22:26:41 -27.579591 153.100358 +2009-08-24T22:26:42 -27.579618 153.100383 +2009-08-24T22:26:43 -27.579639 153.100404 +2009-08-24T22:26:44 -27.579650 153.100420 +2009-08-24T22:26:45 -27.579665 153.100432 +2009-08-24T22:26:46 -27.579679 153.100442 +2009-08-24T22:26:47 -27.579690 153.100451 +2009-08-24T22:26:48 -27.579697 153.100459 +2009-08-24T22:26:49 -27.579700 153.100462 +2009-08-24T22:26:50 -27.579699 153.100464 +2009-08-24T22:26:51 -27.579699 153.100466 +2009-08-24T22:26:52 -27.579700 153.100466 +2009-08-24T22:26:53 -27.579704 153.100466 +2009-08-24T22:26:54 -27.579705 153.100465 +2009-08-24T22:26:55 -27.579708 153.100468 +2009-08-24T22:26:56 -27.579712 153.100471 +2009-08-24T22:26:57 -27.579719 153.100476 +2009-08-24T22:26:58 -27.579728 153.100485 +2009-08-24T22:26:59 -27.579744 153.100493 +2009-08-24T22:27:00 -27.579759 153.100496 +2009-08-24T22:27:01 -27.579780 153.100481 +2009-08-24T22:27:02 -27.579788 153.100462 +2009-08-24T22:27:03 -27.579791 153.100436 +2009-08-24T22:27:04 -27.579788 153.100426 +2009-08-24T22:27:05 -27.579783 153.100409 +2009-08-24T22:27:06 -27.579781 153.100390 +2009-08-24T22:27:07 -27.579780 153.100375 +2009-08-24T22:27:08 -27.579779 153.100364 +2009-08-24T22:27:09 -27.579778 153.100354 +2009-08-24T22:27:10 -27.579777 153.100347 +2009-08-24T22:27:11 -27.579777 153.100341 +2009-08-24T22:27:12 -27.579776 153.100336 diff --git a/examples/positioning/positioning.pro b/examples/positioning/positioning.pro new file mode 100644 index 0000000..0e436b4 --- /dev/null +++ b/examples/positioning/positioning.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +qtHaveModule(widgets): SUBDIRS += logfilepositionsource +qtHaveModule(quick): SUBDIRS += geoflickr weatherinfo satelliteinfo diff --git a/examples/positioning/satelliteinfo/doc/images/example-satelliteinfo.png b/examples/positioning/satelliteinfo/doc/images/example-satelliteinfo.png new file mode 100644 index 0000000..aa9a217 Binary files /dev/null and b/examples/positioning/satelliteinfo/doc/images/example-satelliteinfo.png differ diff --git a/examples/positioning/satelliteinfo/doc/src/satelliteinfo.qdoc b/examples/positioning/satelliteinfo/doc/src/satelliteinfo.qdoc new file mode 100644 index 0000000..51e4086 --- /dev/null +++ b/examples/positioning/satelliteinfo/doc/src/satelliteinfo.qdoc @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example satelliteinfo + \title SatelliteInfo (C++/QML) + + \brief The SatelliteInfo example shows how the available satellites + at the user's current position and marks the satellites + currently contributing to the GPS fix as pink. + + \ingroup qtpositioning-examples + + Key \l{Qt Positioning} classes used in this example: + + \list + \li \l{QGeoSatelliteInfo} + \li \l{QGeoSatelliteInfoSource} + \endlist + + \image ../images/example-satelliteinfo.png + + The example displays the signal strength of all satellites in view. Any satellite + that is currently used to calculate the GPS fix has been marked pink. The number at + the bottom of each signal bar is the individual satellite identifier. + + The application operates in three different modes: + + \table + \header + \li Application mode + \li Description + \row + \li running + \li The application continuously queries the system for satellite updates. When new data + is available it will be displayed. + \row + \li stopped + \li The application stops updating the satellite information. + \row + \li single + \li The application makes a single update request with a timeout of 10s. The display + remains empty until the request was answered by the system. + \endtable + + If the platform does not provide satellite information the application automatically + switches into a demo mode whereby it continuously switches between predefined + sets of satellite data. + + \include examples-run.qdocinc +*/ diff --git a/examples/positioning/satelliteinfo/main.cpp b/examples/positioning/satelliteinfo/main.cpp new file mode 100644 index 0000000..8d94d01 --- /dev/null +++ b/examples/positioning/satelliteinfo/main.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include "satellitemodel.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + qmlRegisterType("Local", 1, 0, "SatelliteModel"); + + QQuickView view; + view.setSource(QStringLiteral("qrc:///satelliteinfo.qml")); + view.setResizeMode(QQuickView::SizeRootObjectToView); + + QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit())); + view.show(); + + return app.exec(); +} + + diff --git a/examples/positioning/satelliteinfo/satelliteinfo.pro b/examples/positioning/satelliteinfo/satelliteinfo.pro new file mode 100644 index 0000000..4aef9d0 --- /dev/null +++ b/examples/positioning/satelliteinfo/satelliteinfo.pro @@ -0,0 +1,22 @@ +TEMPLATE = app +TARGET = satelliteinfo + +QT += quick positioning + +SOURCES += main.cpp \ + satellitemodel.cpp + +HEADERS += \ + satellitemodel.h + +OTHER_FILES += \ + satelliteinfo.qml + +RESOURCES += \ + satelliteinfo.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/positioning/satelliteinfo +INSTALLS += target + + + diff --git a/examples/positioning/satelliteinfo/satelliteinfo.qml b/examples/positioning/satelliteinfo/satelliteinfo.qml new file mode 100644 index 0000000..185b21f --- /dev/null +++ b/examples/positioning/satelliteinfo/satelliteinfo.qml @@ -0,0 +1,304 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import Local 1.0 + +Rectangle { + id: page + width: 360 + height: 360 + + SatelliteModel { + id: satelliteModel + running: true + onErrorFound: errorLabel.text = qsTr("Last Error: %1", "%1=error number").arg(code) + } + + Item { + id: header + height: column.height + 30 + width: parent.width + state: "running" + + anchors.top: parent.top + + function toggle() + { + switch (header.state) { + case "single": header.state = "running"; break; + default: + case "running": header.state = "stopped"; break; + case "stopped": header.state = "single"; break; + } + } + + function enterSingle() + { + satelliteModel.singleRequestMode = true; + satelliteModel.running = true; + } + + function enterRunning() + { + satelliteModel.running = false; + satelliteModel.singleRequestMode = false; + satelliteModel.running = true; + } + + states: [ + State { + name: "stopped" + PropertyChanges { target: startStop; bText: qsTr("Single") } + PropertyChanges { + target: modeLabel; text: qsTr("Current Mode: stopped") + } + PropertyChanges { target: satelliteModel; running: false; } + }, + State { + name: "single" + PropertyChanges { target: startStop; bText: qsTr("Start") } + PropertyChanges { + target: modeLabel; text: qsTr("Current Mode: single") + } + StateChangeScript { script: header.enterSingle(); } + }, + State { + name: "running" + PropertyChanges { target: startStop; bText: qsTr("Stop") } + PropertyChanges { + target: modeLabel; text: qsTr("Current Mode: running") + } + StateChangeScript { script: header.enterRunning(); } + } + ] + + Column { + id: column + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.margins: 7 + Text { + id: overview + text: satelliteModel.satelliteInfoAvailable + ? qsTr("Known Satellites") + : qsTr("Known Satellites (Demo Mode)") + font.pointSize: 12 + } + + Text { + id: modeLabel + font.pointSize: 12 + } + + Text { + id: errorLabel + text: qsTr("Last Error: None") + font.pointSize: 12 + } + } + Rectangle { + id: startStop + border.color: "black" + border.width: 3 + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.margins: 7 + radius: 10 + height: maxField.height*1.4 + width: maxField.width*1.4 + + property string bText: qsTr("Stop"); + + Text { //need this for sizing + id: maxField + text: qsTr("Single") + font.pointSize: 13 + opacity: 0 + } + + Text { + id: buttonText + anchors.centerIn: parent + text: startStop.bText + font.pointSize: 13 + } + + MouseArea { + anchors.fill: parent + onPressed: { startStop.color = "lightGray" } + onClicked: { header.toggle() } + onReleased: { startStop.color = "white" } + } + } + } + + Rectangle { + anchors.top: header.bottom + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: rect.myMargin + border.width: 3 + radius: 10 + border.color: "black" + + Item { + id: rect + anchors.fill: parent + anchors.margins: myMargin + property int myMargin: 7 + + Row { + id: view + property int rows: repeater.model.entryCount + property int singleWidth: ((rect.width - scale.width)/rows )-rect.myMargin + spacing: rect.myMargin + + Rectangle { + id: scale + width: strengthLabel.width+10 + height: rect.height + color: "#32cd32" + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: lawngreenRect.top + font.pointSize: 11 + text: "50" + } + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + font.pointSize: 11 + text: "100" + } + + Rectangle { + id: redRect + width: parent.width + color: "red" + height: parent.height*10/100 + anchors.bottom: parent.bottom + Text { + id: strengthLabel + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + font.pointSize: 11 + text: "00" + } + } + Rectangle { + id: orangeRect + height: parent.height*10/100 + anchors.bottom: redRect.top + width: parent.width + color: "#ffa500" + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + font.pointSize: 11 + text: "10" + } + } + Rectangle { + id: goldRect + height: parent.height*10/100 + anchors.bottom: orangeRect.top + width: parent.width + color: "#ffd700" + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + font.pointSize: 11 + text: "20" + } + } + Rectangle { + id: yellowRect + height: parent.height*10/100 + anchors.bottom: goldRect.top + width: parent.width + color: "yellow" + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + font.pointSize: 11 + text: "30" + } + } + Rectangle { + id: lawngreenRect + height: parent.height*10/100 + anchors.bottom: yellowRect.top + width: parent.width + color: "#7cFc00" + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + font.pointSize: 11 + text: "40" + } + } + } + + Repeater { + id: repeater + model: satelliteModel + delegate: Rectangle { + height: rect.height + width: view.singleWidth + Rectangle { + anchors.bottom: parent.bottom + width: parent.width + height: parent.height*signalStrength/100 + color: isInUse ? "#7FFF0000" : "#7F0000FF" + } + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + text: satelliteIdentifier + } + } + } + } + } + } +} + diff --git a/examples/positioning/satelliteinfo/satelliteinfo.qrc b/examples/positioning/satelliteinfo/satelliteinfo.qrc new file mode 100644 index 0000000..8745f87 --- /dev/null +++ b/examples/positioning/satelliteinfo/satelliteinfo.qrc @@ -0,0 +1,5 @@ + + + satelliteinfo.qml + + diff --git a/examples/positioning/satelliteinfo/satellitemodel.cpp b/examples/positioning/satelliteinfo/satellitemodel.cpp new file mode 100644 index 0000000..d1ae514 --- /dev/null +++ b/examples/positioning/satelliteinfo/satellitemodel.cpp @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "satellitemodel.h" +#include +#include + +SatelliteModel::SatelliteModel(QObject *parent) : + QAbstractListModel(parent), source(0), m_componentCompleted(false), m_running(false), + m_runningRequested(false), demo(false), isSingle(false), singleRequestServed(false) +{ + source = QGeoSatelliteInfoSource::createDefaultSource(this); + if (!demo && !source) { + qWarning() << "No satellite data source found. Changing to demo mode."; + demo = true; + } + if (!demo) { + source->setUpdateInterval(3000); + connect(source, SIGNAL(satellitesInViewUpdated(QList)), + this, SLOT(satellitesInViewUpdated(QList))); + connect(source, SIGNAL(satellitesInUseUpdated(QList)), + this, SLOT(satellitesInUseUpdated(QList))); + connect(source, SIGNAL(error(QGeoSatelliteInfoSource::Error)), + this, SLOT(error(QGeoSatelliteInfoSource::Error))); + } + + if (demo) { + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(updateDemoData())); + timer->start(3000); + } +} + +int SatelliteModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (!source && !demo) + return 0; + + return knownSatellites.count(); +} + +QVariant SatelliteModel::data(const QModelIndex &index, int role) const +{ + if (!demo && !source) + return QVariant(); + + if (!index.isValid() || index.row() < 0) + return QVariant(); + + if (index.row() >= knownSatellites.count()) { + qWarning() << "SatelliteModel: Index out of bound"; + return QVariant(); + } + + const QGeoSatelliteInfo &info = knownSatellites.at(index.row()); + switch (role) { + case IdentifierRole: + return info.satelliteIdentifier(); + case InUseRole: + return satellitesInUse.contains(info.satelliteIdentifier()); + case SignalStrengthRole: + return info.signalStrength(); + case ElevationRole: + if (!info.hasAttribute(QGeoSatelliteInfo::Elevation)) + return QVariant(); + return info.attribute(QGeoSatelliteInfo::Elevation); + case AzimuthRole: + if (!info.hasAttribute(QGeoSatelliteInfo::Azimuth)) + return QVariant(); + return info.attribute(QGeoSatelliteInfo::Azimuth); + default: + break; + + } + + return QVariant(); +} + +QHash SatelliteModel::roleNames() const +{ + QHash roleNames; + roleNames.insert(IdentifierRole, "satelliteIdentifier"); + roleNames.insert(InUseRole, "isInUse"); + roleNames.insert(SignalStrengthRole, "signalStrength"); + roleNames.insert(ElevationRole, "elevation"); + roleNames.insert(AzimuthRole, "azimuth"); + return roleNames; +} + +void SatelliteModel::componentComplete() +{ + m_componentCompleted = true; + if (m_runningRequested) + setRunning(true); +} + +bool SatelliteModel::running() const +{ + return m_running; +} + +bool SatelliteModel::isSingleRequest() const +{ + return isSingle; +} + +void SatelliteModel::setSingleRequest(bool single) +{ + if (running()) { + qWarning() << "Cannot change single request mode while running"; + return; + } + + if (single != isSingle) { //flag changed + isSingle = single; + emit singleRequestChanged(); + } +} + +void SatelliteModel::setRunning(bool isActive) +{ + if (!source && !demo) + return; + + if (!m_componentCompleted) { + m_runningRequested = isActive; + return; + } + + if (m_running == isActive) + return; + + m_running = isActive; + + if (m_running) { + clearModel(); + if (demo) + timer->start(2000); + else if (isSingleRequest()) + source->requestUpdate(10000); + else + source->startUpdates(); + + if (demo) + singleRequestServed = false; + } else { + if (demo) + timer->stop(); + else if (!isSingleRequest()) + source->stopUpdates(); + } + + + Q_EMIT runningChanged(); +} + +int SatelliteModel::entryCount() const +{ + return knownSatellites.count(); +} + +bool SatelliteModel::canProvideSatelliteInfo() const +{ + return !demo; +} + +void SatelliteModel::clearModel() +{ + beginResetModel(); + knownSatelliteIds.clear(); + knownSatellites.clear(); + satellitesInUse.clear(); + endResetModel(); +} + +void SatelliteModel::updateDemoData() +{ + static bool flag = true; + QList satellites; + if (flag) { + for (int i = 0; i<5; i++) { + QGeoSatelliteInfo info; + info.setSatelliteIdentifier(i); + info.setSignalStrength(20 + 20*i); + satellites.append(info); + } + } else { + for (int i = 0; i<9; i++) { + QGeoSatelliteInfo info; + info.setSatelliteIdentifier(i*2); + info.setSignalStrength(20 + 10*i); + satellites.append(info); + } + } + + + satellitesInViewUpdated(satellites); + flag ? satellitesInUseUpdated(QList() << satellites.at(2)) + : satellitesInUseUpdated(QList() << satellites.at(3)); + flag = !flag; + + emit errorFound(flag); + + if (isSingleRequest() && !singleRequestServed) { + singleRequestServed = true; + setRunning(false); + } +} + +void SatelliteModel::error(QGeoSatelliteInfoSource::Error error) +{ + emit errorFound((int)error); +} + +QT_BEGIN_NAMESPACE +inline bool operator<(const QGeoSatelliteInfo& a, const QGeoSatelliteInfo& b) +{ + return a.satelliteIdentifier() < b.satelliteIdentifier(); +} +QT_END_NAMESPACE + +void SatelliteModel::satellitesInViewUpdated(const QList &infos) +{ + if (!running()) + return; + + int oldEntryCount = knownSatellites.count(); + + + QSet satelliteIdsInUpdate; + foreach (const QGeoSatelliteInfo &info, infos) + satelliteIdsInUpdate.insert(info.satelliteIdentifier()); + + QSet toBeRemoved = knownSatelliteIds - satelliteIdsInUpdate; + + //We reset the model as in reality just about all entry values change + //and there are generally a lot of inserts and removals each time + //Hence we don't bother with complex model update logic beyond resetModel() + beginResetModel(); + + knownSatellites = infos; + + //sort them for presentation purposes + std::sort(knownSatellites.begin(), knownSatellites.end()); + + //remove old "InUse" data + //new satellites are by default not in "InUse" + //existing satellites keep their "inUse" state + satellitesInUse -= toBeRemoved; + + knownSatelliteIds = satelliteIdsInUpdate; + endResetModel(); + + if (oldEntryCount != knownSatellites.count()) + emit entryCountChanged(); +} + +void SatelliteModel::satellitesInUseUpdated(const QList &infos) +{ + if (!running()) + return; + + beginResetModel(); + + satellitesInUse.clear(); + foreach (const QGeoSatelliteInfo &info, infos) + satellitesInUse.insert(info.satelliteIdentifier()); + + endResetModel(); +} + diff --git a/examples/positioning/satelliteinfo/satellitemodel.h b/examples/positioning/satelliteinfo/satellitemodel.h new file mode 100644 index 0000000..5890cb2 --- /dev/null +++ b/examples/positioning/satelliteinfo/satellitemodel.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SATELLITEMODEL_H +#define SATELLITEMODEL_H + +#include +#include +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QTimer) +QT_FORWARD_DECLARE_CLASS(QGeoSatelliteInfoSource) + +class SatelliteModel : public QAbstractListModel, public QQmlParserStatus +{ + Q_OBJECT + Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged) + Q_PROPERTY(bool satelliteInfoAvailable READ canProvideSatelliteInfo NOTIFY canProvideSatelliteInfoChanged) + Q_PROPERTY(int entryCount READ entryCount NOTIFY entryCountChanged) + Q_PROPERTY(bool singleRequestMode READ isSingleRequest WRITE setSingleRequest NOTIFY singleRequestChanged) + Q_INTERFACES(QQmlParserStatus) +public: + explicit SatelliteModel(QObject *parent = 0); + + enum { + IdentifierRole = Qt::UserRole + 1, + InUseRole, + SignalStrengthRole, + ElevationRole, + AzimuthRole + }; + + //From QAbstractListModel + int rowCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + QHash roleNames() const; + + //From QQmlParserStatus + void classBegin() {} + void componentComplete(); + + bool running() const; + void setRunning(bool isActive); + + bool isSingleRequest() const; + void setSingleRequest(bool single); + + int entryCount() const; + + bool canProvideSatelliteInfo() const; + +signals: + void runningChanged(); + void entryCountChanged(); + void errorFound(int code); + void canProvideSatelliteInfoChanged(); + void singleRequestChanged(); + +public slots: + void clearModel(); + void updateDemoData(); + +private slots: + void error(QGeoSatelliteInfoSource::Error); + void satellitesInViewUpdated(const QList &infos); + void satellitesInUseUpdated(const QList &infos); + +private: + QGeoSatelliteInfoSource *source; + bool m_componentCompleted; + bool m_running; + bool m_runningRequested; + QList knownSatellites; + QSet knownSatelliteIds; + QSet satellitesInUse; + bool demo; + QTimer *timer; + bool isSingle; + bool singleRequestServed; + +}; + +QML_DECLARE_TYPE(SatelliteModel) + +#endif // SATELLITEMODEL_H diff --git a/examples/positioning/weatherinfo/appmodel.cpp b/examples/positioning/weatherinfo/appmodel.cpp new file mode 100644 index 0000000..4d8806b --- /dev/null +++ b/examples/positioning/weatherinfo/appmodel.cpp @@ -0,0 +1,580 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "appmodel.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + *This application uses http://openweathermap.org/api + **/ + +#define ZERO_KELVIN 273.15 + +Q_LOGGING_CATEGORY(requestsLog,"wapp.requests") + +WeatherData::WeatherData(QObject *parent) : + QObject(parent) +{ +} + +WeatherData::WeatherData(const WeatherData &other) : + QObject(0), + m_dayOfWeek(other.m_dayOfWeek), + m_weather(other.m_weather), + m_weatherDescription(other.m_weatherDescription), + m_temperature(other.m_temperature) +{ +} + +QString WeatherData::dayOfWeek() const +{ + return m_dayOfWeek; +} + +/*! + * The icon value is based on OpenWeatherMap.org icon set. For details + * see http://bugs.openweathermap.org/projects/api/wiki/Weather_Condition_Codes + * + * e.g. 01d ->sunny day + * + * The icon string will be translated to + * http://openweathermap.org/img/w/01d.png + */ +QString WeatherData::weatherIcon() const +{ + return m_weather; +} + +QString WeatherData::weatherDescription() const +{ + return m_weatherDescription; +} + +QString WeatherData::temperature() const +{ + return m_temperature; +} + +void WeatherData::setDayOfWeek(const QString &value) +{ + m_dayOfWeek = value; + emit dataChanged(); +} + +void WeatherData::setWeatherIcon(const QString &value) +{ + m_weather = value; + emit dataChanged(); +} + +void WeatherData::setWeatherDescription(const QString &value) +{ + m_weatherDescription = value; + emit dataChanged(); +} + +void WeatherData::setTemperature(const QString &value) +{ + m_temperature = value; + emit dataChanged(); +} + +class AppModelPrivate +{ +public: + static const int baseMsBeforeNewRequest = 5 * 1000; // 5 s, increased after each missing answer up to 10x + QGeoPositionInfoSource *src; + QGeoCoordinate coord; + QString longitude, latitude; + QString city; + QNetworkAccessManager *nam; + QNetworkSession *ns; + WeatherData now; + QList forecast; + QQmlListProperty *fcProp; + QSignalMapper *geoReplyMapper; + QSignalMapper *weatherReplyMapper, *forecastReplyMapper; + bool ready; + bool useGps; + QElapsedTimer throttle; + int nErrors; + int minMsBeforeNewRequest; + QTimer delayedCityRequestTimer; + QTimer requestNewWeatherTimer; + QString app_ident; + + AppModelPrivate() : + src(NULL), + nam(NULL), + ns(NULL), + fcProp(NULL), + ready(false), + useGps(true), + nErrors(0), + minMsBeforeNewRequest(baseMsBeforeNewRequest) + { + delayedCityRequestTimer.setSingleShot(true); + delayedCityRequestTimer.setInterval(1000); // 1 s + requestNewWeatherTimer.setSingleShot(false); + requestNewWeatherTimer.setInterval(20*60*1000); // 20 min + throttle.invalidate(); + app_ident = QStringLiteral("36496bad1955bf3365448965a42b9eac"); + } +}; + +static void forecastAppend(QQmlListProperty *prop, WeatherData *val) +{ + Q_UNUSED(val); + Q_UNUSED(prop); +} + +static WeatherData *forecastAt(QQmlListProperty *prop, int index) +{ + AppModelPrivate *d = static_cast(prop->data); + return d->forecast.at(index); +} + +static int forecastCount(QQmlListProperty *prop) +{ + AppModelPrivate *d = static_cast(prop->data); + return d->forecast.size(); +} + +static void forecastClear(QQmlListProperty *prop) +{ + static_cast(prop->data)->forecast.clear(); +} + +//! [0] +AppModel::AppModel(QObject *parent) : + QObject(parent), + d(new AppModelPrivate) +{ +//! [0] + d->fcProp = new QQmlListProperty(this, d, + forecastAppend, + forecastCount, + forecastAt, + forecastClear); + + d->geoReplyMapper = new QSignalMapper(this); + d->weatherReplyMapper = new QSignalMapper(this); + d->forecastReplyMapper = new QSignalMapper(this); + + connect(d->geoReplyMapper, SIGNAL(mapped(QObject*)), + this, SLOT(handleGeoNetworkData(QObject*))); + connect(d->weatherReplyMapper, SIGNAL(mapped(QObject*)), + this, SLOT(handleWeatherNetworkData(QObject*))); + connect(d->forecastReplyMapper, SIGNAL(mapped(QObject*)), + this, SLOT(handleForecastNetworkData(QObject*))); + connect(&d->delayedCityRequestTimer, SIGNAL(timeout()), + this, SLOT(queryCity())); + connect(&d->requestNewWeatherTimer, SIGNAL(timeout()), + this, SLOT(refreshWeather())); + d->requestNewWeatherTimer.start(); + + +//! [1] + // make sure we have an active network session + d->nam = new QNetworkAccessManager(this); + + QNetworkConfigurationManager ncm; + d->ns = new QNetworkSession(ncm.defaultConfiguration(), this); + connect(d->ns, SIGNAL(opened()), this, SLOT(networkSessionOpened())); + // the session may be already open. if it is, run the slot directly + if (d->ns->isOpen()) + this->networkSessionOpened(); + // tell the system we want network + d->ns->open(); +} +//! [1] + +AppModel::~AppModel() +{ + d->ns->close(); + if (d->src) + d->src->stopUpdates(); + delete d; +} + +//! [2] +void AppModel::networkSessionOpened() +{ + d->src = QGeoPositionInfoSource::createDefaultSource(this); + + if (d->src) { + d->useGps = true; + connect(d->src, SIGNAL(positionUpdated(QGeoPositionInfo)), + this, SLOT(positionUpdated(QGeoPositionInfo))); + connect(d->src, SIGNAL(error(QGeoPositionInfoSource::Error)), + this, SLOT(positionError(QGeoPositionInfoSource::Error))); + d->src->startUpdates(); + } else { + d->useGps = false; + d->city = "Brisbane"; + emit cityChanged(); + this->refreshWeather(); + } +} +//! [2] + +//! [3] +void AppModel::positionUpdated(QGeoPositionInfo gpsPos) +{ + d->coord = gpsPos.coordinate(); + + if (!(d->useGps)) + return; + + queryCity(); +} +//! [3] + +void AppModel::queryCity() +{ + //don't update more often then once a minute + //to keep load on server low + if (d->throttle.isValid() && d->throttle.elapsed() < d->minMsBeforeNewRequest ) { + qCDebug(requestsLog) << "delaying query of city"; + if (!d->delayedCityRequestTimer.isActive()) + d->delayedCityRequestTimer.start(); + return; + } + qDebug(requestsLog) << "requested query of city"; + d->throttle.start(); + d->minMsBeforeNewRequest = (d->nErrors + 1) * d->baseMsBeforeNewRequest; + + QString latitude, longitude; + longitude.setNum(d->coord.longitude()); + latitude.setNum(d->coord.latitude()); + + QUrl url("http://api.openweathermap.org/data/2.5/weather"); + QUrlQuery query; + query.addQueryItem("lat", latitude); + query.addQueryItem("lon", longitude); + query.addQueryItem("mode", "json"); + query.addQueryItem("APPID", d->app_ident); + url.setQuery(query); + qCDebug(requestsLog) << "submitting request"; + + QNetworkReply *rep = d->nam->get(QNetworkRequest(url)); + // connect up the signal right away + d->geoReplyMapper->setMapping(rep, rep); + connect(rep, SIGNAL(finished()), + d->geoReplyMapper, SLOT(map())); +} + +void AppModel::positionError(QGeoPositionInfoSource::Error e) +{ + Q_UNUSED(e); + qWarning() << "Position source error. Falling back to simulation mode."; + // cleanup insufficient QGeoPositionInfoSource instance + d->src->stopUpdates(); + d->src->deleteLater(); + d->src = 0; + + // activate simulation mode + d->useGps = false; + d->city = "Brisbane"; + emit cityChanged(); + this->refreshWeather(); +} + +void AppModel::hadError(bool tryAgain) +{ + qCDebug(requestsLog) << "hadError, will " << (tryAgain ? "" : "not ") << "rety"; + d->throttle.start(); + if (d->nErrors < 10) + ++d->nErrors; + d->minMsBeforeNewRequest = (d->nErrors + 1) * d->baseMsBeforeNewRequest; + if (tryAgain) + d->delayedCityRequestTimer.start(); +} + +void AppModel::handleGeoNetworkData(QObject *replyObj) +{ + QNetworkReply *networkReply = qobject_cast(replyObj); + if (!networkReply) { + hadError(false); // should retry? + return; + } + + if (!networkReply->error()) { + d->nErrors = 0; + if (!d->throttle.isValid()) + d->throttle.start(); + d->minMsBeforeNewRequest = d->baseMsBeforeNewRequest; + //convert coordinates to city name + QJsonDocument document = QJsonDocument::fromJson(networkReply->readAll()); + + QJsonObject jo = document.object(); + QJsonValue jv = jo.value(QStringLiteral("name")); + + const QString city = jv.toString(); + qCDebug(requestsLog) << "got city: " << city; + if (city != d->city) { + d->city = city; + emit cityChanged(); + refreshWeather(); + } + } else { + hadError(true); + } + networkReply->deleteLater(); +} + +void AppModel::refreshWeather() +{ + if (d->city.isEmpty()) { + qCDebug(requestsLog) << "refreshing weather skipped (no city)"; + return; + } + qCDebug(requestsLog) << "refreshing weather"; + QUrl url("http://api.openweathermap.org/data/2.5/weather"); + QUrlQuery query; + + query.addQueryItem("q", d->city); + query.addQueryItem("mode", "json"); + query.addQueryItem("APPID", d->app_ident); + url.setQuery(query); + + QNetworkReply *rep = d->nam->get(QNetworkRequest(url)); + // connect up the signal right away + d->weatherReplyMapper->setMapping(rep, rep); + connect(rep, SIGNAL(finished()), + d->weatherReplyMapper, SLOT(map())); +} + +static QString niceTemperatureString(double t) +{ + return QString::number(qRound(t-ZERO_KELVIN)) + QChar(0xB0); +} + +void AppModel::handleWeatherNetworkData(QObject *replyObj) +{ + qCDebug(requestsLog) << "got weather network data"; + QNetworkReply *networkReply = qobject_cast(replyObj); + if (!networkReply) + return; + + if (!networkReply->error()) { + foreach (WeatherData *inf, d->forecast) + delete inf; + d->forecast.clear(); + + QJsonDocument document = QJsonDocument::fromJson(networkReply->readAll()); + + if (document.isObject()) { + QJsonObject obj = document.object(); + QJsonObject tempObject; + QJsonValue val; + + if (obj.contains(QStringLiteral("weather"))) { + val = obj.value(QStringLiteral("weather")); + QJsonArray weatherArray = val.toArray(); + val = weatherArray.at(0); + tempObject = val.toObject(); + d->now.setWeatherDescription(tempObject.value(QStringLiteral("description")).toString()); + d->now.setWeatherIcon(tempObject.value("icon").toString()); + } + if (obj.contains(QStringLiteral("main"))) { + val = obj.value(QStringLiteral("main")); + tempObject = val.toObject(); + val = tempObject.value(QStringLiteral("temp")); + d->now.setTemperature(niceTemperatureString(val.toDouble())); + } + } + } + networkReply->deleteLater(); + + //retrieve the forecast + QUrl url("http://api.openweathermap.org/data/2.5/forecast/daily"); + QUrlQuery query; + + query.addQueryItem("q", d->city); + query.addQueryItem("mode", "json"); + query.addQueryItem("cnt", "5"); + query.addQueryItem("APPID", d->app_ident); + url.setQuery(query); + + QNetworkReply *rep = d->nam->get(QNetworkRequest(url)); + // connect up the signal right away + d->forecastReplyMapper->setMapping(rep, rep); + connect(rep, SIGNAL(finished()), d->forecastReplyMapper, SLOT(map())); +} + +void AppModel::handleForecastNetworkData(QObject *replyObj) +{ + qCDebug(requestsLog) << "got forecast"; + QNetworkReply *networkReply = qobject_cast(replyObj); + if (!networkReply) + return; + + if (!networkReply->error()) { + QJsonDocument document = QJsonDocument::fromJson(networkReply->readAll()); + + QJsonObject jo; + QJsonValue jv; + QJsonObject root = document.object(); + jv = root.value(QStringLiteral("list")); + if (!jv.isArray()) + qWarning() << "Invalid forecast object"; + QJsonArray ja = jv.toArray(); + //we need 4 days of forecast -> first entry is today + if (ja.count() != 5) + qWarning() << "Invalid forecast object"; + + QString data; + for (int i = 1; isetTemperature(data); + + //get date + jv = subtree.value(QStringLiteral("dt")); + QDateTime dt = QDateTime::fromMSecsSinceEpoch((qint64)jv.toDouble()*1000); + forecastEntry->setDayOfWeek(dt.date().toString(QStringLiteral("ddd"))); + + //get icon + QJsonArray weatherArray = subtree.value(QStringLiteral("weather")).toArray(); + jo = weatherArray.at(0).toObject(); + forecastEntry->setWeatherIcon(jo.value(QStringLiteral("icon")).toString()); + + //get description + forecastEntry->setWeatherDescription(jo.value(QStringLiteral("description")).toString()); + + d->forecast.append(forecastEntry); + } + + if (!(d->ready)) { + d->ready = true; + emit readyChanged(); + } + + emit weatherChanged(); + } + networkReply->deleteLater(); +} + +bool AppModel::hasValidCity() const +{ + return (!(d->city.isEmpty()) && d->city.size() > 1 && d->city != ""); +} + +bool AppModel::hasValidWeather() const +{ + return hasValidCity() && (!(d->now.weatherIcon().isEmpty()) && + (d->now.weatherIcon().size() > 1) && + d->now.weatherIcon() != ""); +} + +WeatherData *AppModel::weather() const +{ + return &(d->now); +} + +QQmlListProperty AppModel::forecast() const +{ + return *(d->fcProp); +} + +bool AppModel::ready() const +{ + return d->ready; +} + +bool AppModel::hasSource() const +{ + return (d->src != NULL); +} + +bool AppModel::useGps() const +{ + return d->useGps; +} + +void AppModel::setUseGps(bool value) +{ + d->useGps = value; + if (value) { + d->city = ""; + d->throttle.invalidate(); + emit cityChanged(); + emit weatherChanged(); + } + emit useGpsChanged(); +} + +QString AppModel::city() const +{ + return d->city; +} + +void AppModel::setCity(const QString &value) +{ + d->city = value; + emit cityChanged(); + refreshWeather(); +} diff --git a/examples/positioning/weatherinfo/appmodel.h b/examples/positioning/weatherinfo/appmodel.h new file mode 100644 index 0000000..024f314 --- /dev/null +++ b/examples/positioning/weatherinfo/appmodel.h @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef APPMODEL_H +#define APPMODEL_H + +#include +#include +#include +#include + +#include + +//! [0] +class WeatherData : public QObject { + Q_OBJECT + Q_PROPERTY(QString dayOfWeek + READ dayOfWeek WRITE setDayOfWeek + NOTIFY dataChanged) + Q_PROPERTY(QString weatherIcon + READ weatherIcon WRITE setWeatherIcon + NOTIFY dataChanged) + Q_PROPERTY(QString weatherDescription + READ weatherDescription WRITE setWeatherDescription + NOTIFY dataChanged) + Q_PROPERTY(QString temperature + READ temperature WRITE setTemperature + NOTIFY dataChanged) + +public: + explicit WeatherData(QObject *parent = 0); + WeatherData(const WeatherData &other); + + QString dayOfWeek() const; + QString weatherIcon() const; + QString weatherDescription() const; + QString temperature() const; + + void setDayOfWeek(const QString &value); + void setWeatherIcon(const QString &value); + void setWeatherDescription(const QString &value); + void setTemperature(const QString &value); + +signals: + void dataChanged(); +//! [0] +private: + QString m_dayOfWeek; + QString m_weather; + QString m_weatherDescription; + QString m_temperature; +//! [1] +}; +//! [1] + +Q_DECLARE_METATYPE(WeatherData) + +class AppModelPrivate; +//! [2] +class AppModel : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool ready + READ ready + NOTIFY readyChanged) + Q_PROPERTY(bool hasSource + READ hasSource + NOTIFY readyChanged) + Q_PROPERTY(bool hasValidCity + READ hasValidCity + NOTIFY cityChanged) + Q_PROPERTY(bool hasValidWeather + READ hasValidWeather + NOTIFY weatherChanged) + Q_PROPERTY(bool useGps + READ useGps WRITE setUseGps + NOTIFY useGpsChanged) + Q_PROPERTY(QString city + READ city WRITE setCity + NOTIFY cityChanged) + Q_PROPERTY(WeatherData *weather + READ weather + NOTIFY weatherChanged) + Q_PROPERTY(QQmlListProperty forecast + READ forecast + NOTIFY weatherChanged) + +public: + explicit AppModel(QObject *parent = 0); + ~AppModel(); + + bool ready() const; + bool hasSource() const; + bool useGps() const; + bool hasValidCity() const; + bool hasValidWeather() const; + void setUseGps(bool value); + void hadError(bool tryAgain); + + QString city() const; + void setCity(const QString &value); + + WeatherData *weather() const; + QQmlListProperty forecast() const; + +public slots: + Q_INVOKABLE void refreshWeather(); + +//! [2] +private slots: + void queryCity(); + void networkSessionOpened(); + void positionUpdated(QGeoPositionInfo gpsPos); + void positionError(QGeoPositionInfoSource::Error e); + // these would have QNetworkReply* params but for the signalmapper + void handleGeoNetworkData(QObject *networkReply); + void handleWeatherNetworkData(QObject *networkReply); + void handleForecastNetworkData(QObject *networkReply); + +//! [3] +signals: + void readyChanged(); + void useGpsChanged(); + void cityChanged(); + void weatherChanged(); + +//! [3] + +private: + AppModelPrivate *d; + +//! [4] +}; +//! [4] + +#endif // APPMODEL_H diff --git a/examples/positioning/weatherinfo/components/BigForecastIcon.qml b/examples/positioning/weatherinfo/components/BigForecastIcon.qml new file mode 100644 index 0000000..8630c17 --- /dev/null +++ b/examples/positioning/weatherinfo/components/BigForecastIcon.qml @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: current + + property string topText: "20*" + property string bottomText: "Mostly cloudy" + property string weatherIcon: "01d" + property real smallSide: (current.width < current.height ? current.width : current.height) + + Text { + text: current.topText + font.pointSize: 28 + anchors { + top: current.top + left: current.left + topMargin: 5 + leftMargin: 5 + } + } + + WeatherIcon { + weatherIcon: current.weatherIcon + useServerIcon: false + anchors.centerIn: parent + anchors.verticalCenterOffset: -15 + width: current.smallSide + height: current.smallSide + } + + Text { + text: current.bottomText + font.pointSize: 23 + wrapMode: Text.WordWrap + width: parent.width + horizontalAlignment: Text.AlignRight + anchors { + bottom: current.bottom + right: current.right + rightMargin: 5 + } + } +} diff --git a/examples/positioning/weatherinfo/components/ForecastIcon.qml b/examples/positioning/weatherinfo/components/ForecastIcon.qml new file mode 100644 index 0000000..f0d809c --- /dev/null +++ b/examples/positioning/weatherinfo/components/ForecastIcon.qml @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: top + + property string topText: "Mon" + property string weatherIcon: "01d" + property string bottomText: "22*/23*" + + Text { + id: dayText + horizontalAlignment: Text.AlignHCenter + width: top.width + text: top.topText + + anchors.top: parent.top + anchors.topMargin: top.height / 5 - dayText.paintedHeight + anchors.horizontalCenter: parent.horizontalCenter + } + + WeatherIcon { + id: icon + weatherIcon: top.weatherIcon + + property real side: { + var h = 3 * top.height / 5 + if (top.width < h) + top.width; + else + h; + } + + width: icon.side + height: icon.side + + anchors.centerIn: parent + } + + Text { + id: tempText + horizontalAlignment: Text.AlignHCenter + width: top.width + text: top.bottomText + + anchors.bottom: parent.bottom + anchors.bottomMargin: top.height / 5 - tempText.paintedHeight + anchors.horizontalCenter: parent.horizontalCenter + } +} diff --git a/examples/positioning/weatherinfo/components/WeatherIcon.qml b/examples/positioning/weatherinfo/components/WeatherIcon.qml new file mode 100644 index 0000000..3278cc3 --- /dev/null +++ b/examples/positioning/weatherinfo/components/WeatherIcon.qml @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: container + + property string weatherIcon: "01d" + + //server icons are too small. we keep using the local images + property bool useServerIcon: true + + Image { + id: img + source: { + if (useServerIcon) + "http://openweathermap.org/img/w/" + container.weatherIcon + ".png" + else { + switch (weatherIcon) { + case "01d": + case "01n": + "../icons/weather-sunny.png" + break; + case "02d": + case "02n": + "../icons/weather-sunny-very-few-clouds.png" + break; + case "03d": + case "03n": + "../icons/weather-few-clouds.png" + break; + case "04d": + case "04n": + "../icons/weather-overcast.png" + break; + case "09d": + case "09n": + "../icons/weather-showers.png" + break; + case "10d": + case "10n": + "../icons/weather-showers.png" + break; + case "11d": + case "11n": + "../icons/weather-thundershower.png" + break; + case "13d": + case "13n": + "../icons/weather-snow.png" + break; + case "50d": + case "50n": + "../icons/weather-fog.png" + break; + default: + "../icons/weather-unknown.png" + } + } + } + smooth: true + anchors.fill: parent + } +} diff --git a/examples/positioning/weatherinfo/doc/images/example-weatherinfo.png b/examples/positioning/weatherinfo/doc/images/example-weatherinfo.png new file mode 100644 index 0000000..6557b57 Binary files /dev/null and b/examples/positioning/weatherinfo/doc/images/example-weatherinfo.png differ diff --git a/examples/positioning/weatherinfo/doc/src/weatherinfo.qdoc b/examples/positioning/weatherinfo/doc/src/weatherinfo.qdoc new file mode 100644 index 0000000..3db6fcb --- /dev/null +++ b/examples/positioning/weatherinfo/doc/src/weatherinfo.qdoc @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example weatherinfo + \title Weather Info (C++/QML) + + \brief The Weather Info example shows how to use the user's current position + to retrieve local content from a web service in a C++ plugin for QML. + + \ingroup qtpositioning-examples + + Key \l{Qt Positioning} classes used in this example: + + \list + \li \l{QGeoPositionInfo} + \li \l{QGeoPositionInfoSource} + \endlist + + \image ../images/example-weatherinfo.png + + \include examples-run.qdocinc + + The example uses weather data provided by \l http://www.openweathermap.org. + + The key part of this example is the application's data model, contained + in the WeatherData and AppModel classes. WeatherData represents the weather + information taken from the HTTP service. It is a simple data class, but we + give it Q_PROPERTies to expose it nicely to QML, later. + + \snippet weatherinfo/appmodel.h 0 + \snippet weatherinfo/appmodel.h 1 + + AppModel models the state of the entire application. At startup, the + application first begins by waiting for network connectivity. We do + this using the QNetworkConfigurationManager and QNetworkSession family + of C++ APIs. + + \snippet weatherinfo/appmodel.cpp 0 + \snippet weatherinfo/appmodel.cpp 1 + + Once the network session is open, we proceed to get the platform's + default position source using QGeoPositionInfo::createDefaultSource() + + \snippet weatherinfo/appmodel.cpp 2 + + If no default source is available, we take a static position and fetch + weather for that. If, however, we do have a position source, we connect + its positionUpdated() signal to a slot on the AppModel and call + startUpdates(), which begins regular updates of device position. + + When a position update is received, we use the longitude and latitude + of the returned coordinate to retrieve the current "city" name for use + in the weather lookup. + + \snippet weatherinfo/appmodel.cpp 3 + + To inform the UI about this process, the cityChanged() signal is emitted + when a new city is used, and the weatherChanged() signal whenever a + weather update occurs. + + \snippet weatherinfo/appmodel.h 2 + \snippet weatherinfo/appmodel.h 3 + \snippet weatherinfo/appmodel.h 4 + + We use a QQmlListProperty for the weather forecast information, + which contains the next 4 days of forecast weather. This makes it + easy to access from QML. + + To expose these to the QML UI layer, we use the qmlRegisterType() + function. We call this once for each type we wish to register, before + loading the actual QML file. + + \snippet weatherinfo/main.cpp 0 + \snippet weatherinfo/main.cpp 1 + + Finally, in the actual QML, we instantiate the AppModel. + + \snippet weatherinfo/weatherinfo.qml 0 + \snippet weatherinfo/weatherinfo.qml 1 + \snippet weatherinfo/weatherinfo.qml 2 + + Once instantiated like this, we can use its properties elsewhere in the + QML document: + + \snippet weatherinfo/weatherinfo.qml 3 + \snippet weatherinfo/weatherinfo.qml 4 + +*/ diff --git a/examples/positioning/weatherinfo/icons/README.txt b/examples/positioning/weatherinfo/icons/README.txt new file mode 100644 index 0000000..d384153 --- /dev/null +++ b/examples/positioning/weatherinfo/icons/README.txt @@ -0,0 +1,5 @@ +The scalable icons are from: + +http://tango.freedesktop.org/Tango_Icon_Library +http://darkobra.deviantart.com/art/Tango-Weather-Icon-Pack-98024429 + diff --git a/examples/positioning/weatherinfo/icons/weather-few-clouds.png b/examples/positioning/weatherinfo/icons/weather-few-clouds.png new file mode 100644 index 0000000..a8000ef Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-few-clouds.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-fog.png b/examples/positioning/weatherinfo/icons/weather-fog.png new file mode 100644 index 0000000..9ffe9c4 Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-fog.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-haze.png b/examples/positioning/weatherinfo/icons/weather-haze.png new file mode 100644 index 0000000..ae6f13e Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-haze.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-icy.png b/examples/positioning/weatherinfo/icons/weather-icy.png new file mode 100644 index 0000000..18d2038 Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-icy.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-overcast.png b/examples/positioning/weatherinfo/icons/weather-overcast.png new file mode 100644 index 0000000..9d50f77 Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-overcast.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-showers.png b/examples/positioning/weatherinfo/icons/weather-showers.png new file mode 100644 index 0000000..07489aa Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-showers.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-sleet.png b/examples/positioning/weatherinfo/icons/weather-sleet.png new file mode 100644 index 0000000..3d22589 Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-sleet.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-snow.png b/examples/positioning/weatherinfo/icons/weather-snow.png new file mode 100644 index 0000000..e7426e3 Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-snow.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-storm.png b/examples/positioning/weatherinfo/icons/weather-storm.png new file mode 100644 index 0000000..6b6b366 Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-storm.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-sunny-very-few-clouds.png b/examples/positioning/weatherinfo/icons/weather-sunny-very-few-clouds.png new file mode 100644 index 0000000..133bcb2 Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-sunny-very-few-clouds.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-sunny.png b/examples/positioning/weatherinfo/icons/weather-sunny.png new file mode 100644 index 0000000..0fac921 Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-sunny.png differ diff --git a/examples/positioning/weatherinfo/icons/weather-thundershower.png b/examples/positioning/weatherinfo/icons/weather-thundershower.png new file mode 100644 index 0000000..1aff163 Binary files /dev/null and b/examples/positioning/weatherinfo/icons/weather-thundershower.png differ diff --git a/examples/positioning/weatherinfo/main.cpp b/examples/positioning/weatherinfo/main.cpp new file mode 100644 index 0000000..e9d6d11 --- /dev/null +++ b/examples/positioning/weatherinfo/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +//! [0] +#include "appmodel.h" + +int main(int argc, char *argv[]) +{ + QLoggingCategory::setFilterRules("wapp.*.debug=false"); + QGuiApplication application(argc, argv); + + qmlRegisterType("WeatherInfo", 1, 0, "WeatherData"); + qmlRegisterType("WeatherInfo", 1, 0, "AppModel"); + +//! [0] + qRegisterMetaType(); +//! [1] + const QString mainQmlApp = QStringLiteral("qrc:///weatherinfo.qml"); + QQuickView view; + view.setSource(QUrl(mainQmlApp)); + view.setResizeMode(QQuickView::SizeRootObjectToView); + + QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit())); + view.setGeometry(QRect(100, 100, 360, 640)); + view.show(); + return application.exec(); +} +//! [1] diff --git a/examples/positioning/weatherinfo/weatherinfo.pro b/examples/positioning/weatherinfo/weatherinfo.pro new file mode 100644 index 0000000..e2b2102 --- /dev/null +++ b/examples/positioning/weatherinfo/weatherinfo.pro @@ -0,0 +1,21 @@ +TEMPLATE = app +TARGET = weatherinfo + +QT += core network positioning qml quick + +SOURCES += main.cpp \ + appmodel.cpp + +OTHER_FILES += weatherinfo.qml \ + components/WeatherIcon.qml \ + components/ForecastIcon.qml \ + components/BigForecastIcon.qml \ + icons/* + + +RESOURCES += weatherinfo.qrc + +HEADERS += appmodel.h + +target.path = $$[QT_INSTALL_EXAMPLES]/positioning/weatherinfo +INSTALLS += target diff --git a/examples/positioning/weatherinfo/weatherinfo.qml b/examples/positioning/weatherinfo/weatherinfo.qml new file mode 100644 index 0000000..b0b2a8e --- /dev/null +++ b/examples/positioning/weatherinfo/weatherinfo.qml @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import "components" +//! [0] +import WeatherInfo 1.0 + +Item { + id: window +//! [0] + width: 360 + height: 640 + + state: "loading" + + states: [ + State { + name: "loading" + PropertyChanges { target: main; opacity: 0 } + PropertyChanges { target: wait; opacity: 1 } + }, + State { + name: "ready" + PropertyChanges { target: main; opacity: 1 } + PropertyChanges { target: wait; opacity: 0 } + } + ] +//! [1] + AppModel { + id: model + onReadyChanged: { + if (model.ready) + window.state = "ready" + else + window.state = "loading" + } + } +//! [1] + Item { + id: wait + anchors.fill: parent + + Text { + text: "Loading weather data..." + anchors.centerIn: parent + font.pointSize: 18 + } + } + + Item { + id: main + anchors.fill: parent + + Column { + spacing: 6 + + anchors { + fill: parent + topMargin: 6; bottomMargin: 6; leftMargin: 6; rightMargin: 6 + } + + Rectangle { + width: parent.width + height: 25 + color: "lightgrey" + + Text { + text: (model.hasValidCity ? model.city : "Unknown location") + (model.useGps ? " (GPS)" : "") + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + MouseArea { + anchors.fill: parent + onClicked: { + if (model.useGps) { + model.useGps = false + model.city = "Brisbane" + } else { + switch (model.city) { + case "Brisbane": + model.city = "Oslo" + break + case "Oslo": + model.city = "Helsinki" + break + case "Helsinki": + model.city = "New York" + break + case "New York": + model.useGps = true + break + } + } + } + } + } + +//! [3] + BigForecastIcon { + id: current + + width: main.width -12 + height: 2 * (main.height - 25 - 12) / 3 + + weatherIcon: (model.hasValidWeather + ? model.weather.weatherIcon + : "01d") +//! [3] + topText: (model.hasValidWeather + ? model.weather.temperature + : "??") + bottomText: (model.hasValidWeather + ? model.weather.weatherDescription + : "No weather data") + + MouseArea { + anchors.fill: parent + onClicked: { + model.refreshWeather() + } + } +//! [4] + } +//! [4] + + Row { + id: iconRow + spacing: 6 + + width: main.width - 12 + height: (main.height - 25 - 24) / 3 + + property real iconWidth: iconRow.width / 4 - 10 + property real iconHeight: iconRow.height + + ForecastIcon { + id: forecast1 + width: iconRow.iconWidth + height: iconRow.iconHeight + + topText: (model.hasValidWeather ? + model.forecast[0].dayOfWeek : "??") + bottomText: (model.hasValidWeather ? + model.forecast[0].temperature : "??/??") + weatherIcon: (model.hasValidWeather ? + model.forecast[0].weatherIcon : "01d") + } + ForecastIcon { + id: forecast2 + width: iconRow.iconWidth + height: iconRow.iconHeight + + topText: (model.hasValidWeather ? + model.forecast[1].dayOfWeek : "??") + bottomText: (model.hasValidWeather ? + model.forecast[1].temperature : "??/??") + weatherIcon: (model.hasValidWeather ? + model.forecast[1].weatherIcon : "01d") + } + ForecastIcon { + id: forecast3 + width: iconRow.iconWidth + height: iconRow.iconHeight + + topText: (model.hasValidWeather ? + model.forecast[2].dayOfWeek : "??") + bottomText: (model.hasValidWeather ? + model.forecast[2].temperature : "??/??") + weatherIcon: (model.hasValidWeather ? + model.forecast[2].weatherIcon : "01d") + } + ForecastIcon { + id: forecast4 + width: iconRow.iconWidth + height: iconRow.iconHeight + + topText: (model.hasValidWeather ? + model.forecast[3].dayOfWeek : "??") + bottomText: (model.hasValidWeather ? + model.forecast[3].temperature : "??/??") + weatherIcon: (model.hasValidWeather ? + model.forecast[3].weatherIcon : "01d") + } + + } + } + } +//! [2] +} +//! [2] diff --git a/examples/positioning/weatherinfo/weatherinfo.qrc b/examples/positioning/weatherinfo/weatherinfo.qrc new file mode 100644 index 0000000..7b79dbe --- /dev/null +++ b/examples/positioning/weatherinfo/weatherinfo.qrc @@ -0,0 +1,20 @@ + + + weatherinfo.qml + components/BigForecastIcon.qml + components/ForecastIcon.qml + components/WeatherIcon.qml + icons/weather-few-clouds.png + icons/weather-fog.png + icons/weather-haze.png + icons/weather-icy.png + icons/weather-overcast.png + icons/weather-showers.png + icons/weather-sleet.png + icons/weather-snow.png + icons/weather-storm.png + icons/weather-sunny-very-few-clouds.png + icons/weather-sunny.png + icons/weather-thundershower.png + + diff --git a/include/QtLocation/5.7.1/QtLocation/private/qabstractgeotilecache_p.h b/include/QtLocation/5.7.1/QtLocation/private/qabstractgeotilecache_p.h new file mode 100644 index 0000000..c483a2f --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qabstractgeotilecache_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qabstractgeotilecache_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qcache3q_p.h b/include/QtLocation/5.7.1/QtLocation/private/qcache3q_p.h new file mode 100644 index 0000000..2f3ebc0 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qcache3q_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qcache3q_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeocameracapabilities_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeocameracapabilities_p.h new file mode 100644 index 0000000..c237979 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeocameracapabilities_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeocameracapabilities_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeocameradata_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeocameradata_p.h new file mode 100644 index 0000000..0639753 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeocameradata_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeocameradata_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeocameratiles_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeocameratiles_p.h new file mode 100644 index 0000000..80f6aaf --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeocameratiles_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeocameratiles_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeocodereply_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeocodereply_p.h new file mode 100644 index 0000000..2524050 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeocodereply_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeocodereply_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeocodingmanager_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeocodingmanager_p.h new file mode 100644 index 0000000..043ed36 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeocodingmanager_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeocodingmanager_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeocodingmanagerengine_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeocodingmanagerengine_p.h new file mode 100644 index 0000000..5ce24ee --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeocodingmanagerengine_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeocodingmanagerengine_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeofiletilecache_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeofiletilecache_p.h new file mode 100644 index 0000000..9fbe35a --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeofiletilecache_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeofiletilecache_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeomaneuver_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeomaneuver_p.h new file mode 100644 index 0000000..cd5008e --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeomaneuver_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeomaneuver_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeomap_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeomap_p.h new file mode 100644 index 0000000..b7327e4 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeomap_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeomap_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeomap_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeomap_p_p.h new file mode 100644 index 0000000..3407c69 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeomap_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeomap_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanager_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanager_p.h new file mode 100644 index 0000000..9b03ed7 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanager_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeomappingmanager_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanager_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanager_p_p.h new file mode 100644 index 0000000..a9d965a --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanager_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeomappingmanager_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanagerengine_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanagerengine_p.h new file mode 100644 index 0000000..a1dd77b --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanagerengine_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeomappingmanagerengine_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanagerengine_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanagerengine_p_p.h new file mode 100644 index 0000000..7d99d28 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeomappingmanagerengine_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeomappingmanagerengine_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeomaptype_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeomaptype_p.h new file mode 100644 index 0000000..d6f8348 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeomaptype_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeomaptype_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeomaptype_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeomaptype_p_p.h new file mode 100644 index 0000000..93fb3ba --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeomaptype_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeomaptype_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeoroute_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeoroute_p.h new file mode 100644 index 0000000..aed5df1 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeoroute_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeoroute_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparser_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparser_p.h new file mode 100644 index 0000000..75a676d --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparser_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeorouteparser_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparser_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparser_p_p.h new file mode 100644 index 0000000..a40608f --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparser_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeorouteparser_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparserosrmv4_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparserosrmv4_p.h new file mode 100644 index 0000000..0882302 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparserosrmv4_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeorouteparserosrmv4_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparserosrmv5_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparserosrmv5_p.h new file mode 100644 index 0000000..d16d23f --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeorouteparserosrmv5_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeorouteparserosrmv5_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeoroutereply_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeoroutereply_p.h new file mode 100644 index 0000000..73e5640 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeoroutereply_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeoroutereply_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeorouterequest_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeorouterequest_p.h new file mode 100644 index 0000000..00f7941 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeorouterequest_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeorouterequest_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeoroutesegment_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeoroutesegment_p.h new file mode 100644 index 0000000..77cc84a --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeoroutesegment_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeoroutesegment_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeoroutingmanager_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeoroutingmanager_p.h new file mode 100644 index 0000000..1824922 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeoroutingmanager_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeoroutingmanager_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeoroutingmanagerengine_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeoroutingmanagerengine_p.h new file mode 100644 index 0000000..6f11de9 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeoroutingmanagerengine_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeoroutingmanagerengine_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeoserviceprovider_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeoserviceprovider_p.h new file mode 100644 index 0000000..88f9999 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeoserviceprovider_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeoserviceprovider_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmap_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmap_p.h new file mode 100644 index 0000000..718b0a3 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmap_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotiledmap_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmap_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmap_p_p.h new file mode 100644 index 0000000..10bf8bb --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmap_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotiledmap_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmappingmanagerengine_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmappingmanagerengine_p.h new file mode 100644 index 0000000..8cda0fe --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmappingmanagerengine_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotiledmappingmanagerengine_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmappingmanagerengine_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmappingmanagerengine_p_p.h new file mode 100644 index 0000000..1ad7d38 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmappingmanagerengine_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotiledmappingmanagerengine_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmapreply_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmapreply_p.h new file mode 100644 index 0000000..90e0c73 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmapreply_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotiledmapreply_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmapreply_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmapreply_p_p.h new file mode 100644 index 0000000..6563bf2 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmapreply_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotiledmapreply_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmapscene_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmapscene_p.h new file mode 100644 index 0000000..edf39c9 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotiledmapscene_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotiledmapscene_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotilefetcher_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotilefetcher_p.h new file mode 100644 index 0000000..5e921b5 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotilefetcher_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotilefetcher_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotilefetcher_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotilefetcher_p_p.h new file mode 100644 index 0000000..c183b71 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotilefetcher_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotilefetcher_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotilerequestmanager_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotilerequestmanager_p.h new file mode 100644 index 0000000..8872823 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotilerequestmanager_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotilerequestmanager_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotilespec_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotilespec_p.h new file mode 100644 index 0000000..7737cc7 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotilespec_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotilespec_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qgeotilespec_p_p.h b/include/QtLocation/5.7.1/QtLocation/private/qgeotilespec_p_p.h new file mode 100644 index 0000000..8f318b6 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qgeotilespec_p_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/maps/qgeotilespec_p_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplace_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplace_p.h new file mode 100644 index 0000000..1aabde7 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplace_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplace_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplaceattribute_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplaceattribute_p.h new file mode 100644 index 0000000..ce8bd7c --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplaceattribute_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplaceattribute_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplacecategory_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplacecategory_p.h new file mode 100644 index 0000000..ed94a62 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplacecategory_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplacecategory_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplacecontactdetail_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplacecontactdetail_p.h new file mode 100644 index 0000000..c8833e9 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplacecontactdetail_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplacecontactdetail_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplacecontent_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplacecontent_p.h new file mode 100644 index 0000000..4ccd7c8 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplacecontent_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplacecontent_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplacecontentrequest_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplacecontentrequest_p.h new file mode 100644 index 0000000..64ca72d --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplacecontentrequest_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplacecontentrequest_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplaceeditorial_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplaceeditorial_p.h new file mode 100644 index 0000000..c4caf2e --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplaceeditorial_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplaceeditorial_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplaceicon_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplaceicon_p.h new file mode 100644 index 0000000..37a951d --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplaceicon_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplaceicon_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplaceimage_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplaceimage_p.h new file mode 100644 index 0000000..9de1983 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplaceimage_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplaceimage_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplacemanagerengine_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplacemanagerengine_p.h new file mode 100644 index 0000000..2e1be79 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplacemanagerengine_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplacemanagerengine_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplaceproposedsearchresult_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplaceproposedsearchresult_p.h new file mode 100644 index 0000000..b9e81b0 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplaceproposedsearchresult_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplaceproposedsearchresult_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplaceratings_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplaceratings_p.h new file mode 100644 index 0000000..3904253 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplaceratings_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplaceratings_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplacereply_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplacereply_p.h new file mode 100644 index 0000000..fb0e273 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplacereply_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplacereply_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplaceresult_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplaceresult_p.h new file mode 100644 index 0000000..94132fe --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplaceresult_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplaceresult_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplacereview_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplacereview_p.h new file mode 100644 index 0000000..94552a3 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplacereview_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplacereview_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplacesearchresult_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplacesearchresult_p.h new file mode 100644 index 0000000..1b7404e --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplacesearchresult_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplacesearchresult_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplacesupplier_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplacesupplier_p.h new file mode 100644 index 0000000..718cc74 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplacesupplier_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplacesupplier_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/qplaceuser_p.h b/include/QtLocation/5.7.1/QtLocation/private/qplaceuser_p.h new file mode 100644 index 0000000..0dc4089 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/qplaceuser_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/qplaceuser_p.h" diff --git a/include/QtLocation/5.7.1/QtLocation/private/unsupportedreplies_p.h b/include/QtLocation/5.7.1/QtLocation/private/unsupportedreplies_p.h new file mode 100644 index 0000000..396fcf9 --- /dev/null +++ b/include/QtLocation/5.7.1/QtLocation/private/unsupportedreplies_p.h @@ -0,0 +1 @@ +#include "../../../../../src/location/places/unsupportedreplies_p.h" diff --git a/include/QtLocation/QGeoCodeReply b/include/QtLocation/QGeoCodeReply new file mode 100644 index 0000000..14193f8 --- /dev/null +++ b/include/QtLocation/QGeoCodeReply @@ -0,0 +1 @@ +#include "qgeocodereply.h" diff --git a/include/QtLocation/QGeoCodingManager b/include/QtLocation/QGeoCodingManager new file mode 100644 index 0000000..ed7d721 --- /dev/null +++ b/include/QtLocation/QGeoCodingManager @@ -0,0 +1 @@ +#include "qgeocodingmanager.h" diff --git a/include/QtLocation/QGeoCodingManagerEngine b/include/QtLocation/QGeoCodingManagerEngine new file mode 100644 index 0000000..69303d2 --- /dev/null +++ b/include/QtLocation/QGeoCodingManagerEngine @@ -0,0 +1 @@ +#include "qgeocodingmanagerengine.h" diff --git a/include/QtLocation/QGeoManeuver b/include/QtLocation/QGeoManeuver new file mode 100644 index 0000000..a3ff6a5 --- /dev/null +++ b/include/QtLocation/QGeoManeuver @@ -0,0 +1 @@ +#include "qgeomaneuver.h" diff --git a/include/QtLocation/QGeoRoute b/include/QtLocation/QGeoRoute new file mode 100644 index 0000000..fd6690a --- /dev/null +++ b/include/QtLocation/QGeoRoute @@ -0,0 +1 @@ +#include "qgeoroute.h" diff --git a/include/QtLocation/QGeoRouteReply b/include/QtLocation/QGeoRouteReply new file mode 100644 index 0000000..6109d67 --- /dev/null +++ b/include/QtLocation/QGeoRouteReply @@ -0,0 +1 @@ +#include "qgeoroutereply.h" diff --git a/include/QtLocation/QGeoRouteRequest b/include/QtLocation/QGeoRouteRequest new file mode 100644 index 0000000..221969b --- /dev/null +++ b/include/QtLocation/QGeoRouteRequest @@ -0,0 +1 @@ +#include "qgeorouterequest.h" diff --git a/include/QtLocation/QGeoRouteSegment b/include/QtLocation/QGeoRouteSegment new file mode 100644 index 0000000..74590d6 --- /dev/null +++ b/include/QtLocation/QGeoRouteSegment @@ -0,0 +1 @@ +#include "qgeoroutesegment.h" diff --git a/include/QtLocation/QGeoRoutingManager b/include/QtLocation/QGeoRoutingManager new file mode 100644 index 0000000..76e5224 --- /dev/null +++ b/include/QtLocation/QGeoRoutingManager @@ -0,0 +1 @@ +#include "qgeoroutingmanager.h" diff --git a/include/QtLocation/QGeoRoutingManagerEngine b/include/QtLocation/QGeoRoutingManagerEngine new file mode 100644 index 0000000..300a668 --- /dev/null +++ b/include/QtLocation/QGeoRoutingManagerEngine @@ -0,0 +1 @@ +#include "qgeoroutingmanagerengine.h" diff --git a/include/QtLocation/QGeoServiceProvider b/include/QtLocation/QGeoServiceProvider new file mode 100644 index 0000000..d5b38bc --- /dev/null +++ b/include/QtLocation/QGeoServiceProvider @@ -0,0 +1 @@ +#include "qgeoserviceprovider.h" diff --git a/include/QtLocation/QGeoServiceProviderFactory b/include/QtLocation/QGeoServiceProviderFactory new file mode 100644 index 0000000..9bee8fb --- /dev/null +++ b/include/QtLocation/QGeoServiceProviderFactory @@ -0,0 +1 @@ +#include "qgeoserviceproviderfactory.h" diff --git a/include/QtLocation/QLocation b/include/QtLocation/QLocation new file mode 100644 index 0000000..e433f1e --- /dev/null +++ b/include/QtLocation/QLocation @@ -0,0 +1 @@ +#include "qlocation.h" diff --git a/include/QtLocation/QPlace b/include/QtLocation/QPlace new file mode 100644 index 0000000..51b4bac --- /dev/null +++ b/include/QtLocation/QPlace @@ -0,0 +1 @@ +#include "qplace.h" diff --git a/include/QtLocation/QPlaceAttribute b/include/QtLocation/QPlaceAttribute new file mode 100644 index 0000000..05d36df --- /dev/null +++ b/include/QtLocation/QPlaceAttribute @@ -0,0 +1 @@ +#include "qplaceattribute.h" diff --git a/include/QtLocation/QPlaceCategory b/include/QtLocation/QPlaceCategory new file mode 100644 index 0000000..959738a --- /dev/null +++ b/include/QtLocation/QPlaceCategory @@ -0,0 +1 @@ +#include "qplacecategory.h" diff --git a/include/QtLocation/QPlaceContactDetail b/include/QtLocation/QPlaceContactDetail new file mode 100644 index 0000000..4ff2d2d --- /dev/null +++ b/include/QtLocation/QPlaceContactDetail @@ -0,0 +1 @@ +#include "qplacecontactdetail.h" diff --git a/include/QtLocation/QPlaceContent b/include/QtLocation/QPlaceContent new file mode 100644 index 0000000..7ebb145 --- /dev/null +++ b/include/QtLocation/QPlaceContent @@ -0,0 +1 @@ +#include "qplacecontent.h" diff --git a/include/QtLocation/QPlaceContentReply b/include/QtLocation/QPlaceContentReply new file mode 100644 index 0000000..67fc8a8 --- /dev/null +++ b/include/QtLocation/QPlaceContentReply @@ -0,0 +1 @@ +#include "qplacecontentreply.h" diff --git a/include/QtLocation/QPlaceContentRequest b/include/QtLocation/QPlaceContentRequest new file mode 100644 index 0000000..43459f4 --- /dev/null +++ b/include/QtLocation/QPlaceContentRequest @@ -0,0 +1 @@ +#include "qplacecontentrequest.h" diff --git a/include/QtLocation/QPlaceDetailsReply b/include/QtLocation/QPlaceDetailsReply new file mode 100644 index 0000000..1455310 --- /dev/null +++ b/include/QtLocation/QPlaceDetailsReply @@ -0,0 +1 @@ +#include "qplacedetailsreply.h" diff --git a/include/QtLocation/QPlaceEditorial b/include/QtLocation/QPlaceEditorial new file mode 100644 index 0000000..d1a232a --- /dev/null +++ b/include/QtLocation/QPlaceEditorial @@ -0,0 +1 @@ +#include "qplaceeditorial.h" diff --git a/include/QtLocation/QPlaceIcon b/include/QtLocation/QPlaceIcon new file mode 100644 index 0000000..fae7a4e --- /dev/null +++ b/include/QtLocation/QPlaceIcon @@ -0,0 +1 @@ +#include "qplaceicon.h" diff --git a/include/QtLocation/QPlaceIdReply b/include/QtLocation/QPlaceIdReply new file mode 100644 index 0000000..8709b65 --- /dev/null +++ b/include/QtLocation/QPlaceIdReply @@ -0,0 +1 @@ +#include "qplaceidreply.h" diff --git a/include/QtLocation/QPlaceImage b/include/QtLocation/QPlaceImage new file mode 100644 index 0000000..606c306 --- /dev/null +++ b/include/QtLocation/QPlaceImage @@ -0,0 +1 @@ +#include "qplaceimage.h" diff --git a/include/QtLocation/QPlaceManager b/include/QtLocation/QPlaceManager new file mode 100644 index 0000000..7973c48 --- /dev/null +++ b/include/QtLocation/QPlaceManager @@ -0,0 +1 @@ +#include "qplacemanager.h" diff --git a/include/QtLocation/QPlaceManagerEngine b/include/QtLocation/QPlaceManagerEngine new file mode 100644 index 0000000..27f07fc --- /dev/null +++ b/include/QtLocation/QPlaceManagerEngine @@ -0,0 +1 @@ +#include "qplacemanagerengine.h" diff --git a/include/QtLocation/QPlaceMatchReply b/include/QtLocation/QPlaceMatchReply new file mode 100644 index 0000000..37ffdf2 --- /dev/null +++ b/include/QtLocation/QPlaceMatchReply @@ -0,0 +1 @@ +#include "qplacematchreply.h" diff --git a/include/QtLocation/QPlaceMatchRequest b/include/QtLocation/QPlaceMatchRequest new file mode 100644 index 0000000..ceaeb96 --- /dev/null +++ b/include/QtLocation/QPlaceMatchRequest @@ -0,0 +1 @@ +#include "qplacematchrequest.h" diff --git a/include/QtLocation/QPlaceProposedSearchResult b/include/QtLocation/QPlaceProposedSearchResult new file mode 100644 index 0000000..c43f2a6 --- /dev/null +++ b/include/QtLocation/QPlaceProposedSearchResult @@ -0,0 +1 @@ +#include "qplaceproposedsearchresult.h" diff --git a/include/QtLocation/QPlaceRatings b/include/QtLocation/QPlaceRatings new file mode 100644 index 0000000..4b7f63c --- /dev/null +++ b/include/QtLocation/QPlaceRatings @@ -0,0 +1 @@ +#include "qplaceratings.h" diff --git a/include/QtLocation/QPlaceReply b/include/QtLocation/QPlaceReply new file mode 100644 index 0000000..f0654b8 --- /dev/null +++ b/include/QtLocation/QPlaceReply @@ -0,0 +1 @@ +#include "qplacereply.h" diff --git a/include/QtLocation/QPlaceResult b/include/QtLocation/QPlaceResult new file mode 100644 index 0000000..4f5c8db --- /dev/null +++ b/include/QtLocation/QPlaceResult @@ -0,0 +1 @@ +#include "qplaceresult.h" diff --git a/include/QtLocation/QPlaceReview b/include/QtLocation/QPlaceReview new file mode 100644 index 0000000..83cccec --- /dev/null +++ b/include/QtLocation/QPlaceReview @@ -0,0 +1 @@ +#include "qplacereview.h" diff --git a/include/QtLocation/QPlaceSearchReply b/include/QtLocation/QPlaceSearchReply new file mode 100644 index 0000000..395a61a --- /dev/null +++ b/include/QtLocation/QPlaceSearchReply @@ -0,0 +1 @@ +#include "qplacesearchreply.h" diff --git a/include/QtLocation/QPlaceSearchRequest b/include/QtLocation/QPlaceSearchRequest new file mode 100644 index 0000000..b247dab --- /dev/null +++ b/include/QtLocation/QPlaceSearchRequest @@ -0,0 +1 @@ +#include "qplacesearchrequest.h" diff --git a/include/QtLocation/QPlaceSearchResult b/include/QtLocation/QPlaceSearchResult new file mode 100644 index 0000000..2298271 --- /dev/null +++ b/include/QtLocation/QPlaceSearchResult @@ -0,0 +1 @@ +#include "qplacesearchresult.h" diff --git a/include/QtLocation/QPlaceSearchSuggestionReply b/include/QtLocation/QPlaceSearchSuggestionReply new file mode 100644 index 0000000..e7a4f91 --- /dev/null +++ b/include/QtLocation/QPlaceSearchSuggestionReply @@ -0,0 +1 @@ +#include "qplacesearchsuggestionreply.h" diff --git a/include/QtLocation/QPlaceSupplier b/include/QtLocation/QPlaceSupplier new file mode 100644 index 0000000..465b46d --- /dev/null +++ b/include/QtLocation/QPlaceSupplier @@ -0,0 +1 @@ +#include "qplacesupplier.h" diff --git a/include/QtLocation/QPlaceUser b/include/QtLocation/QPlaceUser new file mode 100644 index 0000000..5acba29 --- /dev/null +++ b/include/QtLocation/QPlaceUser @@ -0,0 +1 @@ +#include "qplaceuser.h" diff --git a/include/QtLocation/QtLocation b/include/QtLocation/QtLocation new file mode 100644 index 0000000..897c1aa --- /dev/null +++ b/include/QtLocation/QtLocation @@ -0,0 +1,47 @@ +#ifndef QT_QTLOCATION_MODULE_H +#define QT_QTLOCATION_MODULE_H +#include +#include "qlocation.h" +#include "qlocationglobal.h" +#include "qgeocodereply.h" +#include "qgeocodingmanager.h" +#include "qgeocodingmanagerengine.h" +#include "qgeomaneuver.h" +#include "qgeoroute.h" +#include "qgeoroutereply.h" +#include "qgeorouterequest.h" +#include "qgeoroutesegment.h" +#include "qgeoroutingmanager.h" +#include "qgeoroutingmanagerengine.h" +#include "qgeoserviceprovider.h" +#include "qgeoserviceproviderfactory.h" +#include "placemacro.h" +#include "qplace.h" +#include "qplaceattribute.h" +#include "qplacecategory.h" +#include "qplacecontactdetail.h" +#include "qplacecontent.h" +#include "qplacecontentreply.h" +#include "qplacecontentrequest.h" +#include "qplacedetailsreply.h" +#include "qplaceeditorial.h" +#include "qplaceicon.h" +#include "qplaceidreply.h" +#include "qplaceimage.h" +#include "qplacemanager.h" +#include "qplacemanagerengine.h" +#include "qplacematchreply.h" +#include "qplacematchrequest.h" +#include "qplaceproposedsearchresult.h" +#include "qplaceratings.h" +#include "qplacereply.h" +#include "qplaceresult.h" +#include "qplacereview.h" +#include "qplacesearchreply.h" +#include "qplacesearchrequest.h" +#include "qplacesearchresult.h" +#include "qplacesearchsuggestionreply.h" +#include "qplacesupplier.h" +#include "qplaceuser.h" +#include "qtlocationversion.h" +#endif diff --git a/include/QtLocation/QtLocationVersion b/include/QtLocation/QtLocationVersion new file mode 100644 index 0000000..8da2499 --- /dev/null +++ b/include/QtLocation/QtLocationVersion @@ -0,0 +1 @@ +#include "qtlocationversion.h" diff --git a/include/QtLocation/headers.pri b/include/QtLocation/headers.pri new file mode 100644 index 0000000..6ec9927 --- /dev/null +++ b/include/QtLocation/headers.pri @@ -0,0 +1,6 @@ +SYNCQT.HEADER_FILES = qlocation.h qlocationglobal.h maps/qgeocodereply.h maps/qgeocodingmanager.h maps/qgeocodingmanagerengine.h maps/qgeomaneuver.h maps/qgeoroute.h maps/qgeoroutereply.h maps/qgeorouterequest.h maps/qgeoroutesegment.h maps/qgeoroutingmanager.h maps/qgeoroutingmanagerengine.h maps/qgeoserviceprovider.h maps/qgeoserviceproviderfactory.h places/placemacro.h places/qplace.h places/qplaceattribute.h places/qplacecategory.h places/qplacecontactdetail.h places/qplacecontent.h places/qplacecontentreply.h places/qplacecontentrequest.h places/qplacedetailsreply.h places/qplaceeditorial.h places/qplaceicon.h places/qplaceidreply.h places/qplaceimage.h places/qplacemanager.h places/qplacemanagerengine.h places/qplacematchreply.h places/qplacematchrequest.h places/qplaceproposedsearchresult.h places/qplaceratings.h places/qplacereply.h places/qplaceresult.h places/qplacereview.h places/qplacesearchreply.h places/qplacesearchrequest.h places/qplacesearchresult.h places/qplacesearchsuggestionreply.h places/qplacesupplier.h places/qplaceuser.h ../../include/QtLocation/qtlocationversion.h ../../include/QtLocation/QtLocation +SYNCQT.HEADER_CLASSES = ../../include/QtLocation/QLocation ../../include/QtLocation/QGeoCodeReply ../../include/QtLocation/QGeoCodingManager ../../include/QtLocation/QGeoCodingManagerEngine ../../include/QtLocation/QGeoManeuver ../../include/QtLocation/QGeoRoute ../../include/QtLocation/QGeoRouteReply ../../include/QtLocation/QGeoRouteRequest ../../include/QtLocation/QGeoRouteSegment ../../include/QtLocation/QGeoRoutingManager ../../include/QtLocation/QGeoRoutingManagerEngine ../../include/QtLocation/QGeoServiceProvider ../../include/QtLocation/QGeoServiceProviderFactory ../../include/QtLocation/QPlace ../../include/QtLocation/QPlaceAttribute ../../include/QtLocation/QPlaceCategory ../../include/QtLocation/QPlaceContactDetail ../../include/QtLocation/QPlaceContent ../../include/QtLocation/QPlaceContentReply ../../include/QtLocation/QPlaceContentRequest ../../include/QtLocation/QPlaceDetailsReply ../../include/QtLocation/QPlaceEditorial ../../include/QtLocation/QPlaceIcon ../../include/QtLocation/QPlaceIdReply ../../include/QtLocation/QPlaceImage ../../include/QtLocation/QPlaceManager ../../include/QtLocation/QPlaceManagerEngine ../../include/QtLocation/QPlaceMatchReply ../../include/QtLocation/QPlaceMatchRequest ../../include/QtLocation/QPlaceProposedSearchResult ../../include/QtLocation/QPlaceRatings ../../include/QtLocation/QPlaceReply ../../include/QtLocation/QPlaceResult ../../include/QtLocation/QPlaceReview ../../include/QtLocation/QPlaceSearchReply ../../include/QtLocation/QPlaceSearchRequest ../../include/QtLocation/QPlaceSearchResult ../../include/QtLocation/QPlaceSearchSuggestionReply ../../include/QtLocation/QPlaceSupplier ../../include/QtLocation/QPlaceUser ../../include/QtLocation/QtLocationVersion +SYNCQT.PRIVATE_HEADER_FILES = maps/qabstractgeotilecache_p.h maps/qcache3q_p.h maps/qgeocameracapabilities_p.h maps/qgeocameradata_p.h maps/qgeocameratiles_p.h maps/qgeocodereply_p.h maps/qgeocodingmanager_p.h maps/qgeocodingmanagerengine_p.h maps/qgeofiletilecache_p.h maps/qgeomaneuver_p.h maps/qgeomap_p.h maps/qgeomap_p_p.h maps/qgeomappingmanager_p.h maps/qgeomappingmanager_p_p.h maps/qgeomappingmanagerengine_p.h maps/qgeomappingmanagerengine_p_p.h maps/qgeomaptype_p.h maps/qgeomaptype_p_p.h maps/qgeoroute_p.h maps/qgeorouteparser_p.h maps/qgeorouteparser_p_p.h maps/qgeorouteparserosrmv4_p.h maps/qgeorouteparserosrmv5_p.h maps/qgeoroutereply_p.h maps/qgeorouterequest_p.h maps/qgeoroutesegment_p.h maps/qgeoroutingmanager_p.h maps/qgeoroutingmanagerengine_p.h maps/qgeoserviceprovider_p.h maps/qgeotiledmap_p.h maps/qgeotiledmap_p_p.h maps/qgeotiledmappingmanagerengine_p.h maps/qgeotiledmappingmanagerengine_p_p.h maps/qgeotiledmapreply_p.h maps/qgeotiledmapreply_p_p.h maps/qgeotiledmapscene_p.h maps/qgeotilefetcher_p.h maps/qgeotilefetcher_p_p.h maps/qgeotilerequestmanager_p.h maps/qgeotilespec_p.h maps/qgeotilespec_p_p.h places/qplace_p.h places/qplaceattribute_p.h places/qplacecategory_p.h places/qplacecontactdetail_p.h places/qplacecontent_p.h places/qplacecontentrequest_p.h places/qplaceeditorial_p.h places/qplaceicon_p.h places/qplaceimage_p.h places/qplacemanagerengine_p.h places/qplaceproposedsearchresult_p.h places/qplaceratings_p.h places/qplacereply_p.h places/qplaceresult_p.h places/qplacereview_p.h places/qplacesearchresult_p.h places/qplacesupplier_p.h places/qplaceuser_p.h places/unsupportedreplies_p.h +SYNCQT.QPA_HEADER_FILES = +SYNCQT.CLEAN_HEADER_FILES = qlocation.h qlocationglobal.h maps/qgeocodereply.h maps/qgeocodingmanager.h maps/qgeocodingmanagerengine.h maps/qgeomaneuver.h maps/qgeoroute.h maps/qgeoroutereply.h maps/qgeorouterequest.h maps/qgeoroutesegment.h maps/qgeoroutingmanager.h maps/qgeoroutingmanagerengine.h maps/qgeoserviceprovider.h maps/qgeoserviceproviderfactory.h places/placemacro.h places/qplace.h places/qplaceattribute.h places/qplacecategory.h places/qplacecontactdetail.h places/qplacecontent.h places/qplacecontentreply.h places/qplacecontentrequest.h places/qplacedetailsreply.h places/qplaceeditorial.h places/qplaceicon.h places/qplaceidreply.h places/qplaceimage.h places/qplacemanager.h places/qplacemanagerengine.h places/qplacematchreply.h places/qplacematchrequest.h places/qplaceproposedsearchresult.h places/qplaceratings.h places/qplacereply.h places/qplaceresult.h places/qplacereview.h places/qplacesearchreply.h places/qplacesearchrequest.h places/qplacesearchresult.h places/qplacesearchsuggestionreply.h places/qplacesupplier.h places/qplaceuser.h +SYNCQT.INJECTIONS = diff --git a/include/QtLocation/placemacro.h b/include/QtLocation/placemacro.h new file mode 100644 index 0000000..19404ab --- /dev/null +++ b/include/QtLocation/placemacro.h @@ -0,0 +1 @@ +#include "../../src/location/places/placemacro.h" diff --git a/include/QtLocation/qgeocodereply.h b/include/QtLocation/qgeocodereply.h new file mode 100644 index 0000000..ba6d712 --- /dev/null +++ b/include/QtLocation/qgeocodereply.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeocodereply.h" diff --git a/include/QtLocation/qgeocodingmanager.h b/include/QtLocation/qgeocodingmanager.h new file mode 100644 index 0000000..7ddf50f --- /dev/null +++ b/include/QtLocation/qgeocodingmanager.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeocodingmanager.h" diff --git a/include/QtLocation/qgeocodingmanagerengine.h b/include/QtLocation/qgeocodingmanagerengine.h new file mode 100644 index 0000000..18d06ef --- /dev/null +++ b/include/QtLocation/qgeocodingmanagerengine.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeocodingmanagerengine.h" diff --git a/include/QtLocation/qgeomaneuver.h b/include/QtLocation/qgeomaneuver.h new file mode 100644 index 0000000..72e145b --- /dev/null +++ b/include/QtLocation/qgeomaneuver.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeomaneuver.h" diff --git a/include/QtLocation/qgeoroute.h b/include/QtLocation/qgeoroute.h new file mode 100644 index 0000000..b0bdf34 --- /dev/null +++ b/include/QtLocation/qgeoroute.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeoroute.h" diff --git a/include/QtLocation/qgeoroutereply.h b/include/QtLocation/qgeoroutereply.h new file mode 100644 index 0000000..34d8e88 --- /dev/null +++ b/include/QtLocation/qgeoroutereply.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeoroutereply.h" diff --git a/include/QtLocation/qgeorouterequest.h b/include/QtLocation/qgeorouterequest.h new file mode 100644 index 0000000..33bf11d --- /dev/null +++ b/include/QtLocation/qgeorouterequest.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeorouterequest.h" diff --git a/include/QtLocation/qgeoroutesegment.h b/include/QtLocation/qgeoroutesegment.h new file mode 100644 index 0000000..7205732 --- /dev/null +++ b/include/QtLocation/qgeoroutesegment.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeoroutesegment.h" diff --git a/include/QtLocation/qgeoroutingmanager.h b/include/QtLocation/qgeoroutingmanager.h new file mode 100644 index 0000000..8ae46be --- /dev/null +++ b/include/QtLocation/qgeoroutingmanager.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeoroutingmanager.h" diff --git a/include/QtLocation/qgeoroutingmanagerengine.h b/include/QtLocation/qgeoroutingmanagerengine.h new file mode 100644 index 0000000..4b26f14 --- /dev/null +++ b/include/QtLocation/qgeoroutingmanagerengine.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeoroutingmanagerengine.h" diff --git a/include/QtLocation/qgeoserviceprovider.h b/include/QtLocation/qgeoserviceprovider.h new file mode 100644 index 0000000..4aca205 --- /dev/null +++ b/include/QtLocation/qgeoserviceprovider.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeoserviceprovider.h" diff --git a/include/QtLocation/qgeoserviceproviderfactory.h b/include/QtLocation/qgeoserviceproviderfactory.h new file mode 100644 index 0000000..39a5e4c --- /dev/null +++ b/include/QtLocation/qgeoserviceproviderfactory.h @@ -0,0 +1 @@ +#include "../../src/location/maps/qgeoserviceproviderfactory.h" diff --git a/include/QtLocation/qlocation.h b/include/QtLocation/qlocation.h new file mode 100644 index 0000000..4c266a1 --- /dev/null +++ b/include/QtLocation/qlocation.h @@ -0,0 +1 @@ +#include "../../src/location/qlocation.h" diff --git a/include/QtLocation/qlocationglobal.h b/include/QtLocation/qlocationglobal.h new file mode 100644 index 0000000..9959740 --- /dev/null +++ b/include/QtLocation/qlocationglobal.h @@ -0,0 +1 @@ +#include "../../src/location/qlocationglobal.h" diff --git a/include/QtLocation/qplace.h b/include/QtLocation/qplace.h new file mode 100644 index 0000000..7ce3cf4 --- /dev/null +++ b/include/QtLocation/qplace.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplace.h" diff --git a/include/QtLocation/qplaceattribute.h b/include/QtLocation/qplaceattribute.h new file mode 100644 index 0000000..9ade0c5 --- /dev/null +++ b/include/QtLocation/qplaceattribute.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplaceattribute.h" diff --git a/include/QtLocation/qplacecategory.h b/include/QtLocation/qplacecategory.h new file mode 100644 index 0000000..310d15c --- /dev/null +++ b/include/QtLocation/qplacecategory.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacecategory.h" diff --git a/include/QtLocation/qplacecontactdetail.h b/include/QtLocation/qplacecontactdetail.h new file mode 100644 index 0000000..179040c --- /dev/null +++ b/include/QtLocation/qplacecontactdetail.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacecontactdetail.h" diff --git a/include/QtLocation/qplacecontent.h b/include/QtLocation/qplacecontent.h new file mode 100644 index 0000000..675d5ee --- /dev/null +++ b/include/QtLocation/qplacecontent.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacecontent.h" diff --git a/include/QtLocation/qplacecontentreply.h b/include/QtLocation/qplacecontentreply.h new file mode 100644 index 0000000..3129a8f --- /dev/null +++ b/include/QtLocation/qplacecontentreply.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacecontentreply.h" diff --git a/include/QtLocation/qplacecontentrequest.h b/include/QtLocation/qplacecontentrequest.h new file mode 100644 index 0000000..1578507 --- /dev/null +++ b/include/QtLocation/qplacecontentrequest.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacecontentrequest.h" diff --git a/include/QtLocation/qplacedetailsreply.h b/include/QtLocation/qplacedetailsreply.h new file mode 100644 index 0000000..586e16a --- /dev/null +++ b/include/QtLocation/qplacedetailsreply.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacedetailsreply.h" diff --git a/include/QtLocation/qplaceeditorial.h b/include/QtLocation/qplaceeditorial.h new file mode 100644 index 0000000..9dac346 --- /dev/null +++ b/include/QtLocation/qplaceeditorial.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplaceeditorial.h" diff --git a/include/QtLocation/qplaceicon.h b/include/QtLocation/qplaceicon.h new file mode 100644 index 0000000..558ac04 --- /dev/null +++ b/include/QtLocation/qplaceicon.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplaceicon.h" diff --git a/include/QtLocation/qplaceidreply.h b/include/QtLocation/qplaceidreply.h new file mode 100644 index 0000000..8d19185 --- /dev/null +++ b/include/QtLocation/qplaceidreply.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplaceidreply.h" diff --git a/include/QtLocation/qplaceimage.h b/include/QtLocation/qplaceimage.h new file mode 100644 index 0000000..856deb1 --- /dev/null +++ b/include/QtLocation/qplaceimage.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplaceimage.h" diff --git a/include/QtLocation/qplacemanager.h b/include/QtLocation/qplacemanager.h new file mode 100644 index 0000000..689e043 --- /dev/null +++ b/include/QtLocation/qplacemanager.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacemanager.h" diff --git a/include/QtLocation/qplacemanagerengine.h b/include/QtLocation/qplacemanagerengine.h new file mode 100644 index 0000000..8966e6d --- /dev/null +++ b/include/QtLocation/qplacemanagerengine.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacemanagerengine.h" diff --git a/include/QtLocation/qplacematchreply.h b/include/QtLocation/qplacematchreply.h new file mode 100644 index 0000000..123bd8f --- /dev/null +++ b/include/QtLocation/qplacematchreply.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacematchreply.h" diff --git a/include/QtLocation/qplacematchrequest.h b/include/QtLocation/qplacematchrequest.h new file mode 100644 index 0000000..bca1b69 --- /dev/null +++ b/include/QtLocation/qplacematchrequest.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacematchrequest.h" diff --git a/include/QtLocation/qplaceproposedsearchresult.h b/include/QtLocation/qplaceproposedsearchresult.h new file mode 100644 index 0000000..9a609b4 --- /dev/null +++ b/include/QtLocation/qplaceproposedsearchresult.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplaceproposedsearchresult.h" diff --git a/include/QtLocation/qplaceratings.h b/include/QtLocation/qplaceratings.h new file mode 100644 index 0000000..dc6ad10 --- /dev/null +++ b/include/QtLocation/qplaceratings.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplaceratings.h" diff --git a/include/QtLocation/qplacereply.h b/include/QtLocation/qplacereply.h new file mode 100644 index 0000000..96a2fef --- /dev/null +++ b/include/QtLocation/qplacereply.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacereply.h" diff --git a/include/QtLocation/qplaceresult.h b/include/QtLocation/qplaceresult.h new file mode 100644 index 0000000..48e4bed --- /dev/null +++ b/include/QtLocation/qplaceresult.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplaceresult.h" diff --git a/include/QtLocation/qplacereview.h b/include/QtLocation/qplacereview.h new file mode 100644 index 0000000..19273d9 --- /dev/null +++ b/include/QtLocation/qplacereview.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacereview.h" diff --git a/include/QtLocation/qplacesearchreply.h b/include/QtLocation/qplacesearchreply.h new file mode 100644 index 0000000..5e45879 --- /dev/null +++ b/include/QtLocation/qplacesearchreply.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacesearchreply.h" diff --git a/include/QtLocation/qplacesearchrequest.h b/include/QtLocation/qplacesearchrequest.h new file mode 100644 index 0000000..794ac51 --- /dev/null +++ b/include/QtLocation/qplacesearchrequest.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacesearchrequest.h" diff --git a/include/QtLocation/qplacesearchresult.h b/include/QtLocation/qplacesearchresult.h new file mode 100644 index 0000000..102d1e8 --- /dev/null +++ b/include/QtLocation/qplacesearchresult.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacesearchresult.h" diff --git a/include/QtLocation/qplacesearchsuggestionreply.h b/include/QtLocation/qplacesearchsuggestionreply.h new file mode 100644 index 0000000..72cdc6a --- /dev/null +++ b/include/QtLocation/qplacesearchsuggestionreply.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacesearchsuggestionreply.h" diff --git a/include/QtLocation/qplacesupplier.h b/include/QtLocation/qplacesupplier.h new file mode 100644 index 0000000..071102d --- /dev/null +++ b/include/QtLocation/qplacesupplier.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplacesupplier.h" diff --git a/include/QtLocation/qplaceuser.h b/include/QtLocation/qplaceuser.h new file mode 100644 index 0000000..88d3b28 --- /dev/null +++ b/include/QtLocation/qplaceuser.h @@ -0,0 +1 @@ +#include "../../src/location/places/qplaceuser.h" diff --git a/include/QtLocation/qtlocationversion.h b/include/QtLocation/qtlocationversion.h new file mode 100644 index 0000000..8a87c9f --- /dev/null +++ b/include/QtLocation/qtlocationversion.h @@ -0,0 +1,9 @@ +/* This file was generated by syncqt. */ +#ifndef QT_QTLOCATION_VERSION_H +#define QT_QTLOCATION_VERSION_H + +#define QTLOCATION_VERSION_STR "5.7.1" + +#define QTLOCATION_VERSION 0x050701 + +#endif // QT_QTLOCATION_VERSION_H diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qdeclarativegeoaddress_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qdeclarativegeoaddress_p.h new file mode 100644 index 0000000..56562a7 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qdeclarativegeoaddress_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qdeclarativegeoaddress_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qdeclarativegeolocation_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qdeclarativegeolocation_p.h new file mode 100644 index 0000000..ce5bbf3 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qdeclarativegeolocation_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qdeclarativegeolocation_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qdoublevector2d_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qdoublevector2d_p.h new file mode 100644 index 0000000..a679f2f --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qdoublevector2d_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qdoublevector2d_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qdoublevector3d_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qdoublevector3d_p.h new file mode 100644 index 0000000..6b1a13c --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qdoublevector3d_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qdoublevector3d_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qgeoaddress_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qgeoaddress_p.h new file mode 100644 index 0000000..b494007 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qgeoaddress_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qgeoaddress_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qgeocircle_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qgeocircle_p.h new file mode 100644 index 0000000..80a2f05 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qgeocircle_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qgeocircle_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qgeocoordinate_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qgeocoordinate_p.h new file mode 100644 index 0000000..53b5c3b --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qgeocoordinate_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qgeocoordinate_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qgeolocation_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qgeolocation_p.h new file mode 100644 index 0000000..15bd5a1 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qgeolocation_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qgeolocation_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qgeopositioninfosource_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qgeopositioninfosource_p.h new file mode 100644 index 0000000..a43d355 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qgeopositioninfosource_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qgeopositioninfosource_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qgeoprojection_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qgeoprojection_p.h new file mode 100644 index 0000000..d055679 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qgeoprojection_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qgeoprojection_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qgeorectangle_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qgeorectangle_p.h new file mode 100644 index 0000000..e4d2ac1 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qgeorectangle_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qgeorectangle_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qgeoshape_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qgeoshape_p.h new file mode 100644 index 0000000..ef4a35e --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qgeoshape_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qgeoshape_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qlocationdata_simulator_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qlocationdata_simulator_p.h new file mode 100644 index 0000000..ed0b911 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qlocationdata_simulator_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qlocationdata_simulator_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qlocationutils_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qlocationutils_p.h new file mode 100644 index 0000000..0c3d9cd --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qlocationutils_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qlocationutils_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qnmeapositioninfosource_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qnmeapositioninfosource_p.h new file mode 100644 index 0000000..2fd5904 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qnmeapositioninfosource_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qnmeapositioninfosource_p.h" diff --git a/include/QtPositioning/5.7.1/QtPositioning/private/qpositioningglobal_p.h b/include/QtPositioning/5.7.1/QtPositioning/private/qpositioningglobal_p.h new file mode 100644 index 0000000..657c470 --- /dev/null +++ b/include/QtPositioning/5.7.1/QtPositioning/private/qpositioningglobal_p.h @@ -0,0 +1 @@ +#include "../../../../../src/positioning/qpositioningglobal_p.h" diff --git a/include/QtPositioning/QGeoAddress b/include/QtPositioning/QGeoAddress new file mode 100644 index 0000000..708bcab --- /dev/null +++ b/include/QtPositioning/QGeoAddress @@ -0,0 +1 @@ +#include "qgeoaddress.h" diff --git a/include/QtPositioning/QGeoAreaMonitorInfo b/include/QtPositioning/QGeoAreaMonitorInfo new file mode 100644 index 0000000..7e137e6 --- /dev/null +++ b/include/QtPositioning/QGeoAreaMonitorInfo @@ -0,0 +1 @@ +#include "qgeoareamonitorinfo.h" diff --git a/include/QtPositioning/QGeoAreaMonitorSource b/include/QtPositioning/QGeoAreaMonitorSource new file mode 100644 index 0000000..942ccf6 --- /dev/null +++ b/include/QtPositioning/QGeoAreaMonitorSource @@ -0,0 +1 @@ +#include "qgeoareamonitorsource.h" diff --git a/include/QtPositioning/QGeoCircle b/include/QtPositioning/QGeoCircle new file mode 100644 index 0000000..b77d827 --- /dev/null +++ b/include/QtPositioning/QGeoCircle @@ -0,0 +1 @@ +#include "qgeocircle.h" diff --git a/include/QtPositioning/QGeoCoordinate b/include/QtPositioning/QGeoCoordinate new file mode 100644 index 0000000..812fb2a --- /dev/null +++ b/include/QtPositioning/QGeoCoordinate @@ -0,0 +1 @@ +#include "qgeocoordinate.h" diff --git a/include/QtPositioning/QGeoLocation b/include/QtPositioning/QGeoLocation new file mode 100644 index 0000000..bd38c75 --- /dev/null +++ b/include/QtPositioning/QGeoLocation @@ -0,0 +1 @@ +#include "qgeolocation.h" diff --git a/include/QtPositioning/QGeoPositionInfo b/include/QtPositioning/QGeoPositionInfo new file mode 100644 index 0000000..d6feec9 --- /dev/null +++ b/include/QtPositioning/QGeoPositionInfo @@ -0,0 +1 @@ +#include "qgeopositioninfo.h" diff --git a/include/QtPositioning/QGeoPositionInfoSource b/include/QtPositioning/QGeoPositionInfoSource new file mode 100644 index 0000000..b7cc338 --- /dev/null +++ b/include/QtPositioning/QGeoPositionInfoSource @@ -0,0 +1 @@ +#include "qgeopositioninfosource.h" diff --git a/include/QtPositioning/QGeoPositionInfoSourceFactory b/include/QtPositioning/QGeoPositionInfoSourceFactory new file mode 100644 index 0000000..7448436 --- /dev/null +++ b/include/QtPositioning/QGeoPositionInfoSourceFactory @@ -0,0 +1 @@ +#include "qgeopositioninfosourcefactory.h" diff --git a/include/QtPositioning/QGeoRectangle b/include/QtPositioning/QGeoRectangle new file mode 100644 index 0000000..9a7d48f --- /dev/null +++ b/include/QtPositioning/QGeoRectangle @@ -0,0 +1 @@ +#include "qgeorectangle.h" diff --git a/include/QtPositioning/QGeoSatelliteInfo b/include/QtPositioning/QGeoSatelliteInfo new file mode 100644 index 0000000..a3fd47d --- /dev/null +++ b/include/QtPositioning/QGeoSatelliteInfo @@ -0,0 +1 @@ +#include "qgeosatelliteinfo.h" diff --git a/include/QtPositioning/QGeoSatelliteInfoSource b/include/QtPositioning/QGeoSatelliteInfoSource new file mode 100644 index 0000000..cc6ba9d --- /dev/null +++ b/include/QtPositioning/QGeoSatelliteInfoSource @@ -0,0 +1 @@ +#include "qgeosatelliteinfosource.h" diff --git a/include/QtPositioning/QGeoShape b/include/QtPositioning/QGeoShape new file mode 100644 index 0000000..d86ddc3 --- /dev/null +++ b/include/QtPositioning/QGeoShape @@ -0,0 +1 @@ +#include "qgeoshape.h" diff --git a/include/QtPositioning/QNmeaPositionInfoSource b/include/QtPositioning/QNmeaPositionInfoSource new file mode 100644 index 0000000..5c261c9 --- /dev/null +++ b/include/QtPositioning/QNmeaPositionInfoSource @@ -0,0 +1 @@ +#include "qnmeapositioninfosource.h" diff --git a/include/QtPositioning/QtPositioning b/include/QtPositioning/QtPositioning new file mode 100644 index 0000000..90f0720 --- /dev/null +++ b/include/QtPositioning/QtPositioning @@ -0,0 +1,20 @@ +#ifndef QT_QTPOSITIONING_MODULE_H +#define QT_QTPOSITIONING_MODULE_H +#include +#include "qgeoaddress.h" +#include "qgeoareamonitorinfo.h" +#include "qgeoareamonitorsource.h" +#include "qgeocircle.h" +#include "qgeocoordinate.h" +#include "qgeolocation.h" +#include "qgeopositioninfo.h" +#include "qgeopositioninfosource.h" +#include "qgeopositioninfosourcefactory.h" +#include "qgeorectangle.h" +#include "qgeosatelliteinfo.h" +#include "qgeosatelliteinfosource.h" +#include "qgeoshape.h" +#include "qnmeapositioninfosource.h" +#include "qpositioningglobal.h" +#include "qtpositioningversion.h" +#endif diff --git a/include/QtPositioning/QtPositioningVersion b/include/QtPositioning/QtPositioningVersion new file mode 100644 index 0000000..2f99398 --- /dev/null +++ b/include/QtPositioning/QtPositioningVersion @@ -0,0 +1 @@ +#include "qtpositioningversion.h" diff --git a/include/QtPositioning/headers.pri b/include/QtPositioning/headers.pri new file mode 100644 index 0000000..0faa108 --- /dev/null +++ b/include/QtPositioning/headers.pri @@ -0,0 +1,6 @@ +SYNCQT.HEADER_FILES = qgeoaddress.h qgeoareamonitorinfo.h qgeoareamonitorsource.h qgeocircle.h qgeocoordinate.h qgeolocation.h qgeopositioninfo.h qgeopositioninfosource.h qgeopositioninfosourcefactory.h qgeorectangle.h qgeosatelliteinfo.h qgeosatelliteinfosource.h qgeoshape.h qnmeapositioninfosource.h qpositioningglobal.h ../../include/QtPositioning/qtpositioningversion.h ../../include/QtPositioning/QtPositioning +SYNCQT.HEADER_CLASSES = ../../include/QtPositioning/QGeoAddress ../../include/QtPositioning/QGeoAreaMonitorInfo ../../include/QtPositioning/QGeoAreaMonitorSource ../../include/QtPositioning/QGeoCircle ../../include/QtPositioning/QGeoCoordinate ../../include/QtPositioning/QGeoLocation ../../include/QtPositioning/QGeoPositionInfo ../../include/QtPositioning/QGeoPositionInfoSource ../../include/QtPositioning/QGeoPositionInfoSourceFactory ../../include/QtPositioning/QGeoRectangle ../../include/QtPositioning/QGeoSatelliteInfo ../../include/QtPositioning/QGeoSatelliteInfoSource ../../include/QtPositioning/QGeoShape ../../include/QtPositioning/QNmeaPositionInfoSource ../../include/QtPositioning/QtPositioningVersion +SYNCQT.PRIVATE_HEADER_FILES = qdeclarativegeoaddress_p.h qdeclarativegeolocation_p.h qdoublevector2d_p.h qdoublevector3d_p.h qgeoaddress_p.h qgeocircle_p.h qgeocoordinate_p.h qgeolocation_p.h qgeopositioninfosource_p.h qgeoprojection_p.h qgeorectangle_p.h qgeoshape_p.h qlocationdata_simulator_p.h qlocationutils_p.h qnmeapositioninfosource_p.h qpositioningglobal_p.h +SYNCQT.QPA_HEADER_FILES = +SYNCQT.CLEAN_HEADER_FILES = qgeoaddress.h qgeoareamonitorinfo.h qgeoareamonitorsource.h qgeocircle.h qgeocoordinate.h qgeolocation.h qgeopositioninfo.h qgeopositioninfosource.h qgeopositioninfosourcefactory.h qgeorectangle.h qgeosatelliteinfo.h qgeosatelliteinfosource.h qgeoshape.h qnmeapositioninfosource.h qpositioningglobal.h +SYNCQT.INJECTIONS = diff --git a/include/QtPositioning/qgeoaddress.h b/include/QtPositioning/qgeoaddress.h new file mode 100644 index 0000000..b8e0a99 --- /dev/null +++ b/include/QtPositioning/qgeoaddress.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeoaddress.h" diff --git a/include/QtPositioning/qgeoareamonitorinfo.h b/include/QtPositioning/qgeoareamonitorinfo.h new file mode 100644 index 0000000..f9a334c --- /dev/null +++ b/include/QtPositioning/qgeoareamonitorinfo.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeoareamonitorinfo.h" diff --git a/include/QtPositioning/qgeoareamonitorsource.h b/include/QtPositioning/qgeoareamonitorsource.h new file mode 100644 index 0000000..4555de8 --- /dev/null +++ b/include/QtPositioning/qgeoareamonitorsource.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeoareamonitorsource.h" diff --git a/include/QtPositioning/qgeocircle.h b/include/QtPositioning/qgeocircle.h new file mode 100644 index 0000000..f598c2c --- /dev/null +++ b/include/QtPositioning/qgeocircle.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeocircle.h" diff --git a/include/QtPositioning/qgeocoordinate.h b/include/QtPositioning/qgeocoordinate.h new file mode 100644 index 0000000..93b16d9 --- /dev/null +++ b/include/QtPositioning/qgeocoordinate.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeocoordinate.h" diff --git a/include/QtPositioning/qgeolocation.h b/include/QtPositioning/qgeolocation.h new file mode 100644 index 0000000..59429ea --- /dev/null +++ b/include/QtPositioning/qgeolocation.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeolocation.h" diff --git a/include/QtPositioning/qgeopositioninfo.h b/include/QtPositioning/qgeopositioninfo.h new file mode 100644 index 0000000..213fbb2 --- /dev/null +++ b/include/QtPositioning/qgeopositioninfo.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeopositioninfo.h" diff --git a/include/QtPositioning/qgeopositioninfosource.h b/include/QtPositioning/qgeopositioninfosource.h new file mode 100644 index 0000000..8f7082d --- /dev/null +++ b/include/QtPositioning/qgeopositioninfosource.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeopositioninfosource.h" diff --git a/include/QtPositioning/qgeopositioninfosourcefactory.h b/include/QtPositioning/qgeopositioninfosourcefactory.h new file mode 100644 index 0000000..e59bdd9 --- /dev/null +++ b/include/QtPositioning/qgeopositioninfosourcefactory.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeopositioninfosourcefactory.h" diff --git a/include/QtPositioning/qgeorectangle.h b/include/QtPositioning/qgeorectangle.h new file mode 100644 index 0000000..f4a6526 --- /dev/null +++ b/include/QtPositioning/qgeorectangle.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeorectangle.h" diff --git a/include/QtPositioning/qgeosatelliteinfo.h b/include/QtPositioning/qgeosatelliteinfo.h new file mode 100644 index 0000000..1c1d631 --- /dev/null +++ b/include/QtPositioning/qgeosatelliteinfo.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeosatelliteinfo.h" diff --git a/include/QtPositioning/qgeosatelliteinfosource.h b/include/QtPositioning/qgeosatelliteinfosource.h new file mode 100644 index 0000000..a3115b1 --- /dev/null +++ b/include/QtPositioning/qgeosatelliteinfosource.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeosatelliteinfosource.h" diff --git a/include/QtPositioning/qgeoshape.h b/include/QtPositioning/qgeoshape.h new file mode 100644 index 0000000..6e7d4db --- /dev/null +++ b/include/QtPositioning/qgeoshape.h @@ -0,0 +1 @@ +#include "../../src/positioning/qgeoshape.h" diff --git a/include/QtPositioning/qnmeapositioninfosource.h b/include/QtPositioning/qnmeapositioninfosource.h new file mode 100644 index 0000000..6f5d63d --- /dev/null +++ b/include/QtPositioning/qnmeapositioninfosource.h @@ -0,0 +1 @@ +#include "../../src/positioning/qnmeapositioninfosource.h" diff --git a/include/QtPositioning/qpositioningglobal.h b/include/QtPositioning/qpositioningglobal.h new file mode 100644 index 0000000..a291214 --- /dev/null +++ b/include/QtPositioning/qpositioningglobal.h @@ -0,0 +1 @@ +#include "../../src/positioning/qpositioningglobal.h" diff --git a/include/QtPositioning/qtpositioningversion.h b/include/QtPositioning/qtpositioningversion.h new file mode 100644 index 0000000..0a35884 --- /dev/null +++ b/include/QtPositioning/qtpositioningversion.h @@ -0,0 +1,9 @@ +/* This file was generated by syncqt. */ +#ifndef QT_QTPOSITIONING_VERSION_H +#define QT_QTPOSITIONING_VERSION_H + +#define QTPOSITIONING_VERSION_STR "5.7.1" + +#define QTPOSITIONING_VERSION 0x050701 + +#endif // QT_QTPOSITIONING_VERSION_H diff --git a/qtlocation.pro b/qtlocation.pro new file mode 100644 index 0000000..3104465 --- /dev/null +++ b/qtlocation.pro @@ -0,0 +1,4 @@ +load(configure) +qtCompileTest(gypsy) + +load(qt_parts) diff --git a/src/3rdparty/3rdparty.pro b/src/3rdparty/3rdparty.pro new file mode 100644 index 0000000..72996c7 --- /dev/null +++ b/src/3rdparty/3rdparty.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS += poly2tri +SUBDIRS += clipper +SUBDIRS += clip2tri diff --git a/src/3rdparty/clip2tri/LICENSE b/src/3rdparty/clip2tri/LICENSE new file mode 100644 index 0000000..9d99b88 --- /dev/null +++ b/src/3rdparty/clip2tri/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Bitfighter developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/3rdparty/clip2tri/clip2tri.cpp b/src/3rdparty/clip2tri/clip2tri.cpp new file mode 100644 index 0000000..86870fc --- /dev/null +++ b/src/3rdparty/clip2tri/clip2tri.cpp @@ -0,0 +1,312 @@ +/* + * Authors: kaen, raptor, sam686, watusimoto + * + * Originally from the bitfighter source code + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Bitfighter developers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "clip2tri.h" +#include "../poly2tri/poly2tri.h" + +#include + + +using namespace p2t; + +namespace c2t +{ + + +static const F32 CLIPPER_SCALE_FACT = 1000.0f; +static const F32 CLIPPER_SCALE_FACT_INVERSE = 0.001f; + + +///////////////////////////////// + +Point::Point() +{ + x = 0; + y = 0; +} + +Point::Point(const Point& pt) +{ + x = pt.x; + y = pt.y; +} + + +///////////////////////////////// + +clip2tri::clip2tri() +{ + // Do nothing! +} + +clip2tri::~clip2tri() +{ + // Do nothing! +} + + +void clip2tri::triangulate(const vector > &inputPolygons, vector &outputTriangles, + const vector &boundingPolygon) +{ + // Use clipper to clean. This upscales the floating point input + PolyTree solution; + mergePolysToPolyTree(inputPolygons, solution); + + Path bounds = upscaleClipperPoints(boundingPolygon); + + // This will downscale the Clipper output and use poly2tri to triangulate + triangulateComplex(outputTriangles, bounds, solution); +} + + +Path clip2tri::upscaleClipperPoints(const vector &inputPolygon) +{ + Path outputPolygon; + outputPolygon.resize(inputPolygon.size()); + + for(S32 i = 0; i < inputPolygon.size(); i++) + outputPolygon[i] = IntPoint(S64(inputPolygon[i].x * CLIPPER_SCALE_FACT), S64(inputPolygon[i].y * CLIPPER_SCALE_FACT)); + + return outputPolygon; +} + + +Paths clip2tri::upscaleClipperPoints(const vector > &inputPolygons) +{ + Paths outputPolygons; + + outputPolygons.resize(inputPolygons.size()); + + for(S32 i = 0; i < inputPolygons.size(); i++) + { + outputPolygons[i].resize(inputPolygons[i].size()); + + for(S32 j = 0; j < inputPolygons[i].size(); j++) + outputPolygons[i][j] = IntPoint(S64(inputPolygons[i][j].x * CLIPPER_SCALE_FACT), S64(inputPolygons[i][j].y * CLIPPER_SCALE_FACT)); + } + + return outputPolygons; +} + + +vector > clip2tri::downscaleClipperPoints(const Paths &inputPolygons) +{ + vector > outputPolygons; + + outputPolygons.resize(inputPolygons.size()); + + for(U32 i = 0; i < inputPolygons.size(); i++) + { + outputPolygons[i].resize(inputPolygons[i].size()); + + for(U32 j = 0; j < inputPolygons[i].size(); j++) + outputPolygons[i][j] = Point(F32(inputPolygons[i][j].X) * CLIPPER_SCALE_FACT_INVERSE, F32(inputPolygons[i][j].Y) * CLIPPER_SCALE_FACT_INVERSE); + } + + return outputPolygons; +} + + +// Use Clipper to merge inputPolygons, placing the result in a Polytree +// NOTE: this does NOT downscale the Clipper points. You must do this afterwards +// +// Here you add all your non-navigatable objects (e.g. walls, barriers, etc.) +bool clip2tri::mergePolysToPolyTree(const vector > &inputPolygons, PolyTree &solution) +{ + Paths input = upscaleClipperPoints(inputPolygons); + + // Fire up clipper and union! + Clipper clipper; + clipper.StrictlySimple(true); + + try // there is a "throw" in AddPolygon + { + clipper.AddPaths(input, ptSubject, true); + } + catch(...) + { + printf("clipper.AddPaths, something went wrong\n"); + } + + return clipper.Execute(ctUnion, solution, pftNonZero, pftNonZero); +} + + +// Delete all poly2tri points from a vector and clear the vector +static void deleteAndClear(vector &vec) +{ + for(U32 i = 0; i < vec.size(); i++) + delete vec[i]; + + vec.clear(); +} + + +// Shrink large polygons by reducing each coordinate by 1 in the +// general direction of the last point as we wind around +// +// This normally wouldn't work in every case, but our upscaled-by-1000 polygons +// have little chance to create new duplicate points with this method. +// +// For information on why this was needed, see: +// +// https://code.google.com/p/poly2tri/issues/detail?id=90 +// +static void edgeShrink(Path &path) +{ + U32 prev = path.size() - 1; + for(U32 i = 0; i < path.size(); i++) + { + // Adjust coordinate by 1 depending on the direction + path[i].X - path[prev].X > 0 ? path[i].X-- : path[i].X++; + path[i].Y - path[prev].Y > 0 ? path[i].Y-- : path[i].Y++; + + prev = i; + } +} + + +// This uses poly2tri to triangulate. poly2tri isn't very robust so clipper needs to do +// the cleaning of points before getting here. +// +// A tree structure of polygons is required for doing complex polygons-within-polygons. +// For reference discussion on how this started to be developed, see here: +// +// https://code.google.com/p/poly2tri/issues/detail?id=74 +// +// For assistance with a special case crash, see this utility: +// http://javascript.poly2tri.googlecode.com/hg/index.html +// +// FIXME: what is ignoreFills and ignoreHoles for? kaen? +bool clip2tri::triangulateComplex(vector &outputTriangles, const Path &outline, + const PolyTree &polyTree, bool ignoreFills, bool ignoreHoles) +{ + // Keep track of memory for all the poly2tri objects we create + vector cdtRegistry; + vector > holesRegistry; + vector > polylinesRegistry; + + + // Let's be tricky and add our outline to the root node (it should have none), it'll be + // our first Clipper hole + PolyNode *rootNode = NULL; + + PolyNode tempNode; + if(polyTree.Total() == 0) // Polytree is empty with no root node, e.g. on an empty level + rootNode = &tempNode; + else + rootNode = polyTree.GetFirst()->Parent; + + rootNode->Contour = outline; + + // Now traverse our polyline nodes and triangulate them with only their children holes + PolyNode *currentNode = rootNode; + while(currentNode != NULL) + { + // A Clipper hole is actually what we want to build zones for; they become our bounding + // polylines. poly2tri holes are therefore the inverse + if((!ignoreHoles && currentNode->IsHole()) || + (!ignoreFills && !currentNode->IsHole())) + { + // Build up this polyline in poly2tri's format (downscale Clipper points) + vector polyline; + for(U32 j = 0; j < currentNode->Contour.size(); j++) + polyline.push_back(new p2t::Point(F64(currentNode->Contour[j].X), F64(currentNode->Contour[j].Y))); + + polylinesRegistry.push_back(polyline); // Memory + + // Set our polyline in poly2tri + p2t::CDT* cdt = new p2t::CDT(polyline); + cdtRegistry.push_back(cdt); + + for(U32 j = 0; j < currentNode->Childs.size(); j++) + { + PolyNode *childNode = currentNode->Childs[j]; + + // Slightly modify the polygon to guarantee no duplicate points + edgeShrink(childNode->Contour); + + vector hole; + for(U32 k = 0; k < childNode->Contour.size(); k++) + hole.push_back(new p2t::Point(F64(childNode->Contour[k].X), F64(childNode->Contour[k].Y))); + + holesRegistry.push_back(hole); // Memory + + // Add the holes for this polyline + cdt->AddHole(hole); + } + + cdt->Triangulate(); + + // Add current output triangles to our total + vector currentOutput = cdt->GetTriangles(); + + // Copy our data to TNL::Point and to our output Vector + p2t::Triangle *currentTriangle; + for(U32 j = 0; j < currentOutput.size(); j++) + { + currentTriangle = currentOutput[j]; + outputTriangles.push_back(Point(currentTriangle->GetPoint(0)->x * CLIPPER_SCALE_FACT_INVERSE, currentTriangle->GetPoint(0)->y * CLIPPER_SCALE_FACT_INVERSE)); + outputTriangles.push_back(Point(currentTriangle->GetPoint(1)->x * CLIPPER_SCALE_FACT_INVERSE, currentTriangle->GetPoint(1)->y * CLIPPER_SCALE_FACT_INVERSE)); + outputTriangles.push_back(Point(currentTriangle->GetPoint(2)->x * CLIPPER_SCALE_FACT_INVERSE, currentTriangle->GetPoint(2)->y * CLIPPER_SCALE_FACT_INVERSE)); + } + } + + currentNode = currentNode->GetNext(); + } + + + // Clean up memory used with poly2tri + // + // Clean-up workers + for(S32 i = 0; i < cdtRegistry.size(); i++) + delete cdtRegistry[i]; + + // Free the polylines + for(S32 i = 0; i < polylinesRegistry.size(); i++) + { + vector polyline = polylinesRegistry[i]; + deleteAndClear(polyline); + } + + // Free the holes + for(S32 i = 0; i < holesRegistry.size(); i++) + { + vector hole = holesRegistry[i]; + deleteAndClear(hole); + } + + // Make sure we have output data + if(outputTriangles.size() == 0) + return false; + + return true; +} + + +} /* namespace c2t */ diff --git a/src/3rdparty/clip2tri/clip2tri.h b/src/3rdparty/clip2tri/clip2tri.h new file mode 100644 index 0000000..982c804 --- /dev/null +++ b/src/3rdparty/clip2tri/clip2tri.h @@ -0,0 +1,86 @@ +/* + * Authors: kaen, raptor, sam686, watusimoto + * + * Originally from the bitfighter source code + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Bitfighter developers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef CLIP2TRI_H_ +#define CLIP2TRI_H_ + +#include +#include "../clipper/clipper.h" + +using namespace std; +using namespace ClipperLib; + +namespace c2t +{ + +typedef signed int S32; +typedef signed long long S64; +typedef unsigned int U32; +typedef float F32; +typedef double F64; + + +struct Point +{ + F32 x; + F32 y; + + Point(); + Point(const Point &pt); + + template + Point(T in_x, U in_y) { x = static_cast(in_x); y = static_cast(in_y); } +}; + + +class clip2tri +{ +private: + // + Path upscaleClipperPoints(const vector &inputPolygon); + + // These operate on a vector of polygons + Paths upscaleClipperPoints(const vector > &inputPolygons); + vector > downscaleClipperPoints(const Paths &inputPolygons); + + bool mergePolysToPolyTree(const vector > &inputPolygons, PolyTree &solution); + + bool triangulateComplex(vector &outputTriangles, const Path &outline, + const PolyTree &polyTree, bool ignoreFills = true, bool ignoreHoles = false); + +public: + clip2tri(); + virtual ~clip2tri(); + + void triangulate(const vector > &inputPolygons, vector &outputTriangles, + const vector &boundingPolygon); +}; + +} /* namespace c2t */ + +#endif /* CLIP2TRI_H_ */ diff --git a/src/3rdparty/clip2tri/clip2tri.pro b/src/3rdparty/clip2tri/clip2tri.pro new file mode 100644 index 0000000..50901c0 --- /dev/null +++ b/src/3rdparty/clip2tri/clip2tri.pro @@ -0,0 +1,18 @@ +TARGET = clip2tri + +CONFIG += staticlib exceptions + +load(qt_helper_lib) + +# workaround for QTBUG-31586 +contains(QT_CONFIG, c++11): CONFIG += c++11 + +*-g++* { + QMAKE_CXXFLAGS += -O3 -ftree-vectorize -ffast-math -funsafe-math-optimizations -Wno-error=return-type +} + +HEADERS += clip2tri.h +SOURCES += clip2tri.cpp + +LIBS_PRIVATE += -L$$MODULE_BASE_OUTDIR/lib -lpoly2tri$$qtPlatformTargetSuffix() -lclipper$$qtPlatformTargetSuffix() + diff --git a/src/3rdparty/clip2tri_legal.qdoc b/src/3rdparty/clip2tri_legal.qdoc new file mode 100644 index 0000000..65a5fa7 --- /dev/null +++ b/src/3rdparty/clip2tri_legal.qdoc @@ -0,0 +1,32 @@ +/*! +\page legal-clip2tri.html +\title Clip2Tri Polygon Triangulation Library +\ingroup licensing + +\legalese +\code +Clip2Tri Copyright (c) 2014 Bitfighter developers +https://github.com/raptor/clip2tri + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +\endcode +\endlegalese +*/ diff --git a/src/3rdparty/clipper/clipper.cpp b/src/3rdparty/clipper/clipper.cpp new file mode 100644 index 0000000..7a27bc4 --- /dev/null +++ b/src/3rdparty/clipper/clipper.cpp @@ -0,0 +1,4605 @@ +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 6.1.3a * +* Date : 22 January 2014 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2014 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24-28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +/******************************************************************************* +* * +* This is a translation of the Delphi Clipper library and the naming style * +* used has retained a Delphi flavour. * +* * +*******************************************************************************/ + +#include "clipper.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ClipperLib { + +#ifdef use_int32 + static cInt const loRange = 46340; + static cInt const hiRange = 46340; +#else + static cInt const loRange = 0x3FFFFFFF; + static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; + typedef unsigned long long ulong64; +#endif + +static double const pi = 3.141592653589793238; +static double const two_pi = pi *2; +static double const def_arc_tolerance = 0.25; + +enum Direction { dRightToLeft, dLeftToRight }; + +static int const Unassigned = -1; //edge not currently 'owning' a solution +static int const Skip = -2; //edge that would otherwise close a path + +#define HORIZONTAL (-1.0E+40) +#define TOLERANCE (1.0e-20) +#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) + +struct TEdge { + IntPoint Bot; + IntPoint Curr; + IntPoint Top; + IntPoint Delta; + double Dx; + PolyType PolyTyp; + EdgeSide Side; + int WindDelta; //1 or -1 depending on winding direction + int WindCnt; + int WindCnt2; //winding count of the opposite polytype + int OutIdx; + TEdge *Next; + TEdge *Prev; + TEdge *NextInLML; + TEdge *NextInAEL; + TEdge *PrevInAEL; + TEdge *NextInSEL; + TEdge *PrevInSEL; +}; + +struct IntersectNode { + TEdge *Edge1; + TEdge *Edge2; + IntPoint Pt; +}; + +struct LocalMinima { + cInt Y; + TEdge *LeftBound; + TEdge *RightBound; + LocalMinima *Next; +}; + +struct OutPt; + +struct OutRec { + int Idx; + bool IsHole; + bool IsOpen; + OutRec *FirstLeft; //see comments in clipper.pas + PolyNode *PolyNd; + OutPt *Pts; + OutPt *BottomPt; +}; + +struct OutPt { + int Idx; + IntPoint Pt; + OutPt *Next; + OutPt *Prev; +}; + +struct Join { + OutPt *OutPt1; + OutPt *OutPt2; + IntPoint OffPt; +}; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +inline cInt Round(double val) +{ + if ((val < 0)) return static_cast(val - 0.5); + else return static_cast(val + 0.5); +} +//------------------------------------------------------------------------------ + +inline cInt Abs(cInt val) +{ + return val < 0 ? -val : val; +} + +//------------------------------------------------------------------------------ +// PolyTree methods ... +//------------------------------------------------------------------------------ + +void PolyTree::Clear() +{ + for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i) + delete AllNodes[i]; + AllNodes.resize(0); + Childs.resize(0); +} +//------------------------------------------------------------------------------ + +PolyNode* PolyTree::GetFirst() const +{ + if (!Childs.empty()) + return Childs[0]; + else + return 0; +} +//------------------------------------------------------------------------------ + +int PolyTree::Total() const +{ + return (int)AllNodes.size(); +} + +//------------------------------------------------------------------------------ +// PolyNode methods ... +//------------------------------------------------------------------------------ + +PolyNode::PolyNode(): Childs(), Parent(0), Index(0), m_IsOpen(false) +{ +} +//------------------------------------------------------------------------------ + +int PolyNode::ChildCount() const +{ + return (int)Childs.size(); +} +//------------------------------------------------------------------------------ + +void PolyNode::AddChild(PolyNode& child) +{ + unsigned cnt = (unsigned)Childs.size(); + Childs.push_back(&child); + child.Parent = this; + child.Index = cnt; +} +//------------------------------------------------------------------------------ + +PolyNode* PolyNode::GetNext() const +{ + if (!Childs.empty()) + return Childs[0]; + else + return GetNextSiblingUp(); +} +//------------------------------------------------------------------------------ + +PolyNode* PolyNode::GetNextSiblingUp() const +{ + if (!Parent) //protects against PolyTree.GetNextSiblingUp() + return 0; + else if (Index == Parent->Childs.size() - 1) + return Parent->GetNextSiblingUp(); + else + return Parent->Childs[Index + 1]; +} +//------------------------------------------------------------------------------ + +bool PolyNode::IsHole() const +{ + bool result = true; + PolyNode* node = Parent; + while (node) + { + result = !result; + node = node->Parent; + } + return result; +} +//------------------------------------------------------------------------------ + +bool PolyNode::IsOpen() const +{ + return m_IsOpen; +} +//------------------------------------------------------------------------------ + +#ifndef use_int32 + +//------------------------------------------------------------------------------ +// Int128 class (enables safe math on signed 64bit integers) +// eg Int128 val1((cInt)9223372036854775807); //ie 2^63 -1 +// Int128 val2((cInt)9223372036854775807); +// Int128 val3 = val1 * val2; +// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) +//------------------------------------------------------------------------------ + +class Int128 +{ + public: + + cUInt lo; + cInt hi; + + Int128(cInt _lo = 0) + { + lo = (cUInt)_lo; + if (_lo < 0) hi = -1; else hi = 0; + } + + + Int128(const Int128 &val): lo(val.lo), hi(val.hi){} + + Int128(const cInt& _hi, const ulong64& _lo): lo(_lo), hi(_hi){} + + Int128& operator = (const cInt &val) + { + lo = (ulong64)val; + if (val < 0) hi = -1; else hi = 0; + return *this; + } + + bool operator == (const Int128 &val) const + {return (hi == val.hi && lo == val.lo);} + + bool operator != (const Int128 &val) const + { return !(*this == val);} + + bool operator > (const Int128 &val) const + { + if (hi != val.hi) + return hi > val.hi; + else + return lo > val.lo; + } + + bool operator < (const Int128 &val) const + { + if (hi != val.hi) + return hi < val.hi; + else + return lo < val.lo; + } + + bool operator >= (const Int128 &val) const + { return !(*this < val);} + + bool operator <= (const Int128 &val) const + { return !(*this > val);} + + Int128& operator += (const Int128 &rhs) + { + hi += rhs.hi; + lo += rhs.lo; + if (lo < rhs.lo) hi++; + return *this; + } + + Int128 operator + (const Int128 &rhs) const + { + Int128 result(*this); + result+= rhs; + return result; + } + + Int128& operator -= (const Int128 &rhs) + { + *this += -rhs; + return *this; + } + + Int128 operator - (const Int128 &rhs) const + { + Int128 result(*this); + result -= rhs; + return result; + } + + Int128 operator-() const //unary negation + { + if (lo == 0) + return Int128(-hi,0); + else + return Int128(~hi,~lo +1); + } + + Int128 operator/ (const Int128 &rhs) const + { + if (rhs.lo == 0 && rhs.hi == 0) + throw "Int128 operator/: divide by zero"; + + bool negate = (rhs.hi < 0) != (hi < 0); + Int128 dividend = *this; + Int128 divisor = rhs; + if (dividend.hi < 0) dividend = -dividend; + if (divisor.hi < 0) divisor = -divisor; + + if (divisor < dividend) + { + Int128 result = Int128(0); + Int128 cntr = Int128(1); + while (divisor.hi >= 0 && !(divisor > dividend)) + { + divisor.hi <<= 1; + if ((cInt)divisor.lo < 0) divisor.hi++; + divisor.lo <<= 1; + + cntr.hi <<= 1; + if ((cInt)cntr.lo < 0) cntr.hi++; + cntr.lo <<= 1; + } + divisor.lo >>= 1; + if ((divisor.hi & 1) == 1) + divisor.lo |= 0x8000000000000000LL; + divisor.hi = (ulong64)divisor.hi >> 1; + + cntr.lo >>= 1; + if ((cntr.hi & 1) == 1) + cntr.lo |= 0x8000000000000000LL; + cntr.hi >>= 1; + + while (cntr.hi != 0 || cntr.lo != 0) + { + if (!(dividend < divisor)) + { + dividend -= divisor; + result.hi |= cntr.hi; + result.lo |= cntr.lo; + } + divisor.lo >>= 1; + if ((divisor.hi & 1) == 1) + divisor.lo |= 0x8000000000000000LL; + divisor.hi >>= 1; + + cntr.lo >>= 1; + if ((cntr.hi & 1) == 1) + cntr.lo |= 0x8000000000000000LL; + cntr.hi >>= 1; + } + if (negate) result = -result; + return result; + } + else if (rhs.hi == this->hi && rhs.lo == this->lo) + return Int128(negate ? -1: 1); + else + return Int128(0); + } + + double AsDouble() const + { + const double shift64 = 18446744073709551616.0; //2^64 + if (hi < 0) + { + cUInt lo_ = ~lo + 1; + if (lo_ == 0) return (double)hi * shift64; + else return -(double)(lo_ + ~hi * shift64); + } + else + return (double)(lo + hi * shift64); + } + +}; +//------------------------------------------------------------------------------ + +Int128 Int128Mul (cInt lhs, cInt rhs) +{ + bool negate = (lhs < 0) != (rhs < 0); + + if (lhs < 0) lhs = -lhs; + ulong64 int1Hi = ulong64(lhs) >> 32; + ulong64 int1Lo = ulong64(lhs & 0xFFFFFFFF); + + if (rhs < 0) rhs = -rhs; + ulong64 int2Hi = ulong64(rhs) >> 32; + ulong64 int2Lo = ulong64(rhs & 0xFFFFFFFF); + + //nb: see comments in clipper.pas + ulong64 a = int1Hi * int2Hi; + ulong64 b = int1Lo * int2Lo; + ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; + + Int128 tmp; + tmp.hi = cInt(a + (c >> 32)); + tmp.lo = cInt(c << 32); + tmp.lo += cInt(b); + if (tmp.lo < b) tmp.hi++; + if (negate) tmp = -tmp; + return tmp; +}; +#endif + +//------------------------------------------------------------------------------ +// Miscellaneous global functions +//------------------------------------------------------------------------------ + +bool Orientation(const Path &poly) +{ + return Area(poly) >= 0; +} +//------------------------------------------------------------------------------ + +double Area(const Path &poly) +{ + int size = (int)poly.size(); + if (size < 3) return 0; + + double a = 0; + for (int i = 0, j = size -1; i < size; ++i) + { + a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y); + j = i; + } + return -a * 0.5; +} +//------------------------------------------------------------------------------ + +double Area(const OutRec &outRec) +{ + OutPt *op = outRec.Pts; + if (!op) return 0; + double a = 0; + do { + a += (double)(op->Prev->Pt.X + op->Pt.X) * (double)(op->Prev->Pt.Y - op->Pt.Y); + op = op->Next; + } while (op != outRec.Pts); + return a * 0.5; +} +//------------------------------------------------------------------------------ + +bool PointIsVertex(const IntPoint &Pt, OutPt *pp) +{ + OutPt *pp2 = pp; + do + { + if (pp2->Pt == Pt) return true; + pp2 = pp2->Next; + } + while (pp2 != pp); + return false; +} +//------------------------------------------------------------------------------ + +int PointInPolygon (const IntPoint &pt, const Path &path) +{ + //returns 0 if false, +1 if true, -1 if pt ON polygon boundary + //http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf + int result = 0; + size_t cnt = path.size(); + if (cnt < 3) return 0; + IntPoint ip = path[0]; + for(size_t i = 1; i <= cnt; ++i) + { + IntPoint ipNext = (i == cnt ? path[0] : path[i]); + if (ipNext.Y == pt.Y) + { + if ((ipNext.X == pt.X) || (ip.Y == pt.Y && + ((ipNext.X > pt.X) == (ip.X < pt.X)))) return -1; + } + if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y)) + { + if (ip.X >= pt.X) + { + if (ipNext.X > pt.X) result = 1 - result; + else + { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - + (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; + } + } else + { + if (ipNext.X > pt.X) + { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - + (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; + } + } + } + ip = ipNext; + } + return result; +} +//------------------------------------------------------------------------------ + +int PointInPolygon (const IntPoint &pt, OutPt *op) +{ + //returns 0 if false, +1 if true, -1 if pt ON polygon boundary + //http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf + int result = 0; + OutPt* startOp = op; + for(;;) + { + if (op->Next->Pt.Y == pt.Y) + { + if ((op->Next->Pt.X == pt.X) || (op->Pt.Y == pt.Y && + ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) return -1; + } + if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y)) + { + if (op->Pt.X >= pt.X) + { + if (op->Next->Pt.X > pt.X) result = 1 - result; + else + { + double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - + (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; + } + } else + { + if (op->Next->Pt.X > pt.X) + { + double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - + (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; + } + } + } + op = op->Next; + if (startOp == op) break; + } + return result; +} +//------------------------------------------------------------------------------ + +bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2) +{ + OutPt* op = OutPt1; + do + { + int res = PointInPolygon(op->Pt, OutPt2); + if (res >= 0) return res != 0; + op = op->Next; + } + while (op != OutPt1); + return true; +} +//---------------------------------------------------------------------- + +bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range) +{ +#ifndef use_int32 + if (UseFullInt64Range) + return Int128Mul(e1.Delta.Y, e2.Delta.X) == Int128Mul(e1.Delta.X, e2.Delta.Y); + else +#endif + return e1.Delta.Y * e2.Delta.X == e1.Delta.X * e2.Delta.Y; +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, bool UseFullInt64Range) +{ +#ifndef use_int32 + if (UseFullInt64Range) + return Int128Mul(pt1.Y-pt2.Y, pt2.X-pt3.X) == Int128Mul(pt1.X-pt2.X, pt2.Y-pt3.Y); + else +#endif + return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) +{ +#ifndef use_int32 + if (UseFullInt64Range) + return Int128Mul(pt1.Y-pt2.Y, pt3.X-pt4.X) == Int128Mul(pt1.X-pt2.X, pt3.Y-pt4.Y); + else +#endif + return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); +} +//------------------------------------------------------------------------------ + +inline bool IsHorizontal(TEdge &e) +{ + return e.Delta.Y == 0; +} +//------------------------------------------------------------------------------ + +inline double GetDx(const IntPoint pt1, const IntPoint pt2) +{ + return (pt1.Y == pt2.Y) ? + HORIZONTAL : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y); +} +//--------------------------------------------------------------------------- + +inline void SetDx(TEdge &e) +{ + e.Delta.X = (e.Top.X - e.Bot.X); + e.Delta.Y = (e.Top.Y - e.Bot.Y); + + if (e.Delta.Y == 0) e.Dx = HORIZONTAL; + else e.Dx = (double)(e.Delta.X) / e.Delta.Y; +} +//--------------------------------------------------------------------------- + +inline void SwapSides(TEdge &Edge1, TEdge &Edge2) +{ + EdgeSide Side = Edge1.Side; + Edge1.Side = Edge2.Side; + Edge2.Side = Side; +} +//------------------------------------------------------------------------------ + +inline void SwapPolyIndexes(TEdge &Edge1, TEdge &Edge2) +{ + int OutIdx = Edge1.OutIdx; + Edge1.OutIdx = Edge2.OutIdx; + Edge2.OutIdx = OutIdx; +} +//------------------------------------------------------------------------------ + +inline cInt TopX(TEdge &edge, const cInt currentY) +{ + return ( currentY == edge.Top.Y ) ? + edge.Top.X : edge.Bot.X + Round(edge.Dx *(currentY - edge.Bot.Y)); +} +//------------------------------------------------------------------------------ + +bool IntersectPoint(TEdge &Edge1, TEdge &Edge2, + IntPoint &ip, bool UseFullInt64Range) +{ +#ifdef use_xyz + ip.Z = 0; +#endif + double b1, b2; + //nb: with very large coordinate values, it's possible for SlopesEqual() to + //return false but for the edge.Dx value be equal due to double precision rounding. + if (SlopesEqual(Edge1, Edge2, UseFullInt64Range) || Edge1.Dx == Edge2.Dx) + { + if (Edge2.Bot.Y > Edge1.Bot.Y) ip = Edge2.Bot; + else ip = Edge1.Bot; + return false; + } + else if (Edge1.Delta.X == 0) + { + ip.X = Edge1.Bot.X; + if (IsHorizontal(Edge2)) + ip.Y = Edge2.Bot.Y; + else + { + b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx); + ip.Y = Round(ip.X / Edge2.Dx + b2); + } + } + else if (Edge2.Delta.X == 0) + { + ip.X = Edge2.Bot.X; + if (IsHorizontal(Edge1)) + ip.Y = Edge1.Bot.Y; + else + { + b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx); + ip.Y = Round(ip.X / Edge1.Dx + b1); + } + } + else + { + b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx; + b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx; + double q = (b2-b1) / (Edge1.Dx - Edge2.Dx); + ip.Y = Round(q); + if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) + ip.X = Round(Edge1.Dx * q + b1); + else + ip.X = Round(Edge2.Dx * q + b2); + } + + if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y) + { + if (Edge1.Top.Y > Edge2.Top.Y) + ip.Y = Edge1.Top.Y; + else + ip.Y = Edge2.Top.Y; + if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) + ip.X = TopX(Edge1, ip.Y); + else + ip.X = TopX(Edge2, ip.Y); + } + return true; +} +//------------------------------------------------------------------------------ + +void ReversePolyPtLinks(OutPt *pp) +{ + if (!pp) return; + OutPt *pp1, *pp2; + pp1 = pp; + do { + pp2 = pp1->Next; + pp1->Next = pp1->Prev; + pp1->Prev = pp2; + pp1 = pp2; + } while( pp1 != pp ); +} +//------------------------------------------------------------------------------ + +void DisposeOutPts(OutPt*& pp) +{ + if (pp == 0) return; + pp->Prev->Next = 0; + while( pp ) + { + OutPt *tmpPp = pp; + pp = pp->Next; + delete tmpPp; + } +} +//------------------------------------------------------------------------------ + +inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt) +{ + std::memset(e, 0, sizeof(TEdge)); + e->Next = eNext; + e->Prev = ePrev; + e->Curr = Pt; + e->OutIdx = Unassigned; +} +//------------------------------------------------------------------------------ + +void InitEdge2(TEdge& e, PolyType Pt) +{ + if (e.Curr.Y >= e.Next->Curr.Y) + { + e.Bot = e.Curr; + e.Top = e.Next->Curr; + } else + { + e.Top = e.Curr; + e.Bot = e.Next->Curr; + } + SetDx(e); + e.PolyTyp = Pt; +} +//------------------------------------------------------------------------------ + +TEdge* RemoveEdge(TEdge* e) +{ + //removes e from double_linked_list (but without removing from memory) + e->Prev->Next = e->Next; + e->Next->Prev = e->Prev; + TEdge* result = e->Next; + e->Prev = 0; //flag as removed (see ClipperBase.Clear) + return result; +} +//------------------------------------------------------------------------------ + +inline void ReverseHorizontal(TEdge &e) +{ + //swap horizontal edges' Top and Bottom x's so they follow the natural + //progression of the bounds - ie so their xbots will align with the + //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] + cInt tmp = e.Top.X; + e.Top.X = e.Bot.X; + e.Bot.X = tmp; +#ifdef use_xyz + tmp = e.Top.Z; + e.Top.Z = e.Bot.Z; + e.Bot.Z = tmp; +#endif +} +//------------------------------------------------------------------------------ + +void SwapPoints(IntPoint &pt1, IntPoint &pt2) +{ + IntPoint tmp = pt1; + pt1 = pt2; + pt2 = tmp; +} +//------------------------------------------------------------------------------ + +bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, + IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) +{ + //precondition: segments are Collinear. + if (Abs(pt1a.X - pt1b.X) > Abs(pt1a.Y - pt1b.Y)) + { + if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); + if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); + if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; + return pt1.X < pt2.X; + } else + { + if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); + if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); + if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; + return pt1.Y > pt2.Y; + } +} +//------------------------------------------------------------------------------ + +bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) +{ + OutPt *p = btmPt1->Prev; + while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Prev; + double dx1p = std::fabs(GetDx(btmPt1->Pt, p->Pt)); + p = btmPt1->Next; + while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Next; + double dx1n = std::fabs(GetDx(btmPt1->Pt, p->Pt)); + + p = btmPt2->Prev; + while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Prev; + double dx2p = std::fabs(GetDx(btmPt2->Pt, p->Pt)); + p = btmPt2->Next; + while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Next; + double dx2n = std::fabs(GetDx(btmPt2->Pt, p->Pt)); + return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); +} +//------------------------------------------------------------------------------ + +OutPt* GetBottomPt(OutPt *pp) +{ + OutPt* dups = 0; + OutPt* p = pp->Next; + while (p != pp) + { + if (p->Pt.Y > pp->Pt.Y) + { + pp = p; + dups = 0; + } + else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X) + { + if (p->Pt.X < pp->Pt.X) + { + dups = 0; + pp = p; + } else + { + if (p->Next != pp && p->Prev != pp) dups = p; + } + } + p = p->Next; + } + if (dups) + { + //there appears to be at least 2 vertices at BottomPt so ... + while (dups != p) + { + if (!FirstIsBottomPt(p, dups)) pp = dups; + dups = dups->Next; + while (dups->Pt != pp->Pt) dups = dups->Next; + } + } + return pp; +} +//------------------------------------------------------------------------------ + +bool FindSegment(OutPt* &pp, bool UseFullInt64Range, + IntPoint &pt1, IntPoint &pt2) +{ + //OutPt1 & OutPt2 => the overlap segment (if the function returns true) + if (!pp) return false; + OutPt* pp2 = pp; + IntPoint pt1a = pt1, pt2a = pt2; + do + { + if (SlopesEqual(pt1a, pt2a, pp->Pt, pp->Prev->Pt, UseFullInt64Range) && + SlopesEqual(pt1a, pt2a, pp->Pt, UseFullInt64Range) && + GetOverlapSegment(pt1a, pt2a, pp->Pt, pp->Prev->Pt, pt1, pt2)) + return true; + pp = pp->Next; + } + while (pp != pp2); + return false; +} +//------------------------------------------------------------------------------ + +bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1, + const IntPoint pt2, const IntPoint pt3) +{ + if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) + return false; + else if (pt1.X != pt3.X) + return (pt2.X > pt1.X) == (pt2.X < pt3.X); + else + return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y); +} +//------------------------------------------------------------------------------ + +OutPt* InsertPolyPtBetween(OutPt* p1, OutPt* p2, const IntPoint Pt) +{ + if (p1 == p2) throw "JoinError"; + OutPt* result = new OutPt; + result->Pt = Pt; + if (p2 == p1->Next) + { + p1->Next = result; + p2->Prev = result; + result->Next = p2; + result->Prev = p1; + } else + { + p2->Next = result; + p1->Prev = result; + result->Next = p1; + result->Prev = p2; + } + return result; +} +//------------------------------------------------------------------------------ + +bool HorzSegmentsOverlap(const IntPoint& pt1a, const IntPoint& pt1b, + const IntPoint& pt2a, const IntPoint& pt2b) +{ + //precondition: both segments are horizontal + if ((pt1a.X > pt2a.X) == (pt1a.X < pt2b.X)) return true; + else if ((pt1b.X > pt2a.X) == (pt1b.X < pt2b.X)) return true; + else if ((pt2a.X > pt1a.X) == (pt2a.X < pt1b.X)) return true; + else if ((pt2b.X > pt1a.X) == (pt2b.X < pt1b.X)) return true; + else if ((pt1a.X == pt2a.X) && (pt1b.X == pt2b.X)) return true; + else if ((pt1a.X == pt2b.X) && (pt1b.X == pt2a.X)) return true; + else return false; +} + + +//------------------------------------------------------------------------------ +// ClipperBase class methods ... +//------------------------------------------------------------------------------ + +ClipperBase::ClipperBase() //constructor +{ + m_MinimaList = 0; + m_CurrentLM = 0; + m_UseFullRange = false; +} +//------------------------------------------------------------------------------ + +ClipperBase::~ClipperBase() //destructor +{ + Clear(); +} +//------------------------------------------------------------------------------ + +void RangeTest(const IntPoint& Pt, bool& useFullRange) +{ + if (useFullRange) + { + if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange) + throw "Coordinate outside allowed range"; + } + else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange) + { + useFullRange = true; + RangeTest(Pt, useFullRange); + } +} +//------------------------------------------------------------------------------ + +TEdge* FindNextLocMin(TEdge* E) +{ + for (;;) + { + while (E->Bot != E->Prev->Bot || E->Curr == E->Top) E = E->Next; + if (!IsHorizontal(*E) && !IsHorizontal(*E->Prev)) break; + while (IsHorizontal(*E->Prev)) E = E->Prev; + TEdge* E2 = E; + while (IsHorizontal(*E)) E = E->Next; + if (E->Top.Y == E->Prev->Bot.Y) continue; //ie just an intermediate horz. + if (E2->Prev->Bot.X < E->Bot.X) E = E2; + break; + } + return E; +} +//------------------------------------------------------------------------------ + +TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise) +{ + TEdge *EStart = E, *Result = E; + TEdge *Horz = 0; + cInt StartX; + if (IsHorizontal(*E)) + { + //it's possible for adjacent overlapping horz edges to start heading left + //before finishing right, so ... + if (IsClockwise) StartX = E->Prev->Bot.X; + else StartX = E->Next->Bot.X; + if (E->Bot.X != StartX) ReverseHorizontal(*E); + } + + if (Result->OutIdx != Skip) + { + if (IsClockwise) + { + while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) + Result = Result->Next; + if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) + { + //nb: at the top of a bound, horizontals are added to the bound + //only when the preceding edge attaches to the horizontal's left vertex + //unless a Skip edge is encountered when that becomes the top divide + Horz = Result; + while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev; + if (Horz->Prev->Top.X == Result->Next->Top.X) + { + if (!IsClockwise) Result = Horz->Prev; + } + else if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev; + } + while (E != Result) + { + E->NextInLML = E->Next; + if (IsHorizontal(*E) && E != EStart && + E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); + E = E->Next; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) + ReverseHorizontal(*E); + Result = Result->Next; //move to the edge just beyond current bound + } else + { + while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) + Result = Result->Prev; + if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) + { + Horz = Result; + while (IsHorizontal(*Horz->Next)) Horz = Horz->Next; + if (Horz->Next->Top.X == Result->Prev->Top.X) + { + if (!IsClockwise) Result = Horz->Next; + } + else if (Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next; + } + + while (E != Result) + { + E->NextInLML = E->Prev; + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) + ReverseHorizontal(*E); + E = E->Prev; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) + ReverseHorizontal(*E); + Result = Result->Prev; //move to the edge just beyond current bound + } + } + + if (Result->OutIdx == Skip) + { + //if edges still remain in the current bound beyond the skip edge then + //create another LocMin and call ProcessBound once more + E = Result; + if (IsClockwise) + { + while (E->Top.Y == E->Next->Bot.Y) E = E->Next; + //don't include top horizontals when parsing a bound a second time, + //they will be contained in the opposite bound ... + while (E != Result && IsHorizontal(*E)) E = E->Prev; + } else + { + while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev; + while (E != Result && IsHorizontal(*E)) E = E->Next; + } + if (E == Result) + { + if (IsClockwise) Result = E->Next; + else Result = E->Prev; + } else + { + //there are more edges in the bound beyond result starting with E + if (IsClockwise) + E = Result->Next; + else + E = Result->Prev; + LocalMinima* locMin = new LocalMinima; + locMin->Next = 0; + locMin->Y = E->Bot.Y; + locMin->LeftBound = 0; + locMin->RightBound = E; + locMin->RightBound->WindDelta = 0; + Result = ProcessBound(locMin->RightBound, IsClockwise); + InsertLocalMinima(locMin); + } + } + return Result; +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) +{ +#ifdef use_lines + if (!Closed && PolyTyp == ptClip) + throw clipperException("AddPath: Open paths must be subject."); +#else + if (!Closed) + throw clipperException("AddPath: Open paths have been disabled."); +#endif + + int highI = (int)pg.size() -1; + if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI; + while (highI > 0 && (pg[highI] == pg[highI -1])) --highI; + if ((Closed && highI < 2) || (!Closed && highI < 1)) return false; + + //create a new edge array ... + TEdge *edges = new TEdge [highI +1]; + + bool IsFlat = true; + //1. Basic (first) edge initialization ... + try + { + edges[1].Curr = pg[1]; + RangeTest(pg[0], m_UseFullRange); + RangeTest(pg[highI], m_UseFullRange); + InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]); + InitEdge(&edges[highI], &edges[0], &edges[highI-1], pg[highI]); + for (int i = highI - 1; i >= 1; --i) + { + RangeTest(pg[i], m_UseFullRange); + InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]); + } + } + catch(...) + { + delete [] edges; + throw; //range test fails + } + TEdge *eStart = &edges[0]; + + //2. Remove duplicate vertices, and (when closed) collinear edges ... + TEdge *E = eStart, *eLoopStop = eStart; + for (;;) + { + if ((E->Curr == E->Next->Curr)) + { + if (E == E->Next) break; + if (E == eStart) eStart = E->Next; + E = RemoveEdge(E); + eLoopStop = E; + continue; + } + if (E->Prev == E->Next) + break; //only two vertices + else if (Closed && + SlopesEqual(E->Prev->Curr, E->Curr, E->Next->Curr, m_UseFullRange) && + (!m_PreserveCollinear || + !Pt2IsBetweenPt1AndPt3(E->Prev->Curr, E->Curr, E->Next->Curr))) + { + //Collinear edges are allowed for open paths but in closed paths + //the default is to merge adjacent collinear edges into a single edge. + //However, if the PreserveCollinear property is enabled, only overlapping + //collinear edges (ie spikes) will be removed from closed paths. + if (E == eStart) eStart = E->Next; + E = RemoveEdge(E); + E = E->Prev; + eLoopStop = E; + continue; + } + E = E->Next; + if (E == eLoopStop) break; + } + + if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next))) + { + delete [] edges; + return false; + } + + if (!Closed) + { + m_HasOpenPaths = true; + eStart->Prev->OutIdx = Skip; + } + + //3. Do second stage of edge initialization ... + E = eStart; + do + { + InitEdge2(*E, PolyTyp); + E = E->Next; + if (IsFlat && E->Curr.Y != eStart->Curr.Y) IsFlat = false; + } + while (E != eStart); + + //4. Finally, add edge bounds to LocalMinima list ... + + //Totally flat paths must be handled differently when adding them + //to LocalMinima list to avoid endless loops etc ... + if (IsFlat) + { + if (Closed) + { + delete [] edges; + return false; + } + E->Prev->OutIdx = Skip; + if (E->Prev->Bot.X < E->Prev->Top.X) ReverseHorizontal(*E->Prev); + LocalMinima* locMin = new LocalMinima(); + locMin->Next = 0; + locMin->Y = E->Bot.Y; + locMin->LeftBound = 0; + locMin->RightBound = E; + locMin->RightBound->Side = esRight; + locMin->RightBound->WindDelta = 0; + while (E->Next->OutIdx != Skip) + { + E->NextInLML = E->Next; + if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); + E = E->Next; + } + InsertLocalMinima(locMin); + m_edges.push_back(edges); + return true; + } + + m_edges.push_back(edges); + bool clockwise; + TEdge* EMin = 0; + for (;;) + { + E = FindNextLocMin(E); + if (E == EMin) break; + else if (!EMin) EMin = E; + + //E and E.Prev now share a local minima (left aligned if horizontal). + //Compare their slopes to find which starts which bound ... + LocalMinima* locMin = new LocalMinima; + locMin->Next = 0; + locMin->Y = E->Bot.Y; + if (E->Dx < E->Prev->Dx) + { + locMin->LeftBound = E->Prev; + locMin->RightBound = E; + clockwise = false; //Q.nextInLML = Q.prev + } else + { + locMin->LeftBound = E; + locMin->RightBound = E->Prev; + clockwise = true; //Q.nextInLML = Q.next + } + locMin->LeftBound->Side = esLeft; + locMin->RightBound->Side = esRight; + + if (!Closed) locMin->LeftBound->WindDelta = 0; + else if (locMin->LeftBound->Next == locMin->RightBound) + locMin->LeftBound->WindDelta = -1; + else locMin->LeftBound->WindDelta = 1; + locMin->RightBound->WindDelta = -locMin->LeftBound->WindDelta; + + E = ProcessBound(locMin->LeftBound, clockwise); + TEdge* E2 = ProcessBound(locMin->RightBound, !clockwise); + + if (locMin->LeftBound->OutIdx == Skip) + locMin->LeftBound = 0; + else if (locMin->RightBound->OutIdx == Skip) + locMin->RightBound = 0; + InsertLocalMinima(locMin); + if (!clockwise) E = E2; + } + return true; +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) +{ + bool result = false; + for (Paths::size_type i = 0; i < ppg.size(); ++i) + if (AddPath(ppg[i], PolyTyp, Closed)) result = true; + return result; +} +//------------------------------------------------------------------------------ + +void ClipperBase::InsertLocalMinima(LocalMinima *newLm) +{ + if( ! m_MinimaList ) + { + m_MinimaList = newLm; + } + else if( newLm->Y >= m_MinimaList->Y ) + { + newLm->Next = m_MinimaList; + m_MinimaList = newLm; + } else + { + LocalMinima* tmpLm = m_MinimaList; + while( tmpLm->Next && ( newLm->Y < tmpLm->Next->Y ) ) + tmpLm = tmpLm->Next; + newLm->Next = tmpLm->Next; + tmpLm->Next = newLm; + } +} +//------------------------------------------------------------------------------ + +void ClipperBase::Clear() +{ + DisposeLocalMinimaList(); + for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) + { + //for each edge array in turn, find the first used edge and + //check for and remove any hiddenPts in each edge in the array. + TEdge* edges = m_edges[i]; + delete [] edges; + } + m_edges.clear(); + m_UseFullRange = false; + m_HasOpenPaths = false; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Reset() +{ + m_CurrentLM = m_MinimaList; + if( !m_CurrentLM ) return; //ie nothing to process + + //reset all edges ... + LocalMinima* lm = m_MinimaList; + while( lm ) + { + TEdge* e = lm->LeftBound; + if (e) + { + e->Curr = e->Bot; + e->Side = esLeft; + e->OutIdx = Unassigned; + } + + e = lm->RightBound; + if (e) + { + e->Curr = e->Bot; + e->Side = esRight; + e->OutIdx = Unassigned; + } + lm = lm->Next; + } +} +//------------------------------------------------------------------------------ + +void ClipperBase::DisposeLocalMinimaList() +{ + while( m_MinimaList ) + { + LocalMinima* tmpLm = m_MinimaList->Next; + delete m_MinimaList; + m_MinimaList = tmpLm; + } + m_CurrentLM = 0; +} +//------------------------------------------------------------------------------ + +void ClipperBase::PopLocalMinima() +{ + if( ! m_CurrentLM ) return; + m_CurrentLM = m_CurrentLM->Next; +} +//------------------------------------------------------------------------------ + +IntRect ClipperBase::GetBounds() +{ + IntRect result; + LocalMinima* lm = m_MinimaList; + if (!lm) + { + result.left = result.top = result.right = result.bottom = 0; + return result; + } + result.left = lm->LeftBound->Bot.X; + result.top = lm->LeftBound->Bot.Y; + result.right = lm->LeftBound->Bot.X; + result.bottom = lm->LeftBound->Bot.Y; + while (lm) + { + if (lm->LeftBound->Bot.Y > result.bottom) + result.bottom = lm->LeftBound->Bot.Y; + TEdge* e = lm->LeftBound; + for (;;) { + TEdge* bottomE = e; + while (e->NextInLML) + { + if (e->Bot.X < result.left) result.left = e->Bot.X; + if (e->Bot.X > result.right) result.right = e->Bot.X; + e = e->NextInLML; + } + if (e->Bot.X < result.left) result.left = e->Bot.X; + if (e->Bot.X > result.right) result.right = e->Bot.X; + if (e->Top.X < result.left) result.left = e->Top.X; + if (e->Top.X > result.right) result.right = e->Top.X; + if (e->Top.Y < result.top) result.top = e->Top.Y; + + if (bottomE == lm->LeftBound) e = lm->RightBound; + else break; + } + lm = lm->Next; + } + return result; +} + +//------------------------------------------------------------------------------ +// TClipper methods ... +//------------------------------------------------------------------------------ + +Clipper::Clipper(int initOptions) : ClipperBase() //constructor +{ + m_ActiveEdges = 0; + m_SortedEdges = 0; + m_ExecuteLocked = false; + m_UseFullRange = false; + m_ReverseOutput = ((initOptions & ioReverseSolution) != 0); + m_StrictSimple = ((initOptions & ioStrictlySimple) != 0); + m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0); + m_HasOpenPaths = false; +#ifdef use_xyz + m_ZFill = 0; +#endif +} +//------------------------------------------------------------------------------ + +Clipper::~Clipper() //destructor +{ + Clear(); + m_Scanbeam.clear(); +} +//------------------------------------------------------------------------------ + +#ifdef use_xyz +void Clipper::ZFillFunction(TZFillCallback zFillFunc) +{ + m_ZFill = zFillFunc; +} +//------------------------------------------------------------------------------ +#endif + +void Clipper::Reset() +{ + ClipperBase::Reset(); + m_Scanbeam.clear(); + m_ActiveEdges = 0; + m_SortedEdges = 0; + LocalMinima* lm = m_MinimaList; + while (lm) + { + InsertScanbeam(lm->Y); + lm = lm->Next; + } +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, Paths &solution, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + if (m_HasOpenPaths) + throw clipperException("Error: PolyTree struct is need for open path clipping."); + m_ExecuteLocked = true; + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = false; + bool succeeded = ExecuteInternal(); + if (succeeded) BuildResult(solution); + DisposeAllOutRecs(); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, PolyTree& polytree, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + m_ExecuteLocked = true; + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = true; + bool succeeded = ExecuteInternal(); + if (succeeded) BuildResult2(polytree); + DisposeAllOutRecs(); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +void Clipper::FixHoleLinkage(OutRec &outrec) +{ + //skip OutRecs that (a) contain outermost polygons or + //(b) already have the correct owner/child linkage ... + if (!outrec.FirstLeft || + (outrec.IsHole != outrec.FirstLeft->IsHole && + outrec.FirstLeft->Pts)) return; + + OutRec* orfl = outrec.FirstLeft; + while (orfl && ((orfl->IsHole == outrec.IsHole) || !orfl->Pts)) + orfl = orfl->FirstLeft; + outrec.FirstLeft = orfl; +} +//------------------------------------------------------------------------------ + +bool Clipper::ExecuteInternal() +{ + bool succeeded = true; + try { + Reset(); + if (!m_CurrentLM) return false; + cInt botY = PopScanbeam(); + do { + InsertLocalMinimaIntoAEL(botY); + ClearGhostJoins(); + ProcessHorizontals(false); + if (m_Scanbeam.empty()) break; + cInt topY = PopScanbeam(); + succeeded = ProcessIntersections(botY, topY); + if (!succeeded) break; + ProcessEdgesAtTopOfScanbeam(topY); + botY = topY; + } while (!m_Scanbeam.empty() || m_CurrentLM); + } + catch(...) + { + succeeded = false; + } + + if (succeeded) + { + //fix orientations ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *outRec = m_PolyOuts[i]; + if (!outRec->Pts || outRec->IsOpen) continue; + if ((outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0)) + ReversePolyPtLinks(outRec->Pts); + } + + if (!m_Joins.empty()) JoinCommonEdges(); + + //unfortunately FixupOutPolygon() must be done after JoinCommonEdges() + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *outRec = m_PolyOuts[i]; + if (outRec->Pts && !outRec->IsOpen) + FixupOutPolygon(*outRec); + } + + if (m_StrictSimple) DoSimplePolygons(); + } + + ClearJoins(); + ClearGhostJoins(); + return succeeded; +} +//------------------------------------------------------------------------------ + +void Clipper::InsertScanbeam(const cInt Y) +{ + m_Scanbeam.insert(Y); +} +//------------------------------------------------------------------------------ + +cInt Clipper::PopScanbeam() +{ + cInt Y = *m_Scanbeam.begin(); + m_Scanbeam.erase(m_Scanbeam.begin()); + return Y; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeAllOutRecs(){ + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + DisposeOutRec(i); + m_PolyOuts.clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeOutRec(PolyOutList::size_type index) +{ + OutRec *outRec = m_PolyOuts[index]; + if (outRec->Pts) DisposeOutPts(outRec->Pts); + delete outRec; + m_PolyOuts[index] = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::SetWindingCount(TEdge &edge) +{ + TEdge *e = edge.PrevInAEL; + //find the edge of the same polytype that immediately preceeds 'edge' in AEL + while (e && ((e->PolyTyp != edge.PolyTyp) || (e->WindDelta == 0))) e = e->PrevInAEL; + if (!e) + { + edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); + edge.WindCnt2 = 0; + e = m_ActiveEdges; //ie get ready to calc WindCnt2 + } + else if (edge.WindDelta == 0 && m_ClipType != ctUnion) + { + edge.WindCnt = 1; + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; //ie get ready to calc WindCnt2 + } + else if (IsEvenOddFillType(edge)) + { + //EvenOdd filling ... + if (edge.WindDelta == 0) + { + //are we inside a subj polygon ... + bool Inside = true; + TEdge *e2 = e->PrevInAEL; + while (e2) + { + if (e2->PolyTyp == e->PolyTyp && e2->WindDelta != 0) + Inside = !Inside; + e2 = e2->PrevInAEL; + } + edge.WindCnt = (Inside ? 0 : 1); + } + else + { + edge.WindCnt = edge.WindDelta; + } + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; //ie get ready to calc WindCnt2 + } + else + { + //nonZero, Positive or Negative filling ... + if (e->WindCnt * e->WindDelta < 0) + { + //prev edge is 'decreasing' WindCount (WC) toward zero + //so we're outside the previous polygon ... + if (Abs(e->WindCnt) > 1) + { + //outside prev poly but still inside another. + //when reversing direction of prev poly use the same WC + if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; + //otherwise continue to 'decrease' WC ... + else edge.WindCnt = e->WindCnt + edge.WindDelta; + } + else + //now outside all polys of same polytype so set own WC ... + edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); + } else + { + //prev edge is 'increasing' WindCount (WC) away from zero + //so we're inside the previous polygon ... + if (edge.WindDelta == 0) + edge.WindCnt = (e->WindCnt < 0 ? e->WindCnt - 1 : e->WindCnt + 1); + //if wind direction is reversing prev then use same WC + else if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; + //otherwise add to WC ... + else edge.WindCnt = e->WindCnt + edge.WindDelta; + } + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; //ie get ready to calc WindCnt2 + } + + //update WindCnt2 ... + if (IsEvenOddAltFillType(edge)) + { + //EvenOdd filling ... + while (e != &edge) + { + if (e->WindDelta != 0) + edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0); + e = e->NextInAEL; + } + } else + { + //nonZero, Positive or Negative filling ... + while ( e != &edge ) + { + edge.WindCnt2 += e->WindDelta; + e = e->NextInAEL; + } + } +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddFillType(const TEdge& edge) const +{ + if (edge.PolyTyp == ptSubject) + return m_SubjFillType == pftEvenOdd; else + return m_ClipFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const +{ + if (edge.PolyTyp == ptSubject) + return m_ClipFillType == pftEvenOdd; else + return m_SubjFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsContributing(const TEdge& edge) const +{ + PolyFillType pft, pft2; + if (edge.PolyTyp == ptSubject) + { + pft = m_SubjFillType; + pft2 = m_ClipFillType; + } else + { + pft = m_ClipFillType; + pft2 = m_SubjFillType; + } + + switch(pft) + { + case pftEvenOdd: + //return false if a subj line has been flagged as inside a subj polygon + if (edge.WindDelta == 0 && edge.WindCnt != 1) return false; + break; + case pftNonZero: + if (Abs(edge.WindCnt) != 1) return false; + break; + case pftPositive: + if (edge.WindCnt != 1) return false; + break; + default: //pftNegative + if (edge.WindCnt != -1) return false; + } + + switch(m_ClipType) + { + case ctIntersection: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 != 0); + case pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + break; + case ctUnion: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + break; + case ctDifference: + if (edge.PolyTyp == ptSubject) + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + else + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 != 0); + case pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + break; + case ctXor: + if (edge.WindDelta == 0) //XOr always contributing unless open + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + else + return true; + break; + default: + return true; + } +} +//------------------------------------------------------------------------------ + +OutPt* Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) +{ + OutPt* result; + TEdge *e, *prevE; + if (IsHorizontal(*e2) || ( e1->Dx > e2->Dx )) + { + result = AddOutPt(e1, Pt); + e2->OutIdx = e1->OutIdx; + e1->Side = esLeft; + e2->Side = esRight; + e = e1; + if (e->PrevInAEL == e2) + prevE = e2->PrevInAEL; + else + prevE = e->PrevInAEL; + } else + { + result = AddOutPt(e2, Pt); + e1->OutIdx = e2->OutIdx; + e1->Side = esRight; + e2->Side = esLeft; + e = e2; + if (e->PrevInAEL == e1) + prevE = e1->PrevInAEL; + else + prevE = e->PrevInAEL; + } + + if (prevE && prevE->OutIdx >= 0 && + (TopX(*prevE, Pt.Y) == TopX(*e, Pt.Y)) && + SlopesEqual(*e, *prevE, m_UseFullRange) && + (e->WindDelta != 0) && (prevE->WindDelta != 0)) + { + OutPt* outPt = AddOutPt(prevE, Pt); + AddJoin(result, outPt, e->Top); + } + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) +{ + AddOutPt( e1, Pt ); + if (e2->WindDelta == 0) AddOutPt(e2, Pt); + if( e1->OutIdx == e2->OutIdx ) + { + e1->OutIdx = Unassigned; + e2->OutIdx = Unassigned; + } + else if (e1->OutIdx < e2->OutIdx) + AppendPolygon(e1, e2); + else + AppendPolygon(e2, e1); +} +//------------------------------------------------------------------------------ + +void Clipper::AddEdgeToSEL(TEdge *edge) +{ + //SEL pointers in PEdge are reused to build a list of horizontal edges. + //However, we don't need to worry about order with horizontal edge processing. + if( !m_SortedEdges ) + { + m_SortedEdges = edge; + edge->PrevInSEL = 0; + edge->NextInSEL = 0; + } + else + { + edge->NextInSEL = m_SortedEdges; + edge->PrevInSEL = 0; + m_SortedEdges->PrevInSEL = edge; + m_SortedEdges = edge; + } +} +//------------------------------------------------------------------------------ + +void Clipper::CopyAELToSEL() +{ + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + while ( e ) + { + e->PrevInSEL = e->PrevInAEL; + e->NextInSEL = e->NextInAEL; + e = e->NextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AddJoin(OutPt *op1, OutPt *op2, const IntPoint OffPt) +{ + Join* j = new Join; + j->OutPt1 = op1; + j->OutPt2 = op2; + j->OffPt = OffPt; + m_Joins.push_back(j); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearJoins() +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + delete m_Joins[i]; + m_Joins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearGhostJoins() +{ + for (JoinList::size_type i = 0; i < m_GhostJoins.size(); i++) + delete m_GhostJoins[i]; + m_GhostJoins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt) +{ + Join* j = new Join; + j->OutPt1 = op; + j->OutPt2 = 0; + j->OffPt = OffPt; + m_GhostJoins.push_back(j); +} +//------------------------------------------------------------------------------ + +void Clipper::InsertLocalMinimaIntoAEL(const cInt botY) +{ + while( m_CurrentLM && ( m_CurrentLM->Y == botY ) ) + { + TEdge* lb = m_CurrentLM->LeftBound; + TEdge* rb = m_CurrentLM->RightBound; + PopLocalMinima(); + OutPt *Op1 = 0; + if (!lb) + { + //nb: don't insert LB into either AEL or SEL + InsertEdgeIntoAEL(rb, 0); + SetWindingCount(*rb); + if (IsContributing(*rb)) + Op1 = AddOutPt(rb, rb->Bot); + } + else if (!rb) + { + InsertEdgeIntoAEL(lb, 0); + SetWindingCount(*lb); + if (IsContributing(*lb)) + Op1 = AddOutPt(lb, lb->Bot); + InsertScanbeam(lb->Top.Y); + } + else + { + InsertEdgeIntoAEL(lb, 0); + InsertEdgeIntoAEL(rb, lb); + SetWindingCount( *lb ); + rb->WindCnt = lb->WindCnt; + rb->WindCnt2 = lb->WindCnt2; + if (IsContributing(*lb)) + Op1 = AddLocalMinPoly(lb, rb, lb->Bot); + InsertScanbeam(lb->Top.Y); + } + + if (rb) + { + if(IsHorizontal(*rb)) AddEdgeToSEL(rb); + else InsertScanbeam( rb->Top.Y ); + } + + if (!lb || !rb) continue; + + //if any output polygons share an edge, they'll need joining later ... + if (Op1 && IsHorizontal(*rb) && + m_GhostJoins.size() > 0 && (rb->WindDelta != 0)) + { + for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i) + { + Join* jr = m_GhostJoins[i]; + //if the horizontal Rb and a 'ghost' horizontal overlap, then convert + //the 'ghost' join to a real join ready for later ... + if (HorzSegmentsOverlap(jr->OutPt1->Pt, jr->OffPt, rb->Bot, rb->Top)) + AddJoin(jr->OutPt1, Op1, jr->OffPt); + } + } + + if (lb->OutIdx >= 0 && lb->PrevInAEL && + lb->PrevInAEL->Curr.X == lb->Bot.X && + lb->PrevInAEL->OutIdx >= 0 && + SlopesEqual(*lb->PrevInAEL, *lb, m_UseFullRange) && + (lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0)) + { + OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot); + AddJoin(Op1, Op2, lb->Top); + } + + if(lb->NextInAEL != rb) + { + + if (rb->OutIdx >= 0 && rb->PrevInAEL->OutIdx >= 0 && + SlopesEqual(*rb->PrevInAEL, *rb, m_UseFullRange) && + (rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0)) + { + OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot); + AddJoin(Op1, Op2, rb->Top); + } + + TEdge* e = lb->NextInAEL; + if (e) + { + while( e != rb ) + { + //nb: For calculating winding counts etc, IntersectEdges() assumes + //that param1 will be to the Right of param2 ABOVE the intersection ... + IntersectEdges(rb , e , lb->Curr); //order important here + e = e->NextInAEL; + } + } + } + + } +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromAEL(TEdge *e) +{ + TEdge* AelPrev = e->PrevInAEL; + TEdge* AelNext = e->NextInAEL; + if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted + if( AelPrev ) AelPrev->NextInAEL = AelNext; + else m_ActiveEdges = AelNext; + if( AelNext ) AelNext->PrevInAEL = AelPrev; + e->NextInAEL = 0; + e->PrevInAEL = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromSEL(TEdge *e) +{ + TEdge* SelPrev = e->PrevInSEL; + TEdge* SelNext = e->NextInSEL; + if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted + if( SelPrev ) SelPrev->NextInSEL = SelNext; + else m_SortedEdges = SelNext; + if( SelNext ) SelNext->PrevInSEL = SelPrev; + e->NextInSEL = 0; + e->PrevInSEL = 0; +} +//------------------------------------------------------------------------------ + +#ifdef use_xyz + +void Clipper::SetZ(IntPoint& pt, TEdge& e) +{ + pt.Z = 0; + if (m_ZFill) + { + //put the 'preferred' point as first parameter ... + if (e.OutIdx < 0) + (*m_ZFill)(e.Bot, e.Top, pt); //outside a path so presume entering + else + (*m_ZFill)(e.Top, e.Bot, pt); //inside a path so presume exiting + } +} +//------------------------------------------------------------------------------ +#endif + +void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, + const IntPoint &Pt, bool protect) +{ + //e1 will be to the Left of e2 BELOW the intersection. Therefore e1 is before + //e2 in AEL except when e1 is being inserted at the intersection point ... + bool e1stops = !protect && !e1->NextInLML && + e1->Top.X == Pt.X && e1->Top.Y == Pt.Y; + bool e2stops = !protect && !e2->NextInLML && + e2->Top.X == Pt.X && e2->Top.Y == Pt.Y; + bool e1Contributing = ( e1->OutIdx >= 0 ); + bool e2Contributing = ( e2->OutIdx >= 0 ); + +#ifdef use_lines + //if either edge is on an OPEN path ... + if (e1->WindDelta == 0 || e2->WindDelta == 0) + { + //ignore subject-subject open path intersections UNLESS they + //are both open paths, AND they are both 'contributing maximas' ... + if (e1->WindDelta == 0 && e2->WindDelta == 0) + { + if ((e1stops || e2stops) && e1Contributing && e2Contributing) + AddLocalMaxPoly(e1, e2, Pt); + } + + //if intersecting a subj line with a subj poly ... + else if (e1->PolyTyp == e2->PolyTyp && + e1->WindDelta != e2->WindDelta && m_ClipType == ctUnion) + { + if (e1->WindDelta == 0) + { + if (e2Contributing) + { + AddOutPt(e1, Pt); + if (e1Contributing) e1->OutIdx = Unassigned; + } + } + else + { + if (e1Contributing) + { + AddOutPt(e2, Pt); + if (e2Contributing) e2->OutIdx = Unassigned; + } + } + } + else if (e1->PolyTyp != e2->PolyTyp) + { + //toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... + if ((e1->WindDelta == 0) && abs(e2->WindCnt) == 1 && + (m_ClipType != ctUnion || e2->WindCnt2 == 0)) + { + AddOutPt(e1, Pt); + if (e1Contributing) e1->OutIdx = Unassigned; + } + else if ((e2->WindDelta == 0) && (abs(e1->WindCnt) == 1) && + (m_ClipType != ctUnion || e1->WindCnt2 == 0)) + { + AddOutPt(e2, Pt); + if (e2Contributing) e2->OutIdx = Unassigned; + } + } + + if (e1stops) + if (e1->OutIdx < 0) DeleteFromAEL(e1); + else throw clipperException("Error intersecting polylines"); + if (e2stops) + if (e2->OutIdx < 0) DeleteFromAEL(e2); + else throw clipperException("Error intersecting polylines"); + return; + } +#endif + + //update winding counts... + //assumes that e1 will be to the Right of e2 ABOVE the intersection + if ( e1->PolyTyp == e2->PolyTyp ) + { + if ( IsEvenOddFillType( *e1) ) + { + int oldE1WindCnt = e1->WindCnt; + e1->WindCnt = e2->WindCnt; + e2->WindCnt = oldE1WindCnt; + } else + { + if (e1->WindCnt + e2->WindDelta == 0 ) e1->WindCnt = -e1->WindCnt; + else e1->WindCnt += e2->WindDelta; + if ( e2->WindCnt - e1->WindDelta == 0 ) e2->WindCnt = -e2->WindCnt; + else e2->WindCnt -= e1->WindDelta; + } + } else + { + if (!IsEvenOddFillType(*e2)) e1->WindCnt2 += e2->WindDelta; + else e1->WindCnt2 = ( e1->WindCnt2 == 0 ) ? 1 : 0; + if (!IsEvenOddFillType(*e1)) e2->WindCnt2 -= e1->WindDelta; + else e2->WindCnt2 = ( e2->WindCnt2 == 0 ) ? 1 : 0; + } + + PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; + if (e1->PolyTyp == ptSubject) + { + e1FillType = m_SubjFillType; + e1FillType2 = m_ClipFillType; + } else + { + e1FillType = m_ClipFillType; + e1FillType2 = m_SubjFillType; + } + if (e2->PolyTyp == ptSubject) + { + e2FillType = m_SubjFillType; + e2FillType2 = m_ClipFillType; + } else + { + e2FillType = m_ClipFillType; + e2FillType2 = m_SubjFillType; + } + + cInt e1Wc, e2Wc; + switch (e1FillType) + { + case pftPositive: e1Wc = e1->WindCnt; break; + case pftNegative: e1Wc = -e1->WindCnt; break; + default: e1Wc = Abs(e1->WindCnt); + } + switch(e2FillType) + { + case pftPositive: e2Wc = e2->WindCnt; break; + case pftNegative: e2Wc = -e2->WindCnt; break; + default: e2Wc = Abs(e2->WindCnt); + } + + if ( e1Contributing && e2Contributing ) + { + if ( e1stops || e2stops || + (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || + (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor) ) + AddLocalMaxPoly(e1, e2, Pt); + else + { + AddOutPt(e1, Pt); + AddOutPt(e2, Pt); + SwapSides( *e1 , *e2 ); + SwapPolyIndexes( *e1 , *e2 ); + } + } + else if ( e1Contributing ) + { + if (e2Wc == 0 || e2Wc == 1) + { + AddOutPt(e1, Pt); + SwapSides(*e1, *e2); + SwapPolyIndexes(*e1, *e2); + } + } + else if ( e2Contributing ) + { + if (e1Wc == 0 || e1Wc == 1) + { + AddOutPt(e2, Pt); + SwapSides(*e1, *e2); + SwapPolyIndexes(*e1, *e2); + } + } + else if ( (e1Wc == 0 || e1Wc == 1) && + (e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops ) + { + //neither edge is currently contributing ... + + cInt e1Wc2, e2Wc2; + switch (e1FillType2) + { + case pftPositive: e1Wc2 = e1->WindCnt2; break; + case pftNegative : e1Wc2 = -e1->WindCnt2; break; + default: e1Wc2 = Abs(e1->WindCnt2); + } + switch (e2FillType2) + { + case pftPositive: e2Wc2 = e2->WindCnt2; break; + case pftNegative: e2Wc2 = -e2->WindCnt2; break; + default: e2Wc2 = Abs(e2->WindCnt2); + } + + if (e1->PolyTyp != e2->PolyTyp) + AddLocalMinPoly(e1, e2, Pt); + else if (e1Wc == 1 && e2Wc == 1) + switch( m_ClipType ) { + case ctIntersection: + if (e1Wc2 > 0 && e2Wc2 > 0) + AddLocalMinPoly(e1, e2, Pt); + break; + case ctUnion: + if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) + AddLocalMinPoly(e1, e2, Pt); + break; + case ctDifference: + if (((e1->PolyTyp == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || + ((e1->PolyTyp == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) + AddLocalMinPoly(e1, e2, Pt); + break; + case ctXor: + AddLocalMinPoly(e1, e2, Pt); + } + else + SwapSides( *e1, *e2 ); + } + + if( (e1stops != e2stops) && + ( (e1stops && (e1->OutIdx >= 0)) || (e2stops && (e2->OutIdx >= 0)) ) ) + { + SwapSides( *e1, *e2 ); + SwapPolyIndexes( *e1, *e2 ); + } + + //finally, delete any non-contributing maxima edges ... + if( e1stops ) DeleteFromAEL( e1 ); + if( e2stops ) DeleteFromAEL( e2 ); +} +//------------------------------------------------------------------------------ + +void Clipper::SetHoleState(TEdge *e, OutRec *outrec) +{ + bool IsHole = false; + TEdge *e2 = e->PrevInAEL; + while (e2) + { + if (e2->OutIdx >= 0 && e2->WindDelta != 0) + { + IsHole = !IsHole; + if (! outrec->FirstLeft) + outrec->FirstLeft = m_PolyOuts[e2->OutIdx]; + } + e2 = e2->PrevInAEL; + } + if (IsHole) outrec->IsHole = true; +} +//------------------------------------------------------------------------------ + +OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) +{ + //work out which polygon fragment has the correct hole state ... + if (!outRec1->BottomPt) + outRec1->BottomPt = GetBottomPt(outRec1->Pts); + if (!outRec2->BottomPt) + outRec2->BottomPt = GetBottomPt(outRec2->Pts); + OutPt *OutPt1 = outRec1->BottomPt; + OutPt *OutPt2 = outRec2->BottomPt; + if (OutPt1->Pt.Y > OutPt2->Pt.Y) return outRec1; + else if (OutPt1->Pt.Y < OutPt2->Pt.Y) return outRec2; + else if (OutPt1->Pt.X < OutPt2->Pt.X) return outRec1; + else if (OutPt1->Pt.X > OutPt2->Pt.X) return outRec2; + else if (OutPt1->Next == OutPt1) return outRec2; + else if (OutPt2->Next == OutPt2) return outRec1; + else if (FirstIsBottomPt(OutPt1, OutPt2)) return outRec1; + else return outRec2; +} +//------------------------------------------------------------------------------ + +bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2) +{ + do + { + outRec1 = outRec1->FirstLeft; + if (outRec1 == outRec2) return true; + } while (outRec1); + return false; +} +//------------------------------------------------------------------------------ + +OutRec* Clipper::GetOutRec(int Idx) +{ + OutRec* outrec = m_PolyOuts[Idx]; + while (outrec != m_PolyOuts[outrec->Idx]) + outrec = m_PolyOuts[outrec->Idx]; + return outrec; +} +//------------------------------------------------------------------------------ + +void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) +{ + //get the start and ends of both output polygons ... + OutRec *outRec1 = m_PolyOuts[e1->OutIdx]; + OutRec *outRec2 = m_PolyOuts[e2->OutIdx]; + + OutRec *holeStateRec; + if (Param1RightOfParam2(outRec1, outRec2)) + holeStateRec = outRec2; + else if (Param1RightOfParam2(outRec2, outRec1)) + holeStateRec = outRec1; + else + holeStateRec = GetLowermostRec(outRec1, outRec2); + + //get the start and ends of both output polygons and + //join e2 poly onto e1 poly and delete pointers to e2 ... + + OutPt* p1_lft = outRec1->Pts; + OutPt* p1_rt = p1_lft->Prev; + OutPt* p2_lft = outRec2->Pts; + OutPt* p2_rt = p2_lft->Prev; + + EdgeSide Side; + //join e2 poly onto e1 poly and delete pointers to e2 ... + if( e1->Side == esLeft ) + { + if( e2->Side == esLeft ) + { + //z y x a b c + ReversePolyPtLinks(p2_lft); + p2_lft->Next = p1_lft; + p1_lft->Prev = p2_lft; + p1_rt->Next = p2_rt; + p2_rt->Prev = p1_rt; + outRec1->Pts = p2_rt; + } else + { + //x y z a b c + p2_rt->Next = p1_lft; + p1_lft->Prev = p2_rt; + p2_lft->Prev = p1_rt; + p1_rt->Next = p2_lft; + outRec1->Pts = p2_lft; + } + Side = esLeft; + } else + { + if( e2->Side == esRight ) + { + //a b c z y x + ReversePolyPtLinks(p2_lft); + p1_rt->Next = p2_rt; + p2_rt->Prev = p1_rt; + p2_lft->Next = p1_lft; + p1_lft->Prev = p2_lft; + } else + { + //a b c x y z + p1_rt->Next = p2_lft; + p2_lft->Prev = p1_rt; + p1_lft->Prev = p2_rt; + p2_rt->Next = p1_lft; + } + Side = esRight; + } + + outRec1->BottomPt = 0; + if (holeStateRec == outRec2) + { + if (outRec2->FirstLeft != outRec1) + outRec1->FirstLeft = outRec2->FirstLeft; + outRec1->IsHole = outRec2->IsHole; + } + outRec2->Pts = 0; + outRec2->BottomPt = 0; + outRec2->FirstLeft = outRec1; + + int OKIdx = e1->OutIdx; + int ObsoleteIdx = e2->OutIdx; + + e1->OutIdx = Unassigned; //nb: safe because we only get here via AddLocalMaxPoly + e2->OutIdx = Unassigned; + + TEdge* e = m_ActiveEdges; + while( e ) + { + if( e->OutIdx == ObsoleteIdx ) + { + e->OutIdx = OKIdx; + e->Side = Side; + break; + } + e = e->NextInAEL; + } + + outRec2->Idx = outRec1->Idx; +} +//------------------------------------------------------------------------------ + +OutRec* Clipper::CreateOutRec() +{ + OutRec* result = new OutRec; + result->IsHole = false; + result->IsOpen = false; + result->FirstLeft = 0; + result->Pts = 0; + result->BottomPt = 0; + result->PolyNd = 0; + m_PolyOuts.push_back(result); + result->Idx = (int)m_PolyOuts.size()-1; + return result; +} +//------------------------------------------------------------------------------ + +OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt) +{ + bool ToFront = (e->Side == esLeft); + if( e->OutIdx < 0 ) + { + OutRec *outRec = CreateOutRec(); + outRec->IsOpen = (e->WindDelta == 0); + OutPt* newOp = new OutPt; + outRec->Pts = newOp; + newOp->Idx = outRec->Idx; + newOp->Pt = pt; + newOp->Next = newOp; + newOp->Prev = newOp; + if (!outRec->IsOpen) + SetHoleState(e, outRec); +#ifdef use_xyz + if (pt == e->Bot) newOp->Pt = e->Bot; + else if (pt == e->Top) newOp->Pt = e->Top; + else SetZ(newOp->Pt, *e); +#endif + e->OutIdx = outRec->Idx; //nb: do this after SetZ ! + return newOp; + } else + { + OutRec *outRec = m_PolyOuts[e->OutIdx]; + //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most' + OutPt* op = outRec->Pts; + + if (ToFront && (pt == op->Pt)) return op; + else if (!ToFront && (pt == op->Prev->Pt)) return op->Prev; + + OutPt* newOp = new OutPt; + newOp->Idx = outRec->Idx; + newOp->Pt = pt; + newOp->Next = op; + newOp->Prev = op->Prev; + newOp->Prev->Next = newOp; + op->Prev = newOp; + if (ToFront) outRec->Pts = newOp; +#ifdef use_xyz + if (pt == e->Bot) newOp->Pt = e->Bot; + else if (pt == e->Top) newOp->Pt = e->Top; + else SetZ(newOp->Pt, *e); +#endif + return newOp; + } +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessHorizontals(bool IsTopOfScanbeam) +{ + TEdge* horzEdge = m_SortedEdges; + while(horzEdge) + { + DeleteFromSEL(horzEdge); + ProcessHorizontal(horzEdge, IsTopOfScanbeam); + horzEdge = m_SortedEdges; + } +} +//------------------------------------------------------------------------------ + +inline bool IsMinima(TEdge *e) +{ + return e && (e->Prev->NextInLML != e) && (e->Next->NextInLML != e); +} +//------------------------------------------------------------------------------ + +inline bool IsMaxima(TEdge *e, const cInt Y) +{ + return e && e->Top.Y == Y && !e->NextInLML; +} +//------------------------------------------------------------------------------ + +inline bool IsIntermediate(TEdge *e, const cInt Y) +{ + return e->Top.Y == Y && e->NextInLML; +} +//------------------------------------------------------------------------------ + +TEdge *GetMaximaPair(TEdge *e) +{ + TEdge* result = 0; + if ((e->Next->Top == e->Top) && !e->Next->NextInLML) + result = e->Next; + else if ((e->Prev->Top == e->Top) && !e->Prev->NextInLML) + result = e->Prev; + + if (result && (result->OutIdx == Skip || + //result is false if both NextInAEL & PrevInAEL are nil & not horizontal ... + (result->NextInAEL == result->PrevInAEL && !IsHorizontal(*result)))) + return 0; + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2) +{ + //check that one or other edge hasn't already been removed from AEL ... + if (Edge1->NextInAEL == Edge1->PrevInAEL || + Edge2->NextInAEL == Edge2->PrevInAEL) return; + + if( Edge1->NextInAEL == Edge2 ) + { + TEdge* Next = Edge2->NextInAEL; + if( Next ) Next->PrevInAEL = Edge1; + TEdge* Prev = Edge1->PrevInAEL; + if( Prev ) Prev->NextInAEL = Edge2; + Edge2->PrevInAEL = Prev; + Edge2->NextInAEL = Edge1; + Edge1->PrevInAEL = Edge2; + Edge1->NextInAEL = Next; + } + else if( Edge2->NextInAEL == Edge1 ) + { + TEdge* Next = Edge1->NextInAEL; + if( Next ) Next->PrevInAEL = Edge2; + TEdge* Prev = Edge2->PrevInAEL; + if( Prev ) Prev->NextInAEL = Edge1; + Edge1->PrevInAEL = Prev; + Edge1->NextInAEL = Edge2; + Edge2->PrevInAEL = Edge1; + Edge2->NextInAEL = Next; + } + else + { + TEdge* Next = Edge1->NextInAEL; + TEdge* Prev = Edge1->PrevInAEL; + Edge1->NextInAEL = Edge2->NextInAEL; + if( Edge1->NextInAEL ) Edge1->NextInAEL->PrevInAEL = Edge1; + Edge1->PrevInAEL = Edge2->PrevInAEL; + if( Edge1->PrevInAEL ) Edge1->PrevInAEL->NextInAEL = Edge1; + Edge2->NextInAEL = Next; + if( Edge2->NextInAEL ) Edge2->NextInAEL->PrevInAEL = Edge2; + Edge2->PrevInAEL = Prev; + if( Edge2->PrevInAEL ) Edge2->PrevInAEL->NextInAEL = Edge2; + } + + if( !Edge1->PrevInAEL ) m_ActiveEdges = Edge1; + else if( !Edge2->PrevInAEL ) m_ActiveEdges = Edge2; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInSEL(TEdge *Edge1, TEdge *Edge2) +{ + if( !( Edge1->NextInSEL ) && !( Edge1->PrevInSEL ) ) return; + if( !( Edge2->NextInSEL ) && !( Edge2->PrevInSEL ) ) return; + + if( Edge1->NextInSEL == Edge2 ) + { + TEdge* Next = Edge2->NextInSEL; + if( Next ) Next->PrevInSEL = Edge1; + TEdge* Prev = Edge1->PrevInSEL; + if( Prev ) Prev->NextInSEL = Edge2; + Edge2->PrevInSEL = Prev; + Edge2->NextInSEL = Edge1; + Edge1->PrevInSEL = Edge2; + Edge1->NextInSEL = Next; + } + else if( Edge2->NextInSEL == Edge1 ) + { + TEdge* Next = Edge1->NextInSEL; + if( Next ) Next->PrevInSEL = Edge2; + TEdge* Prev = Edge2->PrevInSEL; + if( Prev ) Prev->NextInSEL = Edge1; + Edge1->PrevInSEL = Prev; + Edge1->NextInSEL = Edge2; + Edge2->PrevInSEL = Edge1; + Edge2->NextInSEL = Next; + } + else + { + TEdge* Next = Edge1->NextInSEL; + TEdge* Prev = Edge1->PrevInSEL; + Edge1->NextInSEL = Edge2->NextInSEL; + if( Edge1->NextInSEL ) Edge1->NextInSEL->PrevInSEL = Edge1; + Edge1->PrevInSEL = Edge2->PrevInSEL; + if( Edge1->PrevInSEL ) Edge1->PrevInSEL->NextInSEL = Edge1; + Edge2->NextInSEL = Next; + if( Edge2->NextInSEL ) Edge2->NextInSEL->PrevInSEL = Edge2; + Edge2->PrevInSEL = Prev; + if( Edge2->PrevInSEL ) Edge2->PrevInSEL->NextInSEL = Edge2; + } + + if( !Edge1->PrevInSEL ) m_SortedEdges = Edge1; + else if( !Edge2->PrevInSEL ) m_SortedEdges = Edge2; +} +//------------------------------------------------------------------------------ + +TEdge* GetNextInAEL(TEdge *e, Direction dir) +{ + return dir == dLeftToRight ? e->NextInAEL : e->PrevInAEL; +} +//------------------------------------------------------------------------------ + +void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right) +{ + if (HorzEdge.Bot.X < HorzEdge.Top.X) + { + Left = HorzEdge.Bot.X; + Right = HorzEdge.Top.X; + Dir = dLeftToRight; + } else + { + Left = HorzEdge.Top.X; + Right = HorzEdge.Bot.X; + Dir = dRightToLeft; + } +} +//------------------------------------------------------------------------ + +void Clipper::PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam) +{ + //get the last Op for this horizontal edge + //the point may be anywhere along the horizontal ... + OutPt* outPt = m_PolyOuts[horzEdge->OutIdx]->Pts; + if (horzEdge->Side != esLeft) outPt = outPt->Prev; + + //First, match up overlapping horizontal edges (eg when one polygon's + //intermediate horz edge overlaps an intermediate horz edge of another, or + //when one polygon sits on top of another) ... + //for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i) + //{ + // Join* j = m_GhostJoins[i]; + // if (HorzSegmentsOverlap(j->OutPt1->Pt, j->OffPt, horzEdge->Bot, horzEdge->Top)) + // AddJoin(j->OutPt1, outPt, j->OffPt); + //} + + //Also, since horizontal edges at the top of one SB are often removed from + //the AEL before we process the horizontal edges at the bottom of the next, + //we need to create 'ghost' Join records of 'contrubuting' horizontals that + //we can compare with horizontals at the bottom of the next SB. + if (isTopOfScanbeam) + { + if (outPt->Pt == horzEdge->Top) + AddGhostJoin(outPt, horzEdge->Bot); + else + AddGhostJoin(outPt, horzEdge->Top); + } +} +//------------------------------------------------------------------------------ + +/******************************************************************************* +* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or * +* Bottom of a scanbeam) are processed as if layered. The order in which HEs * +* are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] * +* (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), * +* and with other non-horizontal edges [*]. Once these intersections are * +* processed, intermediate HEs then 'promote' the Edge above (NextInLML) into * +* the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. * +*******************************************************************************/ + +void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam) +{ + Direction dir; + cInt horzLeft, horzRight; + + GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); + + TEdge* eLastHorz = horzEdge, *eMaxPair = 0; + while (eLastHorz->NextInLML && IsHorizontal(*eLastHorz->NextInLML)) + eLastHorz = eLastHorz->NextInLML; + if (!eLastHorz->NextInLML) + eMaxPair = GetMaximaPair(eLastHorz); + + for (;;) + { + bool IsLastHorz = (horzEdge == eLastHorz); + TEdge* e = GetNextInAEL(horzEdge, dir); + while(e) + { + //Break if we've got to the end of an intermediate horizontal edge ... + //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal. + if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML && + e->Dx < horzEdge->NextInLML->Dx) break; + + TEdge* eNext = GetNextInAEL(e, dir); //saves eNext for later + + if ((dir == dLeftToRight && e->Curr.X <= horzRight) || + (dir == dRightToLeft && e->Curr.X >= horzLeft)) + { + if (horzEdge->OutIdx >= 0 && horzEdge->WindDelta != 0) + PrepareHorzJoins(horzEdge, isTopOfScanbeam); + //so far we're still in range of the horizontal Edge but make sure + //we're at the last of consec. horizontals when matching with eMaxPair + if(e == eMaxPair && IsLastHorz) + { + if (dir == dLeftToRight) + IntersectEdges(horzEdge, e, e->Top); + else + IntersectEdges(e, horzEdge, e->Top); + if (eMaxPair->OutIdx >= 0) throw clipperException("ProcessHorizontal error"); + return; + } + else if(dir == dLeftToRight) + { + IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); + IntersectEdges(horzEdge, e, Pt, true); + } + else + { + IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); + IntersectEdges( e, horzEdge, Pt, true); + } + SwapPositionsInAEL( horzEdge, e ); + } + else if( (dir == dLeftToRight && e->Curr.X >= horzRight) || + (dir == dRightToLeft && e->Curr.X <= horzLeft) ) break; + e = eNext; + } //end while + + if (horzEdge->OutIdx >= 0 && horzEdge->WindDelta != 0) + PrepareHorzJoins(horzEdge, isTopOfScanbeam); + + if (horzEdge->NextInLML && IsHorizontal(*horzEdge->NextInLML)) + { + UpdateEdgeIntoAEL(horzEdge); + if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot); + GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); + } else + break; + } //end for (;;) + + if(horzEdge->NextInLML) + { + if(horzEdge->OutIdx >= 0) + { + OutPt* op1 = AddOutPt( horzEdge, horzEdge->Top); + UpdateEdgeIntoAEL(horzEdge); + if (horzEdge->WindDelta == 0) return; + //nb: HorzEdge is no longer horizontal here + TEdge* ePrev = horzEdge->PrevInAEL; + TEdge* eNext = horzEdge->NextInAEL; + if (ePrev && ePrev->Curr.X == horzEdge->Bot.X && + ePrev->Curr.Y == horzEdge->Bot.Y && ePrev->WindDelta != 0 && + (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && + SlopesEqual(*horzEdge, *ePrev, m_UseFullRange))) + { + OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot); + AddJoin(op1, op2, horzEdge->Top); + } + else if (eNext && eNext->Curr.X == horzEdge->Bot.X && + eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 && + eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && + SlopesEqual(*horzEdge, *eNext, m_UseFullRange)) + { + OutPt* op2 = AddOutPt(eNext, horzEdge->Bot); + AddJoin(op1, op2, horzEdge->Top); + } + } + else + UpdateEdgeIntoAEL(horzEdge); + } + else if (eMaxPair) + { + if (eMaxPair->OutIdx >= 0) + { + if (dir == dLeftToRight) + IntersectEdges(horzEdge, eMaxPair, horzEdge->Top); + else + IntersectEdges(eMaxPair, horzEdge, horzEdge->Top); + if (eMaxPair->OutIdx >= 0) + throw clipperException("ProcessHorizontal error"); + } else + { + DeleteFromAEL(horzEdge); + DeleteFromAEL(eMaxPair); + } + } else + { + if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Top); + DeleteFromAEL(horzEdge); + } +} +//------------------------------------------------------------------------------ + +void Clipper::UpdateEdgeIntoAEL(TEdge *&e) +{ + if( !e->NextInLML ) throw + clipperException("UpdateEdgeIntoAEL: invalid call"); + + e->NextInLML->OutIdx = e->OutIdx; + TEdge* AelPrev = e->PrevInAEL; + TEdge* AelNext = e->NextInAEL; + if (AelPrev) AelPrev->NextInAEL = e->NextInLML; + else m_ActiveEdges = e->NextInLML; + if (AelNext) AelNext->PrevInAEL = e->NextInLML; + e->NextInLML->Side = e->Side; + e->NextInLML->WindDelta = e->WindDelta; + e->NextInLML->WindCnt = e->WindCnt; + e->NextInLML->WindCnt2 = e->WindCnt2; + e = e->NextInLML; + e->Curr = e->Bot; + e->PrevInAEL = AelPrev; + e->NextInAEL = AelNext; + if (!IsHorizontal(*e)) InsertScanbeam(e->Top.Y); +} +//------------------------------------------------------------------------------ + +bool Clipper::ProcessIntersections(const cInt botY, const cInt topY) +{ + if( !m_ActiveEdges ) return true; + try { + BuildIntersectList(botY, topY); + size_t IlSize = m_IntersectList.size(); + if (IlSize == 0) return true; + if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList(); + else return false; + } + catch(...) + { + m_SortedEdges = 0; + DisposeIntersectNodes(); + throw clipperException("ProcessIntersections error"); + } + m_SortedEdges = 0; + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeIntersectNodes() +{ + for (size_t i = 0; i < m_IntersectList.size(); ++i ) + delete m_IntersectList[i]; + m_IntersectList.clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::BuildIntersectList(const cInt botY, const cInt topY) +{ + if ( !m_ActiveEdges ) return; + + //prepare for sorting ... + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + while( e ) + { + e->PrevInSEL = e->PrevInAEL; + e->NextInSEL = e->NextInAEL; + e->Curr.X = TopX( *e, topY ); + e = e->NextInAEL; + } + + //bubblesort ... + bool isModified; + do + { + isModified = false; + e = m_SortedEdges; + while( e->NextInSEL ) + { + TEdge *eNext = e->NextInSEL; + IntPoint Pt; + if(e->Curr.X > eNext->Curr.X) + { + if (!IntersectPoint(*e, *eNext, Pt, m_UseFullRange) && e->Curr.X > eNext->Curr.X +1) + throw clipperException("Intersection error"); + if (Pt.Y > botY) + { + Pt.Y = botY; + if (std::fabs(e->Dx) > std::fabs(eNext->Dx)) + Pt.X = TopX(*eNext, botY); else + Pt.X = TopX(*e, botY); + } + + IntersectNode * newNode = new IntersectNode; + newNode->Edge1 = e; + newNode->Edge2 = eNext; + newNode->Pt = Pt; + m_IntersectList.push_back(newNode); + + SwapPositionsInSEL(e, eNext); + isModified = true; + } + else + e = eNext; + } + if( e->PrevInSEL ) e->PrevInSEL->NextInSEL = 0; + else break; + } + while ( isModified ); + m_SortedEdges = 0; //important +} +//------------------------------------------------------------------------------ + + +void Clipper::ProcessIntersectList() +{ + for (size_t i = 0; i < m_IntersectList.size(); ++i) + { + IntersectNode* iNode = m_IntersectList[i]; + { + IntersectEdges( iNode->Edge1, iNode->Edge2, iNode->Pt, true); + SwapPositionsInAEL( iNode->Edge1 , iNode->Edge2 ); + } + delete iNode; + } + m_IntersectList.clear(); +} +//------------------------------------------------------------------------------ + +bool IntersectListSort(IntersectNode* node1, IntersectNode* node2) +{ + return node2->Pt.Y < node1->Pt.Y; +} +//------------------------------------------------------------------------------ + +inline bool EdgesAdjacent(const IntersectNode &inode) +{ + return (inode.Edge1->NextInSEL == inode.Edge2) || + (inode.Edge1->PrevInSEL == inode.Edge2); +} +//------------------------------------------------------------------------------ + +bool Clipper::FixupIntersectionOrder() +{ + //pre-condition: intersections are sorted Bottom-most first. + //Now it's crucial that intersections are made only between adjacent edges, + //so to ensure this the order of intersections may need adjusting ... + CopyAELToSEL(); + std::sort(m_IntersectList.begin(), m_IntersectList.end(), IntersectListSort); + size_t cnt = m_IntersectList.size(); + for (size_t i = 0; i < cnt; ++i) + { + if (!EdgesAdjacent(*m_IntersectList[i])) + { + size_t j = i + 1; + while (j < cnt && !EdgesAdjacent(*m_IntersectList[j])) j++; + if (j == cnt) return false; + std::swap(m_IntersectList[i], m_IntersectList[j]); + } + SwapPositionsInSEL(m_IntersectList[i]->Edge1, m_IntersectList[i]->Edge2); + } + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::DoMaxima(TEdge *e) +{ + TEdge* eMaxPair = GetMaximaPair(e); + if (!eMaxPair) + { + if (e->OutIdx >= 0) + AddOutPt(e, e->Top); + DeleteFromAEL(e); + return; + } + + TEdge* eNext = e->NextInAEL; + while(eNext && eNext != eMaxPair) + { + IntersectEdges(e, eNext, e->Top, true); + SwapPositionsInAEL(e, eNext); + eNext = e->NextInAEL; + } + + if(e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned) + { + DeleteFromAEL(e); + DeleteFromAEL(eMaxPair); + } + else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 ) + { + IntersectEdges( e, eMaxPair, e->Top); + } +#ifdef use_lines + else if (e->WindDelta == 0) + { + if (e->OutIdx >= 0) + { + AddOutPt(e, e->Top); + e->OutIdx = Unassigned; + } + DeleteFromAEL(e); + + if (eMaxPair->OutIdx >= 0) + { + AddOutPt(eMaxPair, e->Top); + eMaxPair->OutIdx = Unassigned; + } + DeleteFromAEL(eMaxPair); + } +#endif + else throw clipperException("DoMaxima error"); +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) +{ + TEdge* e = m_ActiveEdges; + while( e ) + { + //1. process maxima, treating them as if they're 'bent' horizontal edges, + // but exclude maxima with horizontal edges. nb: e can't be a horizontal. + bool IsMaximaEdge = IsMaxima(e, topY); + + if(IsMaximaEdge) + { + TEdge* eMaxPair = GetMaximaPair(e); + IsMaximaEdge = (!eMaxPair || !IsHorizontal(*eMaxPair)); + } + + if(IsMaximaEdge) + { + TEdge* ePrev = e->PrevInAEL; + DoMaxima(e); + if( !ePrev ) e = m_ActiveEdges; + else e = ePrev->NextInAEL; + } + else + { + //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ... + if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML)) + { + UpdateEdgeIntoAEL(e); + if (e->OutIdx >= 0) + AddOutPt(e, e->Bot); + AddEdgeToSEL(e); + } + else + { + e->Curr.X = TopX( *e, topY ); + e->Curr.Y = topY; + } + + if (m_StrictSimple) + { + TEdge* ePrev = e->PrevInAEL; + if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) && + (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0)) + { + OutPt* op = AddOutPt(ePrev, e->Curr); + OutPt* op2 = AddOutPt(e, e->Curr); + AddJoin(op, op2, e->Curr); //StrictlySimple (type-3) join + } + } + + e = e->NextInAEL; + } + } + + //3. Process horizontals at the Top of the scanbeam ... + ProcessHorizontals(true); + + //4. Promote intermediate vertices ... + e = m_ActiveEdges; + while(e) + { + if(IsIntermediate(e, topY)) + { + OutPt* op = 0; + if( e->OutIdx >= 0 ) + op = AddOutPt(e, e->Top); + UpdateEdgeIntoAEL(e); + + //if output polygons share an edge, they'll need joining later ... + TEdge* ePrev = e->PrevInAEL; + TEdge* eNext = e->NextInAEL; + if (ePrev && ePrev->Curr.X == e->Bot.X && + ePrev->Curr.Y == e->Bot.Y && op && + ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && + SlopesEqual(*e, *ePrev, m_UseFullRange) && + (e->WindDelta != 0) && (ePrev->WindDelta != 0)) + { + OutPt* op2 = AddOutPt(ePrev, e->Bot); + AddJoin(op, op2, e->Top); + } + else if (eNext && eNext->Curr.X == e->Bot.X && + eNext->Curr.Y == e->Bot.Y && op && + eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && + SlopesEqual(*e, *eNext, m_UseFullRange) && + (e->WindDelta != 0) && (eNext->WindDelta != 0)) + { + OutPt* op2 = AddOutPt(eNext, e->Bot); + AddJoin(op, op2, e->Top); + } + } + e = e->NextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::FixupOutPolygon(OutRec &outrec) +{ + //FixupOutPolygon() - removes duplicate points and simplifies consecutive + //parallel edges by removing the middle vertex. + OutPt *lastOK = 0; + outrec.BottomPt = 0; + OutPt *pp = outrec.Pts; + + for (;;) + { + if (pp->Prev == pp || pp->Prev == pp->Next ) + { + DisposeOutPts(pp); + outrec.Pts = 0; + return; + } + + //test for duplicate points and collinear edges ... + if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) || + (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) && + (!m_PreserveCollinear || + !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt)))) + { + lastOK = 0; + OutPt *tmp = pp; + pp->Prev->Next = pp->Next; + pp->Next->Prev = pp->Prev; + pp = pp->Prev; + delete tmp; + } + else if (pp == lastOK) break; + else + { + if (!lastOK) lastOK = pp; + pp = pp->Next; + } + } + outrec.Pts = pp; +} +//------------------------------------------------------------------------------ + +int PointCount(OutPt *Pts) +{ + if (!Pts) return 0; + int result = 0; + OutPt* p = Pts; + do + { + result++; + p = p->Next; + } + while (p != Pts); + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResult(Paths &polys) +{ + polys.reserve(m_PolyOuts.size()); + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + if (!m_PolyOuts[i]->Pts) continue; + Path pg; + OutPt* p = m_PolyOuts[i]->Pts->Prev; + int cnt = PointCount(p); + if (cnt < 2) continue; + pg.reserve(cnt); + for (int i = 0; i < cnt; ++i) + { + pg.push_back(p->Pt); + p = p->Prev; + } + polys.push_back(pg); + } +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResult2(PolyTree& polytree) +{ + polytree.Clear(); + polytree.AllNodes.reserve(m_PolyOuts.size()); + //add each output polygon/contour to polytree ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) + { + OutRec* outRec = m_PolyOuts[i]; + int cnt = PointCount(outRec->Pts); + if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) continue; + FixHoleLinkage(*outRec); + PolyNode* pn = new PolyNode(); + //nb: polytree takes ownership of all the PolyNodes + polytree.AllNodes.push_back(pn); + outRec->PolyNd = pn; + pn->Parent = 0; + pn->Index = 0; + pn->Contour.reserve(cnt); + OutPt *op = outRec->Pts->Prev; + for (int j = 0; j < cnt; j++) + { + pn->Contour.push_back(op->Pt); + op = op->Prev; + } + } + + //fixup PolyNode links etc ... + polytree.Childs.reserve(m_PolyOuts.size()); + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) + { + OutRec* outRec = m_PolyOuts[i]; + if (!outRec->PolyNd) continue; + if (outRec->IsOpen) + { + outRec->PolyNd->m_IsOpen = true; + polytree.AddChild(*outRec->PolyNd); + } + else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd) + outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd); + else + polytree.AddChild(*outRec->PolyNd); + } +} +//------------------------------------------------------------------------------ + +void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) +{ + //just swap the contents (because fIntersectNodes is a single-linked-list) + IntersectNode inode = int1; //gets a copy of Int1 + int1.Edge1 = int2.Edge1; + int1.Edge2 = int2.Edge2; + int1.Pt = int2.Pt; + int2.Edge1 = inode.Edge1; + int2.Edge2 = inode.Edge2; + int2.Pt = inode.Pt; +} +//------------------------------------------------------------------------------ + +inline bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) +{ + if (e2.Curr.X == e1.Curr.X) + { + if (e2.Top.Y > e1.Top.Y) + return e2.Top.X < TopX(e1, e2.Top.Y); + else return e1.Top.X > TopX(e2, e1.Top.Y); + } + else return e2.Curr.X < e1.Curr.X; +} +//------------------------------------------------------------------------------ + +bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2, + cInt& Left, cInt& Right) +{ + if (a1 < a2) + { + if (b1 < b2) {Left = std::max(a1,b1); Right = std::min(a2,b2);} + else {Left = std::max(a1,b2); Right = std::min(a2,b1);} + } + else + { + if (b1 < b2) {Left = std::max(a2,b1); Right = std::min(a1,b2);} + else {Left = std::max(a2,b2); Right = std::min(a1,b1);} + } + return Left < Right; +} +//------------------------------------------------------------------------------ + +inline void UpdateOutPtIdxs(OutRec& outrec) +{ + OutPt* op = outrec.Pts; + do + { + op->Idx = outrec.Idx; + op = op->Prev; + } + while(op != outrec.Pts); +} +//------------------------------------------------------------------------------ + +void Clipper::InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge) +{ + if(!m_ActiveEdges) + { + edge->PrevInAEL = 0; + edge->NextInAEL = 0; + m_ActiveEdges = edge; + } + else if(!startEdge && E2InsertsBeforeE1(*m_ActiveEdges, *edge)) + { + edge->PrevInAEL = 0; + edge->NextInAEL = m_ActiveEdges; + m_ActiveEdges->PrevInAEL = edge; + m_ActiveEdges = edge; + } + else + { + if(!startEdge) startEdge = m_ActiveEdges; + while(startEdge->NextInAEL && + !E2InsertsBeforeE1(*startEdge->NextInAEL , *edge)) + startEdge = startEdge->NextInAEL; + edge->NextInAEL = startEdge->NextInAEL; + if(startEdge->NextInAEL) startEdge->NextInAEL->PrevInAEL = edge; + edge->PrevInAEL = startEdge; + startEdge->NextInAEL = edge; + } +} +//---------------------------------------------------------------------- + +OutPt* DupOutPt(OutPt* outPt, bool InsertAfter) +{ + OutPt* result = new OutPt; + result->Pt = outPt->Pt; + result->Idx = outPt->Idx; + if (InsertAfter) + { + result->Next = outPt->Next; + result->Prev = outPt; + outPt->Next->Prev = result; + outPt->Next = result; + } + else + { + result->Prev = outPt->Prev; + result->Next = outPt; + outPt->Prev->Next = result; + outPt->Prev = result; + } + return result; +} +//------------------------------------------------------------------------------ + +bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, + const IntPoint Pt, bool DiscardLeft) +{ + Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight); + Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight); + if (Dir1 == Dir2) return false; + + //When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we + //want Op1b to be on the Right. (And likewise with Op2 and Op2b.) + //So, to facilitate this while inserting Op1b and Op2b ... + //when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b, + //otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.) + if (Dir1 == dLeftToRight) + { + while (op1->Next->Pt.X <= Pt.X && + op1->Next->Pt.X >= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) + op1 = op1->Next; + if (DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; + op1b = DupOutPt(op1, !DiscardLeft); + if (op1b->Pt != Pt) + { + op1 = op1b; + op1->Pt = Pt; + op1b = DupOutPt(op1, !DiscardLeft); + } + } + else + { + while (op1->Next->Pt.X >= Pt.X && + op1->Next->Pt.X <= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) + op1 = op1->Next; + if (!DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; + op1b = DupOutPt(op1, DiscardLeft); + if (op1b->Pt != Pt) + { + op1 = op1b; + op1->Pt = Pt; + op1b = DupOutPt(op1, DiscardLeft); + } + } + + if (Dir2 == dLeftToRight) + { + while (op2->Next->Pt.X <= Pt.X && + op2->Next->Pt.X >= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) + op2 = op2->Next; + if (DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; + op2b = DupOutPt(op2, !DiscardLeft); + if (op2b->Pt != Pt) + { + op2 = op2b; + op2->Pt = Pt; + op2b = DupOutPt(op2, !DiscardLeft); + }; + } else + { + while (op2->Next->Pt.X >= Pt.X && + op2->Next->Pt.X <= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) + op2 = op2->Next; + if (!DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; + op2b = DupOutPt(op2, DiscardLeft); + if (op2b->Pt != Pt) + { + op2 = op2b; + op2->Pt = Pt; + op2b = DupOutPt(op2, DiscardLeft); + }; + }; + + if ((Dir1 == dLeftToRight) == DiscardLeft) + { + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + } + else + { + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + } + return true; +} +//------------------------------------------------------------------------------ + +bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2) +{ + OutPt *op1 = j->OutPt1, *op1b; + OutPt *op2 = j->OutPt2, *op2b; + + //There are 3 kinds of joins for output polygons ... + //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are a vertices anywhere + //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal). + //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same + //location at the Bottom of the overlapping segment (& Join.OffPt is above). + //3. StrictSimple joins where edges touch but are not collinear and where + //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point. + bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y); + + if (isHorizontal && (j->OffPt == j->OutPt1->Pt) && + (j->OffPt == j->OutPt2->Pt)) + { + //Strictly Simple join ... + op1b = j->OutPt1->Next; + while (op1b != op1 && (op1b->Pt == j->OffPt)) + op1b = op1b->Next; + bool reverse1 = (op1b->Pt.Y > j->OffPt.Y); + op2b = j->OutPt2->Next; + while (op2b != op2 && (op2b->Pt == j->OffPt)) + op2b = op2b->Next; + bool reverse2 = (op2b->Pt.Y > j->OffPt.Y); + if (reverse1 == reverse2) return false; + if (reverse1) + { + op1b = DupOutPt(op1, false); + op2b = DupOutPt(op2, true); + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } else + { + op1b = DupOutPt(op1, true); + op2b = DupOutPt(op2, false); + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } + } + else if (isHorizontal) + { + //treat horizontal joins differently to non-horizontal joins since with + //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt + //may be anywhere along the horizontal edge. + op1b = op1; + while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2) + op1 = op1->Prev; + while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2) + op1b = op1b->Next; + if (op1b->Next == op1 || op1b->Next == op2) return false; //a flat 'polygon' + + op2b = op2; + while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b) + op2 = op2->Prev; + while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1) + op2b = op2b->Next; + if (op2b->Next == op2 || op2b->Next == op1) return false; //a flat 'polygon' + + cInt Left, Right; + //Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges + if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right)) + return false; + + //DiscardLeftSide: when overlapping edges are joined, a spike will created + //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up + //on the discard Side as either may still be needed for other joins ... + IntPoint Pt; + bool DiscardLeftSide; + if (op1->Pt.X >= Left && op1->Pt.X <= Right) + { + Pt = op1->Pt; DiscardLeftSide = (op1->Pt.X > op1b->Pt.X); + } + else if (op2->Pt.X >= Left&& op2->Pt.X <= Right) + { + Pt = op2->Pt; DiscardLeftSide = (op2->Pt.X > op2b->Pt.X); + } + else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right) + { + Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->Pt.X; + } + else + { + Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->Pt.X); + } + j->OutPt1 = op1; j->OutPt2 = op2; + return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide); + } else + { + //nb: For non-horizontal joins ... + // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y + // 2. Jr.OutPt1.Pt > Jr.OffPt.Y + + //make sure the polygons are correctly oriented ... + op1b = op1->Next; + while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Next; + bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) || + !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)); + if (Reverse1) + { + op1b = op1->Prev; + while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Prev; + if ((op1b->Pt.Y > op1->Pt.Y) || + !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) return false; + }; + op2b = op2->Next; + while ((op2b->Pt == op2->Pt) && (op2b != op2))op2b = op2b->Next; + bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) || + !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)); + if (Reverse2) + { + op2b = op2->Prev; + while ((op2b->Pt == op2->Pt) && (op2b != op2)) op2b = op2b->Prev; + if ((op2b->Pt.Y > op2->Pt.Y) || + !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) return false; + } + + if ((op1b == op1) || (op2b == op2) || (op1b == op2b) || + ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false; + + if (Reverse1) + { + op1b = DupOutPt(op1, false); + op2b = DupOutPt(op2, true); + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } else + { + op1b = DupOutPt(op1, true); + op2b = DupOutPt(op2, false); + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } + } +} +//---------------------------------------------------------------------- + +void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) +{ + + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec* outRec = m_PolyOuts[i]; + if (outRec->Pts && outRec->FirstLeft == OldOutRec) + { + if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) + outRec->FirstLeft = NewOutRec; + } + } +} +//---------------------------------------------------------------------- + +void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) +{ + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec* outRec = m_PolyOuts[i]; + if (outRec->FirstLeft == OldOutRec) outRec->FirstLeft = NewOutRec; + } +} +//---------------------------------------------------------------------- + +static OutRec* ParseFirstLeft(OutRec* FirstLeft) +{ + while (FirstLeft && !FirstLeft->Pts) + FirstLeft = FirstLeft->FirstLeft; + return FirstLeft; +} +//------------------------------------------------------------------------------ + +void Clipper::JoinCommonEdges() +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + { + Join* join = m_Joins[i]; + + OutRec *outRec1 = GetOutRec(join->OutPt1->Idx); + OutRec *outRec2 = GetOutRec(join->OutPt2->Idx); + + if (!outRec1->Pts || !outRec2->Pts) continue; + + //get the polygon fragment with the correct hole state (FirstLeft) + //before calling JoinPoints() ... + OutRec *holeStateRec; + if (outRec1 == outRec2) holeStateRec = outRec1; + else if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; + else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; + else holeStateRec = GetLowermostRec(outRec1, outRec2); + + if (!JoinPoints(join, outRec1, outRec2)) continue; + + if (outRec1 == outRec2) + { + //instead of joining two polygons, we've just created a new one by + //splitting one polygon into two. + outRec1->Pts = join->OutPt1; + outRec1->BottomPt = 0; + outRec2 = CreateOutRec(); + outRec2->Pts = join->OutPt2; + + //update all OutRec2.Pts Idx's ... + UpdateOutPtIdxs(*outRec2); + + //We now need to check every OutRec.FirstLeft pointer. If it points + //to OutRec1 it may need to point to OutRec2 instead ... + if (m_UsingPolyTree) + for (PolyOutList::size_type j = 0; j < m_PolyOuts.size() - 1; j++) + { + OutRec* oRec = m_PolyOuts[j]; + if (!oRec->Pts || ParseFirstLeft(oRec->FirstLeft) != outRec1 || + oRec->IsHole == outRec1->IsHole) continue; + if (Poly2ContainsPoly1(oRec->Pts, join->OutPt2)) + oRec->FirstLeft = outRec2; + } + + if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts)) + { + //outRec2 is contained by outRec1 ... + outRec2->IsHole = !outRec1->IsHole; + outRec2->FirstLeft = outRec1; + + //fixup FirstLeft pointers that may need reassigning to OutRec1 + if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); + + if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0)) + ReversePolyPtLinks(outRec2->Pts); + + } else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts)) + { + //outRec1 is contained by outRec2 ... + outRec2->IsHole = outRec1->IsHole; + outRec1->IsHole = !outRec2->IsHole; + outRec2->FirstLeft = outRec1->FirstLeft; + outRec1->FirstLeft = outRec2; + + //fixup FirstLeft pointers that may need reassigning to OutRec1 + if (m_UsingPolyTree) FixupFirstLefts2(outRec1, outRec2); + + if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0)) + ReversePolyPtLinks(outRec1->Pts); + } + else + { + //the 2 polygons are completely separate ... + outRec2->IsHole = outRec1->IsHole; + outRec2->FirstLeft = outRec1->FirstLeft; + + //fixup FirstLeft pointers that may need reassigning to OutRec2 + if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec2); + } + + } else + { + //joined 2 polygons together ... + + outRec2->Pts = 0; + outRec2->BottomPt = 0; + outRec2->Idx = outRec1->Idx; + + outRec1->IsHole = holeStateRec->IsHole; + if (holeStateRec == outRec2) + outRec1->FirstLeft = outRec2->FirstLeft; + outRec2->FirstLeft = outRec1; + + //fixup FirstLeft pointers that may need reassigning to OutRec1 + if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); + } + } +} + +//------------------------------------------------------------------------------ +// ClipperOffset support functions ... +//------------------------------------------------------------------------------ + +DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2) +{ + if(pt2.X == pt1.X && pt2.Y == pt1.Y) + return DoublePoint(0, 0); + + double Dx = (double)(pt2.X - pt1.X); + double dy = (double)(pt2.Y - pt1.Y); + double f = 1 *1.0/ std::sqrt( Dx*Dx + dy*dy ); + Dx *= f; + dy *= f; + return DoublePoint(dy, -Dx); +} + +//------------------------------------------------------------------------------ +// ClipperOffset class +//------------------------------------------------------------------------------ + +ClipperOffset::ClipperOffset(double miterLimit, double arcTolerance) +{ + this->MiterLimit = miterLimit; + this->ArcTolerance = arcTolerance; + m_lowest.X = -1; +} +//------------------------------------------------------------------------------ + +ClipperOffset::~ClipperOffset() +{ + Clear(); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::Clear() +{ + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) + delete m_polyNodes.Childs[i]; + m_polyNodes.Childs.clear(); + m_lowest.X = -1; +} +//------------------------------------------------------------------------------ + +void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType) +{ + int highI = (int)path.size() - 1; + if (highI < 0) return; + PolyNode* newNode = new PolyNode(); + newNode->m_jointype = joinType; + newNode->m_endtype = endType; + + //strip duplicate points from path and also get index to the lowest point ... + if (endType == etClosedLine || endType == etClosedPolygon) + while (highI > 0 && path[0] == path[highI]) highI--; + newNode->Contour.reserve(highI + 1); + newNode->Contour.push_back(path[0]); + int j = 0, k = 0; + for (int i = 1; i <= highI; i++) + if (newNode->Contour[j] != path[i]) + { + j++; + newNode->Contour.push_back(path[i]); + if (path[i].Y > newNode->Contour[k].Y || + (path[i].Y == newNode->Contour[k].Y && + path[i].X < newNode->Contour[k].X)) k = j; + } + if ((endType == etClosedPolygon && j < 2) || + (endType != etClosedPolygon && j < 0)) + { + delete newNode; + return; + } + m_polyNodes.AddChild(*newNode); + + //if this path's lowest pt is lower than all the others then update m_lowest + if (endType != etClosedPolygon) return; + if (m_lowest.X < 0) + m_lowest = IntPoint(0, k); + else + { + IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y]; + if (newNode->Contour[k].Y > ip.Y || + (newNode->Contour[k].Y == ip.Y && + newNode->Contour[k].X < ip.X)) + m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType) +{ + for (Paths::size_type i = 0; i < paths.size(); ++i) + AddPath(paths[i], joinType, endType); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::FixOrientations() +{ + //fixup orientations of all closed paths if the orientation of the + //closed path with the lowermost vertex is wrong ... + if (m_lowest.X >= 0 && + !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour)) + { + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) + { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedPolygon || + (node.m_endtype == etClosedLine && Orientation(node.Contour))) + ReversePath(node.Contour); + } + } else + { + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) + { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedLine && !Orientation(node.Contour)) + ReversePath(node.Contour); + } + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::Execute(Paths& solution, double delta) +{ + solution.clear(); + FixOrientations(); + DoOffset(delta); + + //now clean up 'corners' ... + Clipper clpr; + clpr.AddPaths(m_destPolys, ptSubject, true); + if (delta > 0) + { + clpr.Execute(ctUnion, solution, pftPositive, pftPositive); + } + else + { + IntRect r = clpr.GetBounds(); + Path outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPath(outer, ptSubject, true); + clpr.ReverseSolution(true); + clpr.Execute(ctUnion, solution, pftNegative, pftNegative); + if (solution.size() > 0) solution.erase(solution.begin()); + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::Execute(PolyTree& solution, double delta) +{ + solution.Clear(); + FixOrientations(); + DoOffset(delta); + + //now clean up 'corners' ... + Clipper clpr; + clpr.AddPaths(m_destPolys, ptSubject, true); + if (delta > 0) + { + clpr.Execute(ctUnion, solution, pftPositive, pftPositive); + } + else + { + IntRect r = clpr.GetBounds(); + Path outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPath(outer, ptSubject, true); + clpr.ReverseSolution(true); + clpr.Execute(ctUnion, solution, pftNegative, pftNegative); + //remove the outer PolyNode rectangle ... + if (solution.ChildCount() == 1 && solution.Childs[0]->ChildCount() > 0) + { + PolyNode* outerNode = solution.Childs[0]; + solution.Childs.reserve(outerNode->ChildCount()); + solution.Childs[0] = outerNode->Childs[0]; + for (int i = 1; i < outerNode->ChildCount(); ++i) + solution.AddChild(*outerNode->Childs[i]); + } + else + solution.Clear(); + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoOffset(double delta) +{ + m_destPolys.clear(); + m_delta = delta; + + //if Zero offset, just copy any CLOSED polygons to m_p and return ... + if (NEAR_ZERO(delta)) + { + m_destPolys.reserve(m_polyNodes.ChildCount()); + for (int i = 0; i < m_polyNodes.ChildCount(); i++) + { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedPolygon) + m_destPolys.push_back(node.Contour); + } + return; + } + + //see offset_triginometry3.svg in the documentation folder ... + if (MiterLimit > 2) m_miterLim = 2/(MiterLimit * MiterLimit); + else m_miterLim = 0.5; + + double y; + if (ArcTolerance <= 0.0) y = def_arc_tolerance; + else if (ArcTolerance > std::fabs(delta) * def_arc_tolerance) + y = std::fabs(delta) * def_arc_tolerance; + else y = ArcTolerance; + //see offset_triginometry2.svg in the documentation folder ... + double steps = pi / std::acos(1 - y / std::fabs(delta)); + if (steps > std::fabs(delta) * pi) + steps = std::fabs(delta) * pi; //ie excessive precision check + m_sin = std::sin(two_pi / steps); + m_cos = std::cos(two_pi / steps); + m_StepsPerRad = steps / two_pi; + if (delta < 0.0) m_sin = -m_sin; + + m_destPolys.reserve(m_polyNodes.ChildCount() * 2); + for (int i = 0; i < m_polyNodes.ChildCount(); i++) + { + PolyNode& node = *m_polyNodes.Childs[i]; + m_srcPoly = node.Contour; + + int len = (int)m_srcPoly.size(); + if (len == 0 || (delta <= 0 && (len < 3 || node.m_endtype != etClosedPolygon))) + continue; + + m_destPoly.clear(); + if (len == 1) + { + if (node.m_jointype == jtRound) + { + double X = 1.0, Y = 0.0; + for (cInt j = 1; j <= steps; j++) + { + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + double X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + } + else + { + double X = -1.0, Y = -1.0; + for (int j = 0; j < 4; ++j) + { + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + if (X < 0) X = 1; + else if (Y < 0) Y = 1; + else X = -1; + } + } + m_destPolys.push_back(m_destPoly); + continue; + } + //build m_normals ... + m_normals.clear(); + m_normals.reserve(len); + for (int j = 0; j < len - 1; ++j) + m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); + if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon) + m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); + else + m_normals.push_back(DoublePoint(m_normals[len - 2])); + + if (node.m_endtype == etClosedPolygon) + { + int k = len - 1; + for (int j = 0; j < len; ++j) + OffsetPoint(j, k, node.m_jointype); + m_destPolys.push_back(m_destPoly); + } + else if (node.m_endtype == etClosedLine) + { + int k = len - 1; + for (int j = 0; j < len; ++j) + OffsetPoint(j, k, node.m_jointype); + m_destPolys.push_back(m_destPoly); + m_destPoly.clear(); + //re-build m_normals ... + DoublePoint n = m_normals[len -1]; + for (int j = len - 1; j > 0; j--) + m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + m_normals[0] = DoublePoint(-n.X, -n.Y); + k = 0; + for (int j = len - 1; j >= 0; j--) + OffsetPoint(j, k, node.m_jointype); + m_destPolys.push_back(m_destPoly); + } + else + { + int k = 0; + for (int j = 1; j < len - 1; ++j) + OffsetPoint(j, k, node.m_jointype); + + IntPoint pt1; + if (node.m_endtype == etOpenButt) + { + int j = len - 1; + pt1 = IntPoint((cInt)Round(m_srcPoly[j].X + m_normals[j].X * + delta), (cInt)Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); + m_destPoly.push_back(pt1); + pt1 = IntPoint((cInt)Round(m_srcPoly[j].X - m_normals[j].X * + delta), (cInt)Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); + m_destPoly.push_back(pt1); + } + else + { + int j = len - 1; + k = len - 2; + m_sinA = 0; + m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y); + if (node.m_endtype == etOpenSquare) + DoSquare(j, k); + else + DoRound(j, k); + } + + //re-build m_normals ... + for (int j = len - 1; j > 0; j--) + m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y); + + k = len - 1; + for (int j = k - 1; j > 0; --j) OffsetPoint(j, k, node.m_jointype); + + if (node.m_endtype == etOpenButt) + { + pt1 = IntPoint((cInt)Round(m_srcPoly[0].X - m_normals[0].X * delta), + (cInt)Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); + m_destPoly.push_back(pt1); + pt1 = IntPoint((cInt)Round(m_srcPoly[0].X + m_normals[0].X * delta), + (cInt)Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); + m_destPoly.push_back(pt1); + } + else + { + k = 1; + m_sinA = 0; + if (node.m_endtype == etOpenSquare) + DoSquare(0, 1); + else + DoRound(0, 1); + } + m_destPolys.push_back(m_destPoly); + } + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype) +{ + m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); + if (m_sinA < 0.00005 && m_sinA > -0.00005) return; + else if (m_sinA > 1.0) m_sinA = 1.0; + else if (m_sinA < -1.0) m_sinA = -1.0; + + if (m_sinA * m_delta < 0) + { + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); + m_destPoly.push_back(m_srcPoly[j]); + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); + } + else + switch (jointype) + { + case jtMiter: + { + double r = 1 + (m_normals[j].X * m_normals[k].X + + m_normals[j].Y * m_normals[k].Y); + if (r >= m_miterLim) DoMiter(j, k, r); else DoSquare(j, k); + break; + } + case jtSquare: DoSquare(j, k); break; + case jtRound: DoRound(j, k); break; + } + k = j; +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoSquare(int j, int k) +{ + double dx = std::tan(std::atan2(m_sinA, + m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4); + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx)))); + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx)))); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoMiter(int j, int k, double r) +{ + double q = m_delta / r; + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q), + Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q))); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoRound(int j, int k) +{ + double a = std::atan2(m_sinA, + m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); + int steps = (int)Round(m_StepsPerRad * std::fabs(a)); + + double X = m_normals[k].X, Y = m_normals[k].Y, X2; + for (int i = 0; i < steps; ++i) + { + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + X * m_delta), + Round(m_srcPoly[j].Y + Y * m_delta))); + X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); +} + +//------------------------------------------------------------------------------ +// Miscellaneous public functions +//------------------------------------------------------------------------------ + +void Clipper::DoSimplePolygons() +{ + PolyOutList::size_type i = 0; + while (i < m_PolyOuts.size()) + { + OutRec* outrec = m_PolyOuts[i++]; + OutPt* op = outrec->Pts; + if (!op) continue; + do //for each Pt in Polygon until duplicate found do ... + { + OutPt* op2 = op->Next; + while (op2 != outrec->Pts) + { + if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op) + { + //split the polygon into two ... + OutPt* op3 = op->Prev; + OutPt* op4 = op2->Prev; + op->Prev = op4; + op4->Next = op; + op2->Prev = op3; + op3->Next = op2; + + outrec->Pts = op; + OutRec* outrec2 = CreateOutRec(); + outrec2->Pts = op2; + UpdateOutPtIdxs(*outrec2); + if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts)) + { + //OutRec2 is contained by OutRec1 ... + outrec2->IsHole = !outrec->IsHole; + outrec2->FirstLeft = outrec; + } + else + if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) + { + //OutRec1 is contained by OutRec2 ... + outrec2->IsHole = outrec->IsHole; + outrec->IsHole = !outrec2->IsHole; + outrec2->FirstLeft = outrec->FirstLeft; + outrec->FirstLeft = outrec2; + } else + { + //the 2 polygons are separate ... + outrec2->IsHole = outrec->IsHole; + outrec2->FirstLeft = outrec->FirstLeft; + } + op2 = op; //ie get ready for the Next iteration + } + op2 = op2->Next; + } + op = op->Next; + } + while (op != outrec->Pts); + } +} +//------------------------------------------------------------------------------ + +void ReversePath(Path& p) +{ + std::reverse(p.begin(), p.end()); +} +//------------------------------------------------------------------------------ + +void ReversePaths(Paths& p) +{ + for (Paths::size_type i = 0; i < p.size(); ++i) + ReversePath(p[i]); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType) +{ + Clipper c; + c.StrictlySimple(true); + c.AddPath(in_poly, ptSubject, true); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType) +{ + Clipper c; + c.StrictlySimple(true); + c.AddPaths(in_polys, ptSubject, true); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(Paths &polys, PolyFillType fillType) +{ + SimplifyPolygons(polys, polys, fillType); +} +//------------------------------------------------------------------------------ + +inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2) +{ + double Dx = ((double)pt1.X - pt2.X); + double dy = ((double)pt1.Y - pt2.Y); + return (Dx*Dx + dy*dy); +} +//------------------------------------------------------------------------------ + +double DistanceFromLineSqrd( + const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2) +{ + //see https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line + double A = double(ln1.Y - ln2.Y); + double B = double(ln2.X - ln1.X); + double C = A * ln1.X + B * ln1.Y; + C = A * pt.X + B * pt.Y - C; + return (C * C) / (A * A + B * B); +} +//--------------------------------------------------------------------------- + +bool SlopesNearCollinear(const IntPoint& pt1, + const IntPoint& pt2, const IntPoint& pt3, double distSqrd) +{ + return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; +} +//------------------------------------------------------------------------------ + +bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd) +{ + double Dx = (double)pt1.X - pt2.X; + double dy = (double)pt1.Y - pt2.Y; + return ((Dx * Dx) + (dy * dy) <= distSqrd); +} +//------------------------------------------------------------------------------ + +OutPt* ExcludeOp(OutPt* op) +{ + OutPt* result = op->Prev; + result->Next = op->Next; + op->Next->Prev = result; + result->Idx = 0; + return result; +} +//------------------------------------------------------------------------------ + +void CleanPolygon(const Path& in_poly, Path& out_poly, double distance) +{ + //distance = proximity in units/pixels below which vertices + //will be stripped. Default ~= sqrt(2). + + size_t size = in_poly.size(); + + if (size == 0) + { + out_poly.clear(); + return; + } + + OutPt* outPts = new OutPt[size]; + for (size_t i = 0; i < size; ++i) + { + outPts[i].Pt = in_poly[i]; + outPts[i].Next = &outPts[(i + 1) % size]; + outPts[i].Next->Prev = &outPts[i]; + outPts[i].Idx = 0; + } + + double distSqrd = distance * distance; + OutPt* op = &outPts[0]; + while (op->Idx == 0 && op->Next != op->Prev) + { + if (PointsAreClose(op->Pt, op->Prev->Pt, distSqrd)) + { + op = ExcludeOp(op); + size--; + } + else if (PointsAreClose(op->Prev->Pt, op->Next->Pt, distSqrd)) + { + ExcludeOp(op->Next); + op = ExcludeOp(op); + size -= 2; + } + else if (SlopesNearCollinear(op->Prev->Pt, op->Pt, op->Next->Pt, distSqrd)) + { + op = ExcludeOp(op); + size--; + } + else + { + op->Idx = 1; + op = op->Next; + } + } + + if (size < 3) size = 0; + out_poly.resize(size); + for (size_t i = 0; i < size; ++i) + { + out_poly[i] = op->Pt; + op = op->Next; + } + delete [] outPts; +} +//------------------------------------------------------------------------------ + +void CleanPolygon(Path& poly, double distance) +{ + CleanPolygon(poly, poly, distance); +} +//------------------------------------------------------------------------------ + +void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance) +{ + for (Paths::size_type i = 0; i < in_polys.size(); ++i) + CleanPolygon(in_polys[i], out_polys[i], distance); +} +//------------------------------------------------------------------------------ + +void CleanPolygons(Paths& polys, double distance) +{ + CleanPolygons(polys, polys, distance); +} +//------------------------------------------------------------------------------ + +void Minkowski(const Path& poly, const Path& path, + Paths& solution, bool isSum, bool isClosed) +{ + int delta = (isClosed ? 1 : 0); + size_t polyCnt = poly.size(); + size_t pathCnt = path.size(); + Paths pp; + pp.reserve(pathCnt); + if (isSum) + for (size_t i = 0; i < pathCnt; ++i) + { + Path p; + p.reserve(polyCnt); + for (size_t j = 0; j < poly.size(); ++j) + p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y)); + pp.push_back(p); + } + else + for (size_t i = 0; i < pathCnt; ++i) + { + Path p; + p.reserve(polyCnt); + for (size_t j = 0; j < poly.size(); ++j) + p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y)); + pp.push_back(p); + } + + Paths quads; + quads.reserve((pathCnt + delta) * (polyCnt + 1)); + for (size_t i = 0; i < pathCnt - 1 + delta; ++i) + for (size_t j = 0; j < polyCnt; ++j) + { + Path quad; + quad.reserve(4); + quad.push_back(pp[i % pathCnt][j % polyCnt]); + quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]); + quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); + quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); + if (!Orientation(quad)) ReversePath(quad); + quads.push_back(quad); + } + + Clipper c; + c.AddPaths(quads, ptSubject, true); + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); +} +//------------------------------------------------------------------------------ + +void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed) +{ + Minkowski(pattern, path, solution, true, pathIsClosed); +} +//------------------------------------------------------------------------------ + +void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, + PolyFillType pathFillType, bool pathIsClosed) +{ + Clipper c; + for (size_t i = 0; i < paths.size(); ++i) + { + Paths tmp; + Minkowski(pattern, paths[i], tmp, true, pathIsClosed); + c.AddPaths(tmp, ptSubject, true); + } + if (pathIsClosed) c.AddPaths(paths, ptClip, true); + c.Execute(ctUnion, solution, pathFillType, pathFillType); +} +//------------------------------------------------------------------------------ + +void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution) +{ + Minkowski(poly1, poly2, solution, false, true); +} +//------------------------------------------------------------------------------ + +enum NodeType {ntAny, ntOpen, ntClosed}; + +void AddPolyNodeToPolygons(const PolyNode& polynode, NodeType nodetype, Paths& paths) +{ + bool match = true; + if (nodetype == ntClosed) match = !polynode.IsOpen(); + else if (nodetype == ntOpen) return; + + if (!polynode.Contour.empty() && match) + paths.push_back(polynode.Contour); + for (int i = 0; i < polynode.ChildCount(); ++i) + AddPolyNodeToPolygons(*polynode.Childs[i], nodetype, paths); +} +//------------------------------------------------------------------------------ + +void PolyTreeToPaths(const PolyTree& polytree, Paths& paths) +{ + paths.resize(0); + paths.reserve(polytree.Total()); + AddPolyNodeToPolygons(polytree, ntAny, paths); +} +//------------------------------------------------------------------------------ + +void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths) +{ + paths.resize(0); + paths.reserve(polytree.Total()); + AddPolyNodeToPolygons(polytree, ntClosed, paths); +} +//------------------------------------------------------------------------------ + +void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths) +{ + paths.resize(0); + paths.reserve(polytree.Total()); + //Open paths are top level only, so ... + for (int i = 0; i < polytree.ChildCount(); ++i) + if (polytree.Childs[i]->IsOpen()) + paths.push_back(polytree.Childs[i]->Contour); +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, const IntPoint &p) +{ + s << "(" << p.X << "," << p.Y << ")"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, const Path &p) +{ + if (p.empty()) return s; + Path::size_type last = p.size() -1; + for (Path::size_type i = 0; i < last; i++) + s << "(" << p[i].X << "," << p[i].Y << "), "; + s << "(" << p[last].X << "," << p[last].Y << ")\n"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, const Paths &p) +{ + for (Paths::size_type i = 0; i < p.size(); i++) + s << p[i]; + s << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +#ifdef use_deprecated + +void OffsetPaths(const Paths &in_polys, Paths &out_polys, + double delta, JoinType jointype, EndType_ endtype, double limit) +{ + ClipperOffset co(limit, limit); + co.AddPaths(in_polys, jointype, (EndType)endtype); + co.Execute(out_polys, delta); +} +//------------------------------------------------------------------------------ + +#endif + + +} //ClipperLib namespace diff --git a/src/3rdparty/clipper/clipper.h b/src/3rdparty/clipper/clipper.h new file mode 100644 index 0000000..8487014 --- /dev/null +++ b/src/3rdparty/clipper/clipper.h @@ -0,0 +1,398 @@ +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 6.1.3a * +* Date : 22 January 2014 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2014 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24-28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +#ifndef clipper_hpp +#define clipper_hpp + +#define CLIPPER_VERSION "6.1.3" + +//use_int32: When enabled 32bit ints are used instead of 64bit ints. This +//improve performance but coordinate values are limited to the range +/- 46340 +//#define use_int32 + +//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance. +//#define use_xyz + +//use_lines: Enables line clipping. Adds a very minor cost to performance. +//#define use_lines + +//use_deprecated: Enables support for the obsolete OffsetPaths() function +//which has been replace with the ClipperOffset class. +#define use_deprecated + +#include +#include +#include +#include +#include +#include +#include + +namespace ClipperLib { + +enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; +enum PolyType { ptSubject, ptClip }; +//By far the most widely used winding rules for polygon filling are +//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) +//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) +//see http://glprogramming.com/red/chapter11.html +enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; + +#ifdef use_int32 +typedef int cInt; +typedef unsigned int cUInt; +#else +typedef signed long long cInt; +typedef unsigned long long cUInt; +#endif + +struct IntPoint { + cInt X; + cInt Y; +#ifdef use_xyz + cInt Z; + IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {}; +#else + IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {}; +#endif + + friend inline bool operator== (const IntPoint& a, const IntPoint& b) + { + return a.X == b.X && a.Y == b.Y; + } + friend inline bool operator!= (const IntPoint& a, const IntPoint& b) + { + return a.X != b.X || a.Y != b.Y; + } +}; +//------------------------------------------------------------------------------ + +typedef std::vector< IntPoint > Path; +typedef std::vector< Path > Paths; + +inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;} +inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;} + +std::ostream& operator <<(std::ostream &s, const IntPoint &p); +std::ostream& operator <<(std::ostream &s, const Path &p); +std::ostream& operator <<(std::ostream &s, const Paths &p); + +struct DoublePoint +{ + double X; + double Y; + DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} + DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {} +}; +//------------------------------------------------------------------------------ + +#ifdef use_xyz +typedef void (*TZFillCallback)(IntPoint& z1, IntPoint& z2, IntPoint& pt); +#endif + +enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4}; +enum JoinType {jtSquare, jtRound, jtMiter}; +enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound}; +#ifdef use_deprecated + enum EndType_ {etClosed, etButt = 2, etSquare, etRound}; +#endif + +class PolyNode; +typedef std::vector< PolyNode* > PolyNodes; + +class PolyNode +{ +public: + PolyNode(); + Path Contour; + PolyNodes Childs; + PolyNode* Parent; + PolyNode* GetNext() const; + bool IsHole() const; + bool IsOpen() const; + int ChildCount() const; +private: + unsigned Index; //node index in Parent.Childs + bool m_IsOpen; + JoinType m_jointype; + EndType m_endtype; + PolyNode* GetNextSiblingUp() const; + void AddChild(PolyNode& child); + friend class Clipper; //to access Index + friend class ClipperOffset; +}; + +class PolyTree: public PolyNode +{ +public: + ~PolyTree(){Clear();}; + PolyNode* GetFirst() const; + void Clear(); + int Total() const; +private: + PolyNodes AllNodes; + friend class Clipper; //to access AllNodes +}; + +bool Orientation(const Path &poly); +double Area(const Path &poly); +int PointInPolygon(const IntPoint &pt, const Path &path); + +#ifdef use_deprecated + void OffsetPaths(const Paths &in_polys, Paths &out_polys, + double delta, JoinType jointype, EndType_ endtype, double limit = 0); +#endif + +void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd); + +void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415); +void CleanPolygon(Path& poly, double distance = 1.415); +void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415); +void CleanPolygons(Paths& polys, double distance = 1.415); + +void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed); +void MinkowskiSum(const Path& pattern, const Paths& paths, + Paths& solution, PolyFillType pathFillType, bool pathIsClosed); +void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution); + +void PolyTreeToPaths(const PolyTree& polytree, Paths& paths); +void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths); +void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths); + +void ReversePath(Path& p); +void ReversePaths(Paths& p); + +struct IntRect { cInt left; cInt top; cInt right; cInt bottom; }; + +//enums that are used internally ... +enum EdgeSide { esLeft = 1, esRight = 2}; + +//forward declarations (for stuff used internally) ... +struct TEdge; +struct IntersectNode; +struct LocalMinima; +struct Scanbeam; +struct OutPt; +struct OutRec; +struct Join; + +typedef std::vector < OutRec* > PolyOutList; +typedef std::vector < TEdge* > EdgeList; +typedef std::vector < Join* > JoinList; +typedef std::vector < IntersectNode* > IntersectList; + + +//------------------------------------------------------------------------------ + +//ClipperBase is the ancestor to the Clipper class. It should not be +//instantiated directly. This class simply abstracts the conversion of sets of +//polygon coordinates into edge objects that are stored in a LocalMinima list. +class ClipperBase +{ +public: + ClipperBase(); + virtual ~ClipperBase(); + bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); + bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); + virtual void Clear(); + IntRect GetBounds(); + bool PreserveCollinear() {return m_PreserveCollinear;}; + void PreserveCollinear(bool value) {m_PreserveCollinear = value;}; +protected: + void DisposeLocalMinimaList(); + TEdge* AddBoundsToLML(TEdge *e, bool IsClosed); + void PopLocalMinima(); + virtual void Reset(); + TEdge* ProcessBound(TEdge* E, bool IsClockwise); + void InsertLocalMinima(LocalMinima *newLm); + void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed); + TEdge* DescendToMin(TEdge *&E); + void AscendToMax(TEdge *&E, bool Appending, bool IsClosed); + LocalMinima *m_CurrentLM; + LocalMinima *m_MinimaList; + bool m_UseFullRange; + EdgeList m_edges; + bool m_PreserveCollinear; + bool m_HasOpenPaths; +}; +//------------------------------------------------------------------------------ + +class Clipper : public virtual ClipperBase +{ +public: + Clipper(int initOptions = 0); + ~Clipper(); + bool Execute(ClipType clipType, + Paths &solution, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + bool Execute(ClipType clipType, + PolyTree &polytree, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + bool ReverseSolution() {return m_ReverseOutput;}; + void ReverseSolution(bool value) {m_ReverseOutput = value;}; + bool StrictlySimple() {return m_StrictSimple;}; + void StrictlySimple(bool value) {m_StrictSimple = value;}; + //set the callback function for z value filling on intersections (otherwise Z is 0) +#ifdef use_xyz + void ZFillFunction(TZFillCallback zFillFunc); +#endif +protected: + void Reset(); + virtual bool ExecuteInternal(); +private: + PolyOutList m_PolyOuts; + JoinList m_Joins; + JoinList m_GhostJoins; + IntersectList m_IntersectList; + ClipType m_ClipType; + std::set< cInt, std::greater > m_Scanbeam; + TEdge *m_ActiveEdges; + TEdge *m_SortedEdges; + bool m_ExecuteLocked; + PolyFillType m_ClipFillType; + PolyFillType m_SubjFillType; + bool m_ReverseOutput; + bool m_UsingPolyTree; + bool m_StrictSimple; +#ifdef use_xyz + TZFillCallback m_ZFill; //custom callback +#endif + void SetWindingCount(TEdge& edge); + bool IsEvenOddFillType(const TEdge& edge) const; + bool IsEvenOddAltFillType(const TEdge& edge) const; + void InsertScanbeam(const cInt Y); + cInt PopScanbeam(); + void InsertLocalMinimaIntoAEL(const cInt botY); + void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge); + void AddEdgeToSEL(TEdge *edge); + void CopyAELToSEL(); + void DeleteFromSEL(TEdge *e); + void DeleteFromAEL(TEdge *e); + void UpdateEdgeIntoAEL(TEdge *&e); + void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); + bool IsContributing(const TEdge& edge) const; + bool IsTopHorz(const cInt XPos); + void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); + void DoMaxima(TEdge *e); + void PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam); + void ProcessHorizontals(bool IsTopOfScanbeam); + void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam); + void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + OutRec* GetOutRec(int idx); + void AppendPolygon(TEdge *e1, TEdge *e2); + void IntersectEdges(TEdge *e1, TEdge *e2, + const IntPoint &pt, bool protect = false); + OutRec* CreateOutRec(); + OutPt* AddOutPt(TEdge *e, const IntPoint &pt); + void DisposeAllOutRecs(); + void DisposeOutRec(PolyOutList::size_type index); + bool ProcessIntersections(const cInt botY, const cInt topY); + void BuildIntersectList(const cInt botY, const cInt topY); + void ProcessIntersectList(); + void ProcessEdgesAtTopOfScanbeam(const cInt topY); + void BuildResult(Paths& polys); + void BuildResult2(PolyTree& polytree); + void SetHoleState(TEdge *e, OutRec *outrec); + void DisposeIntersectNodes(); + bool FixupIntersectionOrder(); + void FixupOutPolygon(OutRec &outrec); + bool IsHole(TEdge *e); + bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl); + void FixHoleLinkage(OutRec &outrec); + void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt); + void ClearJoins(); + void ClearGhostJoins(); + void AddGhostJoin(OutPt *op, const IntPoint offPt); + bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2); + void JoinCommonEdges(); + void DoSimplePolygons(); + void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec); + void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec); +#ifdef use_xyz + void SetZ(IntPoint& pt, TEdge& e); +#endif +}; +//------------------------------------------------------------------------------ + +class ClipperOffset +{ +public: + ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25); + ~ClipperOffset(); + void AddPath(const Path& path, JoinType joinType, EndType endType); + void AddPaths(const Paths& paths, JoinType joinType, EndType endType); + void Execute(Paths& solution, double delta); + void Execute(PolyTree& solution, double delta); + void Clear(); + double MiterLimit; + double ArcTolerance; +private: + Paths m_destPolys; + Path m_srcPoly; + Path m_destPoly; + std::vector m_normals; + double m_delta, m_sinA, m_sin, m_cos; + double m_miterLim, m_StepsPerRad; + IntPoint m_lowest; + PolyNode m_polyNodes; + + void FixOrientations(); + void DoOffset(double delta); + void OffsetPoint(int j, int& k, JoinType jointype); + void DoSquare(int j, int k); + void DoMiter(int j, int k, double r); + void DoRound(int j, int k); +}; +//------------------------------------------------------------------------------ + +class clipperException : public std::exception +{ + public: + clipperException(const char* description): m_descr(description) {} + virtual ~clipperException() throw() {} + virtual const char* what() const throw() {return m_descr.c_str();} + private: + std::string m_descr; +}; +//------------------------------------------------------------------------------ + +} //ClipperLib namespace + +#endif //clipper_hpp + + diff --git a/src/3rdparty/clipper/clipper.pro b/src/3rdparty/clipper/clipper.pro new file mode 100644 index 0000000..233874e --- /dev/null +++ b/src/3rdparty/clipper/clipper.pro @@ -0,0 +1,17 @@ +TARGET = clipper + +CONFIG += staticlib +CONFIG += exceptions + + +load(qt_helper_lib) + +# workaround for QTBUG-31586 +contains(QT_CONFIG, c++11): CONFIG += c++11 + +*-g++* { + QMAKE_CXXFLAGS += -O3 -ftree-vectorize -ffast-math -funsafe-math-optimizations -Wno-error=return-type +} + +HEADERS += clipper.h +SOURCES += clipper.cpp diff --git a/src/3rdparty/clipper_legal.qdoc b/src/3rdparty/clipper_legal.qdoc new file mode 100644 index 0000000..59b7f57 --- /dev/null +++ b/src/3rdparty/clipper_legal.qdoc @@ -0,0 +1,34 @@ +/*! +\page legal-clipper.html +\title Clipper Polygon Clipping Library +\ingroup licensing + +\legalese +\code +Clipper Copyright Angus Johnson 2010-2014 +http://www.angusj.com + +Use, modification & distribution is subject to Boost Software License Ver 1. +http://www.boost.org/LICENSE_1_0.txt + +Attributions: +The code in this library is an extension of Bala Vatti's clipping algorithm: +"A generic solution to polygon clipping" +Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. +http://portal.acm.org/citation.cfm?id=129906 + +Computer graphics and geometric modeling: implementation and algorithms +By Max K. Agoston +Springer; 1 edition (January 4, 2005) +http://books.google.com/books?q=vatti+clipping+agoston + +See also: +"Polygon Offsetting by Computing Winding Numbers" +Paper no. DETC2005-85513 pp. 565-575 +ASME 2005 International Design Engineering Technical Conferences +and Computers and Information in Engineering Conference (IDETC/CIE2005) +September 24-28, 2005 , Long Beach, California, USA +http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf +\endcode +\endlegalese +*/ diff --git a/src/3rdparty/poly2tri/AUTHORS b/src/3rdparty/poly2tri/AUTHORS new file mode 100644 index 0000000..421601a --- /dev/null +++ b/src/3rdparty/poly2tri/AUTHORS @@ -0,0 +1,8 @@ +Primary Contributors: + + Mason Green (C++, Python) + Thomas Åhlén (Java) + +Other Contributors: + + diff --git a/src/3rdparty/poly2tri/LICENSE b/src/3rdparty/poly2tri/LICENSE new file mode 100644 index 0000000..9417c08 --- /dev/null +++ b/src/3rdparty/poly2tri/LICENSE @@ -0,0 +1,27 @@ +Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +http://code.google.com/p/poly2tri/ + +All rights reserved. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of Poly2Tri nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/3rdparty/poly2tri/common/shapes.cpp b/src/3rdparty/poly2tri/common/shapes.cpp new file mode 100644 index 0000000..2ac7e97 --- /dev/null +++ b/src/3rdparty/poly2tri/common/shapes.cpp @@ -0,0 +1,363 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "shapes.h" +#include + +namespace p2t { + +Triangle::Triangle(Point& a, Point& b, Point& c) +{ + points_[0] = &a; points_[1] = &b; points_[2] = &c; + neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL; + constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; + delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; + interior_ = false; +} + +// Update neighbor pointers +void Triangle::MarkNeighbor(Point* p1, Point* p2, Triangle* t) +{ + if ((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2])) + neighbors_[0] = t; + else if ((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0])) + neighbors_[1] = t; + else if ((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0])) + neighbors_[2] = t; + else + assert(0); +} + +// Exhaustive search to update neighbor pointers +void Triangle::MarkNeighbor(Triangle& t) +{ + if (t.Contains(points_[1], points_[2])) { + neighbors_[0] = &t; + t.MarkNeighbor(points_[1], points_[2], this); + } else if (t.Contains(points_[0], points_[2])) { + neighbors_[1] = &t; + t.MarkNeighbor(points_[0], points_[2], this); + } else if (t.Contains(points_[0], points_[1])) { + neighbors_[2] = &t; + t.MarkNeighbor(points_[0], points_[1], this); + } +} + +/** + * Clears all references to all other triangles and points + */ +void Triangle::Clear() +{ + Triangle *t; + for (int i=0; i<3; i++) + { + t = neighbors_[i]; + if (t != NULL) + { + t->ClearNeighbor( this ); + } + } + ClearNeighbors(); + points_[0]=points_[1]=points_[2] = NULL; +} + +void Triangle::ClearNeighbor(Triangle *triangle ) +{ + if (neighbors_[0] == triangle) + { + neighbors_[0] = NULL; + } + else if (neighbors_[1] == triangle) + { + neighbors_[1] = NULL; + } + else + { + neighbors_[2] = NULL; + } +} + +void Triangle::ClearNeighbors() +{ + neighbors_[0] = NULL; + neighbors_[1] = NULL; + neighbors_[2] = NULL; +} + +void Triangle::ClearDelunayEdges() +{ + delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; +} + +Point* Triangle::OppositePoint(Triangle& t, Point& p) +{ + Point *cw = t.PointCW(p); + return PointCW(*cw); +} + +// Legalized triangle by rotating clockwise around point(0) +void Triangle::Legalize(Point& point) +{ + points_[1] = points_[0]; + points_[0] = points_[2]; + points_[2] = &point; +} + +// Legalize triagnle by rotating clockwise around oPoint +void Triangle::Legalize(Point& opoint, Point& npoint) +{ + if (&opoint == points_[0]) { + points_[1] = points_[0]; + points_[0] = points_[2]; + points_[2] = &npoint; + } else if (&opoint == points_[1]) { + points_[2] = points_[1]; + points_[1] = points_[0]; + points_[0] = &npoint; + } else if (&opoint == points_[2]) { + points_[0] = points_[2]; + points_[2] = points_[1]; + points_[1] = &npoint; + } else { + assert(0); + } +} + +int Triangle::Index(const Point* p) +{ + if (p == points_[0]) { + return 0; + } else if (p == points_[1]) { + return 1; + } else if (p == points_[2]) { + return 2; + } + assert(0); +} + +int Triangle::EdgeIndex(const Point* p1, const Point* p2) +{ + if (points_[0] == p1) { + if (points_[1] == p2) { + return 2; + } else if (points_[2] == p2) { + return 1; + } + } else if (points_[1] == p1) { + if (points_[2] == p2) { + return 0; + } else if (points_[0] == p2) { + return 2; + } + } else if (points_[2] == p1) { + if (points_[0] == p2) { + return 1; + } else if (points_[1] == p2) { + return 0; + } + } + return -1; +} + +void Triangle::MarkConstrainedEdge(const int index) +{ + constrained_edge[index] = true; +} + +void Triangle::MarkConstrainedEdge(Edge& edge) +{ + MarkConstrainedEdge(edge.p, edge.q); +} + +// Mark edge as constrained +void Triangle::MarkConstrainedEdge(Point* p, Point* q) +{ + if ((q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0])) { + constrained_edge[2] = true; + } else if ((q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0])) { + constrained_edge[1] = true; + } else if ((q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1])) { + constrained_edge[0] = true; + } +} + +// The point counter-clockwise to given point +Point* Triangle::PointCW(Point& point) +{ + if (&point == points_[0]) { + return points_[2]; + } else if (&point == points_[1]) { + return points_[0]; + } else if (&point == points_[2]) { + return points_[1]; + } + assert(0); +} + +// The point counter-clockwise to given point +Point* Triangle::PointCCW(Point& point) +{ + if (&point == points_[0]) { + return points_[1]; + } else if (&point == points_[1]) { + return points_[2]; + } else if (&point == points_[2]) { + return points_[0]; + } + assert(0); +} + +// The neighbor clockwise to given point +Triangle* Triangle::NeighborCW(Point& point) +{ + if (&point == points_[0]) { + return neighbors_[1]; + } else if (&point == points_[1]) { + return neighbors_[2]; + } + return neighbors_[0]; +} + +// The neighbor counter-clockwise to given point +Triangle* Triangle::NeighborCCW(Point& point) +{ + if (&point == points_[0]) { + return neighbors_[2]; + } else if (&point == points_[1]) { + return neighbors_[0]; + } + return neighbors_[1]; +} + +bool Triangle::GetConstrainedEdgeCCW(Point& p) +{ + if (&p == points_[0]) { + return constrained_edge[2]; + } else if (&p == points_[1]) { + return constrained_edge[0]; + } + return constrained_edge[1]; +} + +bool Triangle::GetConstrainedEdgeCW(Point& p) +{ + if (&p == points_[0]) { + return constrained_edge[1]; + } else if (&p == points_[1]) { + return constrained_edge[2]; + } + return constrained_edge[0]; +} + +void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce) +{ + if (&p == points_[0]) { + constrained_edge[2] = ce; + } else if (&p == points_[1]) { + constrained_edge[0] = ce; + } else { + constrained_edge[1] = ce; + } +} + +void Triangle::SetConstrainedEdgeCW(Point& p, bool ce) +{ + if (&p == points_[0]) { + constrained_edge[1] = ce; + } else if (&p == points_[1]) { + constrained_edge[2] = ce; + } else { + constrained_edge[0] = ce; + } +} + +bool Triangle::GetDelunayEdgeCCW(Point& p) +{ + if (&p == points_[0]) { + return delaunay_edge[2]; + } else if (&p == points_[1]) { + return delaunay_edge[0]; + } + return delaunay_edge[1]; +} + +bool Triangle::GetDelunayEdgeCW(Point& p) +{ + if (&p == points_[0]) { + return delaunay_edge[1]; + } else if (&p == points_[1]) { + return delaunay_edge[2]; + } + return delaunay_edge[0]; +} + +void Triangle::SetDelunayEdgeCCW(Point& p, bool e) +{ + if (&p == points_[0]) { + delaunay_edge[2] = e; + } else if (&p == points_[1]) { + delaunay_edge[0] = e; + } else { + delaunay_edge[1] = e; + } +} + +void Triangle::SetDelunayEdgeCW(Point& p, bool e) +{ + if (&p == points_[0]) { + delaunay_edge[1] = e; + } else if (&p == points_[1]) { + delaunay_edge[2] = e; + } else { + delaunay_edge[0] = e; + } +} + +// The neighbor across to given point +Triangle& Triangle::NeighborAcross(Point& opoint) +{ + if (&opoint == points_[0]) { + return *neighbors_[0]; + } else if (&opoint == points_[1]) { + return *neighbors_[1]; + } + return *neighbors_[2]; +} + +void Triangle::DebugPrint() +{ + using namespace std; + cout << points_[0]->x << "," << points_[0]->y << " "; + cout << points_[1]->x << "," << points_[1]->y << " "; + cout << points_[2]->x << "," << points_[2]->y << endl; +} + +} + diff --git a/src/3rdparty/poly2tri/common/shapes.h b/src/3rdparty/poly2tri/common/shapes.h new file mode 100644 index 0000000..5b90ea6 --- /dev/null +++ b/src/3rdparty/poly2tri/common/shapes.h @@ -0,0 +1,325 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Include guard +#ifndef SHAPES_H +#define SHAPES_H + +#include +#include +#include +#include + +namespace p2t { + +struct Edge; + +struct Point { + + double x, y; + + /// Default constructor does nothing (for performance). + Point() + { + x = 0.0; + y = 0.0; + } + + /// The edges this point constitutes an upper ending point + std::vector edge_list; + + /// Construct using coordinates. + Point(double x, double y) : x(x), y(y) {} + + /// Set this point to all zeros. + void set_zero() + { + x = 0.0; + y = 0.0; + } + + /// Set this point to some specified coordinates. + void set(double x_, double y_) + { + x = x_; + y = y_; + } + + /// Negate this point. + Point operator -() const + { + Point v; + v.set(-x, -y); + return v; + } + + /// Add a point to this point. + void operator +=(const Point& v) + { + x += v.x; + y += v.y; + } + + /// Subtract a point from this point. + void operator -=(const Point& v) + { + x -= v.x; + y -= v.y; + } + + /// Multiply this point by a scalar. + void operator *=(double a) + { + x *= a; + y *= a; + } + + /// Get the length of this point (the norm). + double Length() const + { + return std::sqrt(x * x + y * y); + } + + /// Convert this point into a unit point. Returns the Length. + double Normalize() + { + double len = Length(); + x /= len; + y /= len; + return len; + } + +}; + +// Represents a simple polygon's edge +struct Edge { + + Point* p, *q; + + /// Constructor + Edge(Point& p1, Point& p2) : p(&p1), q(&p2) + { + if (p1.y > p2.y) { + q = &p1; + p = &p2; + } else if (p1.y == p2.y) { + if (p1.x > p2.x) { + q = &p1; + p = &p2; + } else if (p1.x == p2.x) { + // Repeat points + assert(false); + } + } + + q->edge_list.push_back(this); + } +}; + +// Triangle-based data structures are know to have better performance than quad-edge structures +// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" +// "Triangulations in CGAL" +class Triangle { +public: + +/// Constructor +Triangle(Point& a, Point& b, Point& c); + +/// Flags to determine if an edge is a Constrained edge +bool constrained_edge[3]; +/// Flags to determine if an edge is a Delauney edge +bool delaunay_edge[3]; + +Point* GetPoint(const int& index); +Point* PointCW(Point& point); +Point* PointCCW(Point& point); +Point* OppositePoint(Triangle& t, Point& p); + +Triangle* GetNeighbor(const int& index); +void MarkNeighbor(Point* p1, Point* p2, Triangle* t); +void MarkNeighbor(Triangle& t); + +void MarkConstrainedEdge(const int index); +void MarkConstrainedEdge(Edge& edge); +void MarkConstrainedEdge(Point* p, Point* q); + +int Index(const Point* p); +int EdgeIndex(const Point* p1, const Point* p2); + +Triangle* NeighborCW(Point& point); +Triangle* NeighborCCW(Point& point); +bool GetConstrainedEdgeCCW(Point& p); +bool GetConstrainedEdgeCW(Point& p); +void SetConstrainedEdgeCCW(Point& p, bool ce); +void SetConstrainedEdgeCW(Point& p, bool ce); +bool GetDelunayEdgeCCW(Point& p); +bool GetDelunayEdgeCW(Point& p); +void SetDelunayEdgeCCW(Point& p, bool e); +void SetDelunayEdgeCW(Point& p, bool e); + +bool Contains(Point* p); +bool Contains(const Edge& e); +bool Contains(Point* p, Point* q); +void Legalize(Point& point); +void Legalize(Point& opoint, Point& npoint); +/** + * Clears all references to all other triangles and points + */ +void Clear(); +void ClearNeighbor(Triangle *triangle ); +void ClearNeighbors(); +void ClearDelunayEdges(); + +inline bool IsInterior(); +inline void IsInterior(bool b); + +Triangle& NeighborAcross(Point& opoint); + +void DebugPrint(); + +private: + +/// Triangle points +Point* points_[3]; +/// Neighbor list +Triangle* neighbors_[3]; + +/// Has this triangle been marked as an interior triangle? +bool interior_; +}; + +inline bool cmp(const Point* a, const Point* b) +{ + if (a->y < b->y) { + return true; + } else if (a->y == b->y) { + // Make sure q is point with greater x value + if (a->x < b->x) { + return true; + } + } + return false; +} + +/// Add two points_ component-wise. +inline Point operator +(const Point& a, const Point& b) +{ + return Point(a.x + b.x, a.y + b.y); +} + +/// Subtract two points_ component-wise. +inline Point operator -(const Point& a, const Point& b) +{ + return Point(a.x - b.x, a.y - b.y); +} + +/// Multiply point by scalar +inline Point operator *(double s, const Point& a) +{ + return Point(s * a.x, s * a.y); +} + +inline bool operator ==(const Point& a, const Point& b) +{ + return a.x == b.x && a.y == b.y; +} + +inline bool operator !=(const Point& a, const Point& b) +{ + return !(a.x == b.x) && !(a.y == b.y); +} + +/// Peform the dot product on two vectors. +inline double Dot(const Point& a, const Point& b) +{ + return a.x * b.x + a.y * b.y; +} + +/// Perform the cross product on two vectors. In 2D this produces a scalar. +inline double Cross(const Point& a, const Point& b) +{ + return a.x * b.y - a.y * b.x; +} + +/// Perform the cross product on a point and a scalar. In 2D this produces +/// a point. +inline Point Cross(const Point& a, double s) +{ + return Point(s * a.y, -s * a.x); +} + +/// Perform the cross product on a scalar and a point. In 2D this produces +/// a point. +inline Point Cross(const double s, const Point& a) +{ + return Point(-s * a.y, s * a.x); +} + +inline Point* Triangle::GetPoint(const int& index) +{ + return points_[index]; +} + +inline Triangle* Triangle::GetNeighbor(const int& index) +{ + return neighbors_[index]; +} + +inline bool Triangle::Contains(Point* p) +{ + return p == points_[0] || p == points_[1] || p == points_[2]; +} + +inline bool Triangle::Contains(const Edge& e) +{ + return Contains(e.p) && Contains(e.q); +} + +inline bool Triangle::Contains(Point* p, Point* q) +{ + return Contains(p) && Contains(q); +} + +inline bool Triangle::IsInterior() +{ + return interior_; +} + +inline void Triangle::IsInterior(bool b) +{ + interior_ = b; +} + +} + +#endif + + diff --git a/src/3rdparty/poly2tri/common/utils.h b/src/3rdparty/poly2tri/common/utils.h new file mode 100644 index 0000000..8744b6d --- /dev/null +++ b/src/3rdparty/poly2tri/common/utils.h @@ -0,0 +1,127 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UTILS_H +#define UTILS_H + +// Otherwise #defines like M_PI are undeclared under Visual Studio +#define _USE_MATH_DEFINES + +#include +#include + +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif + +namespace p2t { + +const double PI_3div4 = 3 * M_PI / 4; +const double PI_div2 = 1.57079632679489661923; +const double EPSILON = 1e-12; + +enum Orientation { CW, CCW, COLLINEAR }; + +/** + * Forumla to calculate signed area
+ * Positive if CCW
+ * Negative if CW
+ * 0 if collinear
+ *
+ * A[P1,P2,P3]  =  (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
+ *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
+ * 
+ */ +Orientation Orient2d(Point& pa, Point& pb, Point& pc) +{ + double detleft = (pa.x - pc.x) * (pb.y - pc.y); + double detright = (pa.y - pc.y) * (pb.x - pc.x); + double val = detleft - detright; + if (val > -EPSILON && val < EPSILON) { + return COLLINEAR; + } else if (val > 0) { + return CCW; + } + return CW; +} + +/* +bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) +{ + double pdx = pd.x; + double pdy = pd.y; + double adx = pa.x - pdx; + double ady = pa.y - pdy; + double bdx = pb.x - pdx; + double bdy = pb.y - pdy; + + double adxbdy = adx * bdy; + double bdxady = bdx * ady; + double oabd = adxbdy - bdxady; + + if (oabd <= EPSILON) { + return false; + } + + double cdx = pc.x - pdx; + double cdy = pc.y - pdy; + + double cdxady = cdx * ady; + double adxcdy = adx * cdy; + double ocad = cdxady - adxcdy; + + if (ocad <= EPSILON) { + return false; + } + + return true; +} + +*/ + +bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) +{ + double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y); + if (oadb >= -EPSILON) { + return false; + } + + double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y); + if (oadc <= EPSILON) { + return false; + } + return true; +} + +} + +#endif + diff --git a/src/3rdparty/poly2tri/poly2tri.h b/src/3rdparty/poly2tri/poly2tri.h new file mode 100644 index 0000000..042cb3d --- /dev/null +++ b/src/3rdparty/poly2tri/poly2tri.h @@ -0,0 +1,39 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef POLY2TRI_H +#define POLY2TRI_H + +#include "common/shapes.h" +#include "sweep/cdt.h" + +#endif + diff --git a/src/3rdparty/poly2tri/poly2tri.pro b/src/3rdparty/poly2tri/poly2tri.pro new file mode 100644 index 0000000..d4ae9cd --- /dev/null +++ b/src/3rdparty/poly2tri/poly2tri.pro @@ -0,0 +1,26 @@ +TARGET = poly2tri + +CONFIG += staticlib + +load(qt_helper_lib) + +# workaround for QTBUG-31586 +contains(QT_CONFIG, c++11): CONFIG += c++11 + +*-g++* { + QMAKE_CXXFLAGS += -O3 -ftree-vectorize -ffast-math -funsafe-math-optimizations -Wno-error=return-type +} + +HEADERS += poly2tri.h \ + common/shapes.h \ + common/utils.h \ + sweep/advancing_front.h \ + sweep/cdt.h \ + sweep/sweep.h \ + sweep/sweep_context.h + +SOURCES += common/shapes.cpp \ + sweep/sweep_context.cpp \ + sweep/cdt.cpp \ + sweep/sweep.cpp \ + sweep/advancing_front.cpp diff --git a/src/3rdparty/poly2tri/sweep/advancing_front.cpp b/src/3rdparty/poly2tri/sweep/advancing_front.cpp new file mode 100644 index 0000000..0377984 --- /dev/null +++ b/src/3rdparty/poly2tri/sweep/advancing_front.cpp @@ -0,0 +1,109 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "advancing_front.h" + +namespace p2t { + +AdvancingFront::AdvancingFront(Node& head, Node& tail) +{ + head_ = &head; + tail_ = &tail; + search_node_ = &head; +} + +Node* AdvancingFront::LocateNode(const double& x) +{ + Node* node = search_node_; + + if (x < node->value) { + while ((node = node->prev) != NULL) { + if (x >= node->value) { + search_node_ = node; + return node; + } + } + } else { + while ((node = node->next) != NULL) { + if (x < node->value) { + search_node_ = node->prev; + return node->prev; + } + } + } + return NULL; +} + +Node* AdvancingFront::FindSearchNode(const double& x) +{ + (void)x; // suppress compiler warnings "unused parameter 'x'" + // TODO: implement BST index + return search_node_; +} + +Node* AdvancingFront::LocatePoint(const Point* point) +{ + const double px = point->x; + Node* node = FindSearchNode(px); + const double nx = node->point->x; + + if (px == nx) { + if (point != node->point) { + // We might have two nodes with same x value for a short time + if (point == node->prev->point) { + node = node->prev; + } else if (point == node->next->point) { + node = node->next; + } else { + assert(0); + } + } + } else if (px < nx) { + while ((node = node->prev) != NULL) { + if (point == node->point) { + break; + } + } + } else { + while ((node = node->next) != NULL) { + if (point == node->point) + break; + } + } + if (node) search_node_ = node; + return node; +} + +AdvancingFront::~AdvancingFront() +{ +} + +} + diff --git a/src/3rdparty/poly2tri/sweep/advancing_front.h b/src/3rdparty/poly2tri/sweep/advancing_front.h new file mode 100644 index 0000000..bab73d4 --- /dev/null +++ b/src/3rdparty/poly2tri/sweep/advancing_front.h @@ -0,0 +1,118 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ADVANCED_FRONT_H +#define ADVANCED_FRONT_H + +#include "../common/shapes.h" + +namespace p2t { + +struct Node; + +// Advancing front node +struct Node { + Point* point; + Triangle* triangle; + + Node* next; + Node* prev; + + double value; + + Node(Point& p) : point(&p), triangle(NULL), next(NULL), prev(NULL), value(p.x) + { + } + + Node(Point& p, Triangle& t) : point(&p), triangle(&t), next(NULL), prev(NULL), value(p.x) + { + } + +}; + +// Advancing front +class AdvancingFront { +public: + +AdvancingFront(Node& head, Node& tail); +// Destructor +~AdvancingFront(); + +Node* head(); +void set_head(Node* node); +Node* tail(); +void set_tail(Node* node); +Node* search(); +void set_search(Node* node); + +/// Locate insertion point along advancing front +Node* LocateNode(const double& x); + +Node* LocatePoint(const Point* point); + +private: + +Node* head_, *tail_, *search_node_; + +Node* FindSearchNode(const double& x); +}; + +inline Node* AdvancingFront::head() +{ + return head_; +} +inline void AdvancingFront::set_head(Node* node) +{ + head_ = node; +} + +inline Node* AdvancingFront::tail() +{ + return tail_; +} +inline void AdvancingFront::set_tail(Node* node) +{ + tail_ = node; +} + +inline Node* AdvancingFront::search() +{ + return search_node_; +} + +inline void AdvancingFront::set_search(Node* node) +{ + search_node_ = node; +} + +} + +#endif diff --git a/src/3rdparty/poly2tri/sweep/cdt.cpp b/src/3rdparty/poly2tri/sweep/cdt.cpp new file mode 100644 index 0000000..e0b3ec7 --- /dev/null +++ b/src/3rdparty/poly2tri/sweep/cdt.cpp @@ -0,0 +1,72 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "cdt.h" + +namespace p2t { + +CDT::CDT(std::vector polyline) +{ + sweep_context_ = new SweepContext(polyline); + sweep_ = new Sweep; +} + +void CDT::AddHole(std::vector polyline) +{ + sweep_context_->AddHole(polyline); +} + +void CDT::AddPoint(Point* point) { + sweep_context_->AddPoint(point); +} + +void CDT::Triangulate() +{ + sweep_->Triangulate(*sweep_context_); +} + +std::vector CDT::GetTriangles() +{ + return sweep_context_->GetTriangles(); +} + +std::list CDT::GetMap() +{ + return sweep_context_->GetMap(); +} + +CDT::~CDT() +{ + delete sweep_context_; + delete sweep_; +} + +} + diff --git a/src/3rdparty/poly2tri/sweep/cdt.h b/src/3rdparty/poly2tri/sweep/cdt.h new file mode 100644 index 0000000..e7b703d --- /dev/null +++ b/src/3rdparty/poly2tri/sweep/cdt.h @@ -0,0 +1,105 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CDT_H +#define CDT_H + +#include "advancing_front.h" +#include "sweep_context.h" +#include "sweep.h" + +/** + * + * @author Mason Green + * + */ + +namespace p2t { + +class CDT +{ +public: + + /** + * Constructor - add polyline with non repeating points + * + * @param polyline + */ + CDT(std::vector polyline); + + /** + * Destructor - clean up memory + */ + ~CDT(); + + /** + * Add a hole + * + * @param polyline + */ + void AddHole(std::vector polyline); + + /** + * Add a steiner point + * + * @param point + */ + void AddPoint(Point* point); + + /** + * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points + */ + void Triangulate(); + + /** + * Get CDT triangles + */ + std::vector GetTriangles(); + + /** + * Get triangle map + */ + std::list GetMap(); + + private: + + /** + * Internals + */ + + SweepContext* sweep_context_; + Sweep* sweep_; + +}; + +} + +#endif diff --git a/src/3rdparty/poly2tri/sweep/sweep.cpp b/src/3rdparty/poly2tri/sweep/sweep.cpp new file mode 100644 index 0000000..954d2db --- /dev/null +++ b/src/3rdparty/poly2tri/sweep/sweep.cpp @@ -0,0 +1,814 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include "sweep.h" +#include "sweep_context.h" +#include "advancing_front.h" +#include "../common/utils.h" + +namespace p2t { + +// Triangulate simple polygon with holes +void Sweep::Triangulate(SweepContext& tcx) +{ + tcx.InitTriangulation(); + tcx.CreateAdvancingFront(nodes_); + // Sweep points; build mesh + SweepPoints(tcx); + // Clean up + FinalizationPolygon(tcx); +} + +void Sweep::SweepPoints(SweepContext& tcx) +{ + for (int i = 1; i < tcx.point_count(); i++) { + Point& point = *tcx.GetPoint(i); + Node* node = &PointEvent(tcx, point); + for (unsigned int i = 0; i < point.edge_list.size(); i++) { + EdgeEvent(tcx, point.edge_list[i], node); + } + } +} + +void Sweep::FinalizationPolygon(SweepContext& tcx) +{ + // Get an Internal triangle to start with + Triangle* t = tcx.front()->head()->next->triangle; + Point* p = tcx.front()->head()->next->point; + while (!t->GetConstrainedEdgeCW(*p)) { + t = t->NeighborCCW(*p); + } + + // Collect interior triangles constrained by edges + tcx.MeshClean(*t); +} + +Node& Sweep::PointEvent(SweepContext& tcx, Point& point) +{ + Node& node = tcx.LocateNode(point); + Node& new_node = NewFrontTriangle(tcx, point, node); + + // Only need to check +epsilon since point never have smaller + // x value than node due to how we fetch nodes from the front + if (point.x <= node.point->x + EPSILON) { + Fill(tcx, node); + } + + //tcx.AddNode(new_node); + + FillAdvancingFront(tcx, new_node); + return new_node; +} + +void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node) +{ + tcx.edge_event.constrained_edge = edge; + tcx.edge_event.right = (edge->p->x > edge->q->x); + + if (IsEdgeSideOfTriangle(*node->triangle, *edge->p, *edge->q)) { + return; + } + + // For now we will do all needed filling + // TODO: integrate with flip process might give some better performance + // but for now this avoid the issue with cases that needs both flips and fills + FillEdgeEvent(tcx, edge, node); + EdgeEvent(tcx, *edge->p, *edge->q, node->triangle, *edge->q); +} + +void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) +{ + if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { + return; + } + + Point* p1 = triangle->PointCCW(point); + Orientation o1 = Orient2d(eq, *p1, ep); + if (o1 == COLLINEAR) { + if ( triangle->Contains(&eq, p1)) { + triangle->MarkConstrainedEdge(&eq, p1 ); + // We are modifying the constraint maybe it would be better to + // not change the given constraint and just keep a variable for the new constraint + tcx.edge_event.constrained_edge->q = p1; + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p1, triangle, *p1 ); + } else { + std::runtime_error("EdgeEvent - collinear points not supported"); + assert(0); + } + return; + } + + Point* p2 = triangle->PointCW(point); + Orientation o2 = Orient2d(eq, *p2, ep); + if (o2 == COLLINEAR) { + if ( triangle->Contains(&eq, p2)) { + triangle->MarkConstrainedEdge(&eq, p2 ); + // We are modifying the constraint maybe it would be better to + // not change the given constraint and just keep a variable for the new constraint + tcx.edge_event.constrained_edge->q = p2; + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p2, triangle, *p2 ); + } else { + std::runtime_error("EdgeEvent - collinear points not supported"); + assert(0); + } + return; + } + + if (o1 == o2) { + // Need to decide if we are rotating CW or CCW to get to a triangle + // that will cross edge + if (o1 == CW) { + triangle = triangle->NeighborCCW(point); + } else{ + triangle = triangle->NeighborCW(point); + } + EdgeEvent(tcx, ep, eq, triangle, point); + } else { + // This triangle crosses constraint so lets flippin start! + FlipEdgeEvent(tcx, ep, eq, triangle, point); + } +} + +bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq) +{ + int index = triangle.EdgeIndex(&ep, &eq); + + if (index != -1) { + triangle.MarkConstrainedEdge(index); + Triangle* t = triangle.GetNeighbor(index); + if (t) { + t->MarkConstrainedEdge(&ep, &eq); + } + return true; + } + return false; +} + +Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node) +{ + Triangle* triangle = new Triangle(point, *node.point, *node.next->point); + + triangle->MarkNeighbor(*node.triangle); + tcx.AddToMap(triangle); + + Node* new_node = new Node(point); + nodes_.push_back(new_node); + + new_node->next = node.next; + new_node->prev = &node; + node.next->prev = new_node; + node.next = new_node; + + if (!Legalize(tcx, *triangle)) { + tcx.MapTriangleToNodes(*triangle); + } + + return *new_node; +} + +void Sweep::Fill(SweepContext& tcx, Node& node) +{ + Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point); + + // TODO: should copy the constrained_edge value from neighbor triangles + // for now constrained_edge values are copied during the legalize + triangle->MarkNeighbor(*node.prev->triangle); + triangle->MarkNeighbor(*node.triangle); + + tcx.AddToMap(triangle); + + // Update the advancing front + node.prev->next = node.next; + node.next->prev = node.prev; + + // If it was legalized the triangle has already been mapped + if (!Legalize(tcx, *triangle)) { + tcx.MapTriangleToNodes(*triangle); + } + +} + +void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) +{ + + // Fill right holes + Node* node = n.next; + + while (node->next) { + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; + Fill(tcx, *node); + node = node->next; + } + + // Fill left holes + node = n.prev; + + while (node->prev) { + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; + Fill(tcx, *node); + node = node->prev; + } + + // Fill right basins + if (n.next && n.next->next) { + double angle = BasinAngle(n); + if (angle < PI_3div4) { + FillBasin(tcx, n); + } + } +} + +// True if HoleAngle exceeds 90 degrees. +bool Sweep::LargeHole_DontFill(Node* node) { + + Node* nextNode = node->next; + Node* prevNode = node->prev; + if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point)) + return false; + + // Check additional points on front. + Node* next2Node = nextNode->next; + // "..Plus.." because only want angles on same side as point being added. + if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point)) + return false; + + Node* prev2Node = prevNode->prev; + // "..Plus.." because only want angles on same side as point being added. + if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point)) + return false; + + return true; +} + +bool Sweep::AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb) { + double angle = Angle(*origin, *pa, *pb); + bool exceeds90Degrees = ((angle > PI_div2) || (angle < -PI_div2)); + return exceeds90Degrees; +} + +bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb) { + double angle = Angle(*origin, *pa, *pb); + bool exceedsPlus90DegreesOrIsNegative = (angle > PI_div2) || (angle < 0); + return exceedsPlus90DegreesOrIsNegative; +} + +double Sweep::Angle(Point& origin, Point& pa, Point& pb) { + /* Complex plane + * ab = cosA +i*sinA + * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) + * atan2(y,x) computes the principal value of the argument function + * applied to the complex number x+iy + * Where x = ax*bx + ay*by + * y = ax*by - ay*bx + */ + double px = origin.x; + double py = origin.y; + double ax = pa.x- px; + double ay = pa.y - py; + double bx = pb.x - px; + double by = pb.y - py; + double x = ax * by - ay * bx; + double y = ax * bx + ay * by; + double angle = atan2(x, y); + return angle; +} + +double Sweep::BasinAngle(Node& node) +{ + double ax = node.point->x - node.next->next->point->x; + double ay = node.point->y - node.next->next->point->y; + return atan2(ay, ax); +} + +double Sweep::HoleAngle(Node& node) +{ + /* Complex plane + * ab = cosA +i*sinA + * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) + * atan2(y,x) computes the principal value of the argument function + * applied to the complex number x+iy + * Where x = ax*bx + ay*by + * y = ax*by - ay*bx + */ + double ax = node.next->point->x - node.point->x; + double ay = node.next->point->y - node.point->y; + double bx = node.prev->point->x - node.point->x; + double by = node.prev->point->y - node.point->y; + return atan2(ax * by - ay * bx, ax * bx + ay * by); +} + +bool Sweep::Legalize(SweepContext& tcx, Triangle& t) +{ + // To legalize a triangle we start by finding if any of the three edges + // violate the Delaunay condition + for (int i = 0; i < 3; i++) { + if (t.delaunay_edge[i]) + continue; + + Triangle* ot = t.GetNeighbor(i); + + if (ot) { + Point* p = t.GetPoint(i); + Point* op = ot->OppositePoint(t, *p); + int oi = ot->Index(op); + + // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) + // then we should not try to legalize + if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { + t.constrained_edge[i] = ot->constrained_edge[oi]; + continue; + } + + bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); + + if (inside) { + // Lets mark this shared edge as Delaunay + t.delaunay_edge[i] = true; + ot->delaunay_edge[oi] = true; + + // Lets rotate shared edge one vertex CW to legalize it + RotateTrianglePair(t, *p, *ot, *op); + + // We now got one valid Delaunay Edge shared by two triangles + // This gives us 4 new edges to check for Delaunay + + // Make sure that triangle to node mapping is done only one time for a specific triangle + bool not_legalized = !Legalize(tcx, t); + if (not_legalized) { + tcx.MapTriangleToNodes(t); + } + + not_legalized = !Legalize(tcx, *ot); + if (not_legalized) + tcx.MapTriangleToNodes(*ot); + + // Reset the Delaunay edges, since they only are valid Delaunay edges + // until we add a new triangle or point. + // XXX: need to think about this. Can these edges be tried after we + // return to previous recursive level? + t.delaunay_edge[i] = false; + ot->delaunay_edge[oi] = false; + + // If triangle have been legalized no need to check the other edges since + // the recursive legalization will handles those so we can end here. + return true; + } + } + } + return false; +} + +bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) +{ + double adx = pa.x - pd.x; + double ady = pa.y - pd.y; + double bdx = pb.x - pd.x; + double bdy = pb.y - pd.y; + + double adxbdy = adx * bdy; + double bdxady = bdx * ady; + double oabd = adxbdy - bdxady; + + if (oabd <= 0) + return false; + + double cdx = pc.x - pd.x; + double cdy = pc.y - pd.y; + + double cdxady = cdx * ady; + double adxcdy = adx * cdy; + double ocad = cdxady - adxcdy; + + if (ocad <= 0) + return false; + + double bdxcdy = bdx * cdy; + double cdxbdy = cdx * bdy; + + double alift = adx * adx + ady * ady; + double blift = bdx * bdx + bdy * bdy; + double clift = cdx * cdx + cdy * cdy; + + double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd; + + return det > 0; +} + +void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) +{ + Triangle* n1, *n2, *n3, *n4; + n1 = t.NeighborCCW(p); + n2 = t.NeighborCW(p); + n3 = ot.NeighborCCW(op); + n4 = ot.NeighborCW(op); + + bool ce1, ce2, ce3, ce4; + ce1 = t.GetConstrainedEdgeCCW(p); + ce2 = t.GetConstrainedEdgeCW(p); + ce3 = ot.GetConstrainedEdgeCCW(op); + ce4 = ot.GetConstrainedEdgeCW(op); + + bool de1, de2, de3, de4; + de1 = t.GetDelunayEdgeCCW(p); + de2 = t.GetDelunayEdgeCW(p); + de3 = ot.GetDelunayEdgeCCW(op); + de4 = ot.GetDelunayEdgeCW(op); + + t.Legalize(p, op); + ot.Legalize(op, p); + + // Remap delaunay_edge + ot.SetDelunayEdgeCCW(p, de1); + t.SetDelunayEdgeCW(p, de2); + t.SetDelunayEdgeCCW(op, de3); + ot.SetDelunayEdgeCW(op, de4); + + // Remap constrained_edge + ot.SetConstrainedEdgeCCW(p, ce1); + t.SetConstrainedEdgeCW(p, ce2); + t.SetConstrainedEdgeCCW(op, ce3); + ot.SetConstrainedEdgeCW(op, ce4); + + // Remap neighbors + // XXX: might optimize the markNeighbor by keeping track of + // what side should be assigned to what neighbor after the + // rotation. Now mark neighbor does lots of testing to find + // the right side. + t.ClearNeighbors(); + ot.ClearNeighbors(); + if (n1) ot.MarkNeighbor(*n1); + if (n2) t.MarkNeighbor(*n2); + if (n3) t.MarkNeighbor(*n3); + if (n4) ot.MarkNeighbor(*n4); + t.MarkNeighbor(ot); +} + +void Sweep::FillBasin(SweepContext& tcx, Node& node) +{ + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + tcx.basin.left_node = node.next->next; + } else { + tcx.basin.left_node = node.next; + } + + // Find the bottom and right node + tcx.basin.bottom_node = tcx.basin.left_node; + while (tcx.basin.bottom_node->next + && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) { + tcx.basin.bottom_node = tcx.basin.bottom_node->next; + } + if (tcx.basin.bottom_node == tcx.basin.left_node) { + // No valid basin + return; + } + + tcx.basin.right_node = tcx.basin.bottom_node; + while (tcx.basin.right_node->next + && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) { + tcx.basin.right_node = tcx.basin.right_node->next; + } + if (tcx.basin.right_node == tcx.basin.bottom_node) { + // No valid basins + return; + } + + tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x; + tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y; + + FillBasinReq(tcx, tcx.basin.bottom_node); +} + +void Sweep::FillBasinReq(SweepContext& tcx, Node* node) +{ + // if shallow stop filling + if (IsShallow(tcx, *node)) { + return; + } + + Fill(tcx, *node); + + if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) { + return; + } else if (node->prev == tcx.basin.left_node) { + Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point); + if (o == CW) { + return; + } + node = node->next; + } else if (node->next == tcx.basin.right_node) { + Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point); + if (o == CCW) { + return; + } + node = node->prev; + } else { + // Continue with the neighbor node with lowest Y value + if (node->prev->point->y < node->next->point->y) { + node = node->prev; + } else { + node = node->next; + } + } + + FillBasinReq(tcx, node); +} + +bool Sweep::IsShallow(SweepContext& tcx, Node& node) +{ + double height; + + if (tcx.basin.left_highest) { + height = tcx.basin.left_node->point->y - node.point->y; + } else { + height = tcx.basin.right_node->point->y - node.point->y; + } + + // if shallow stop filling + if (tcx.basin.width > height) { + return true; + } + return false; +} + +void Sweep::FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) +{ + if (tcx.edge_event.right) { + FillRightAboveEdgeEvent(tcx, edge, node); + } else { + FillLeftAboveEdgeEvent(tcx, edge, node); + } +} + +void Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) +{ + while (node->next->point->x < edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node->next->point, *edge->p) == CCW) { + FillRightBelowEdgeEvent(tcx, edge, *node); + } else { + node = node->next; + } + } +} + +void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + if (node.point->x < edge->p->x) { + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else{ + // Convex + FillRightConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillRightBelowEdgeEvent(tcx, edge, node); + } + } +} + +void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + Fill(tcx, *node.next); + if (node.next->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { + // Below + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Next is concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else { + // Next is convex + } + } + } + +} + +void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + // Next concave or convex? + if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, *node.next); + } else{ + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { + // Below + FillRightConvexEdgeEvent(tcx, edge, *node.next); + } else{ + // Above + } + } +} + +void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) +{ + while (node->prev->point->x > edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) { + FillLeftBelowEdgeEvent(tcx, edge, *node); + } else { + node = node->prev; + } + } +} + +void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + if (node.point->x > edge->p->x) { + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else { + // Convex + FillLeftConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillLeftBelowEdgeEvent(tcx, edge, node); + } + } +} + +void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + // Next concave or convex? + if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); + } else{ + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { + // Below + FillLeftConvexEdgeEvent(tcx, edge, *node.prev); + } else{ + // Above + } + } +} + +void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + Fill(tcx, *node.prev); + if (node.prev->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { + // Below + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Next is concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else{ + // Next is convex + } + } + } + +} + +void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p) +{ + Triangle& ot = t->NeighborAcross(p); + Point& op = *ot.OppositePoint(*t, p); + + if (&ot == NULL) { + // If we want to integrate the fillEdgeEvent do it here + // With current implementation we should never get here + //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); + assert(0); + } + + if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) { + // Lets rotate shared edge one vertex CW + RotateTrianglePair(*t, p, ot, op); + tcx.MapTriangleToNodes(*t); + tcx.MapTriangleToNodes(ot); + + if (p == eq && op == ep) { + if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { + t->MarkConstrainedEdge(&ep, &eq); + ot.MarkConstrainedEdge(&ep, &eq); + Legalize(tcx, *t); + Legalize(tcx, ot); + } else { + // XXX: I think one of the triangles should be legalized here? + } + } else { + Orientation o = Orient2d(eq, op, ep); + t = &NextFlipTriangle(tcx, (int)o, *t, ot, p, op); + FlipEdgeEvent(tcx, ep, eq, t, p); + } + } else { + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, *t, ot, newP); + EdgeEvent(tcx, ep, eq, t, p); + } +} + +Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) +{ + if (o == CCW) { + // ot is not crossing edge after flip + int edge_index = ot.EdgeIndex(&p, &op); + ot.delaunay_edge[edge_index] = true; + Legalize(tcx, ot); + ot.ClearDelunayEdges(); + return t; + } + + // t is not crossing edge after flip + int edge_index = t.EdgeIndex(&p, &op); + + t.delaunay_edge[edge_index] = true; + Legalize(tcx, t); + t.ClearDelunayEdges(); + return ot; +} + +Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op) +{ + Orientation o2d = Orient2d(eq, op, ep); + if (o2d == CW) { + // Right + return *ot.PointCCW(op); + } else if (o2d == CCW) { + // Left + return *ot.PointCW(op); + } else{ + //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); + assert(0); + } +} + +void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, + Triangle& t, Point& p) +{ + Triangle& ot = t.NeighborAcross(p); + Point& op = *ot.OppositePoint(t, p); + + if (&t.NeighborAcross(p) == NULL) { + // If we want to integrate the fillEdgeEvent do it here + // With current implementation we should never get here + //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); + assert(0); + } + + if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) { + // flip with new edge op->eq + FlipEdgeEvent(tcx, eq, op, &ot, op); + // TODO: Actually I just figured out that it should be possible to + // improve this by getting the next ot and op before the above + // flip and continue the flipScanEdgeEvent here + // set new ot and op here and loop back to inScanArea test + // also need to set a new flip_triangle first + // Turns out at first glance that this is somewhat complicated + // so it will have to wait. + } else{ + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); + } +} + +Sweep::~Sweep() { + + // Clean up memory + for (size_t i = 0; i < nodes_.size(); i++) { + delete nodes_[i]; + } + +} + +} + diff --git a/src/3rdparty/poly2tri/sweep/sweep.h b/src/3rdparty/poly2tri/sweep/sweep.h new file mode 100644 index 0000000..9bb0b5d --- /dev/null +++ b/src/3rdparty/poly2tri/sweep/sweep.h @@ -0,0 +1,285 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * Sweep-line, Constrained Delauney Triangulation (CDT) See: Domiter, V. and + * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation', + * International Journal of Geographical Information Science + * + * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com + */ + +#ifndef SWEEP_H +#define SWEEP_H + +#include + +namespace p2t { + +class SweepContext; +struct Node; +struct Point; +struct Edge; +class Triangle; + +class Sweep +{ +public: + + /** + * Triangulate + * + * @param tcx + */ + void Triangulate(SweepContext& tcx); + + /** + * Destructor - clean up memory + */ + ~Sweep(); + +private: + + /** + * Start sweeping the Y-sorted point set from bottom to top + * + * @param tcx + */ + void SweepPoints(SweepContext& tcx); + + /** + * Find closes node to the left of the new point and + * create a new triangle. If needed new holes and basins + * will be filled to. + * + * @param tcx + * @param point + * @return + */ + Node& PointEvent(SweepContext& tcx, Point& point); + + /** + * + * + * @param tcx + * @param edge + * @param node + */ + void EdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + + void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point); + + /** + * Creates a new front triangle and legalize it + * + * @param tcx + * @param point + * @param node + * @return + */ + Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node); + + /** + * Adds a triangle to the advancing front to fill a hole. + * @param tcx + * @param node - middle node, that is the bottom of the hole + */ + void Fill(SweepContext& tcx, Node& node); + + /** + * Returns true if triangle was legalized + */ + bool Legalize(SweepContext& tcx, Triangle& t); + + /** + * Requirement:
+ * 1. a,b and c form a triangle.
+ * 2. a and d is know to be on opposite side of bc
+ *
+   *                a
+   *                +
+   *               / \
+   *              /   \
+   *            b/     \c
+   *            +-------+
+   *           /    d    \
+   *          /           \
+   * 
+ * Fact: d has to be in area B to have a chance to be inside the circle formed by + * a,b and c
+ * d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW
+ * This preknowledge gives us a way to optimize the incircle test + * @param a - triangle point, opposite d + * @param b - triangle point + * @param c - triangle point + * @param d - point opposite a + * @return true if d is inside circle, false if on circle edge + */ + bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd); + + /** + * Rotates a triangle pair one vertex CW + *
+   *       n2                    n2
+   *  P +-----+             P +-----+
+   *    | t  /|               |\  t |
+   *    |   / |               | \   |
+   *  n1|  /  |n3           n1|  \  |n3
+   *    | /   |    after CW   |   \ |
+   *    |/ oT |               | oT \|
+   *    +-----+ oP            +-----+
+   *       n4                    n4
+   * 
+ */ + void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op); + + /** + * Fills holes in the Advancing Front + * + * + * @param tcx + * @param n + */ + void FillAdvancingFront(SweepContext& tcx, Node& n); + + // Decision-making about when to Fill hole. + // Contributed by ToolmakerSteve2 + bool LargeHole_DontFill(Node* node); + bool AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb); + bool AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb); + double Angle(Point& origin, Point& pa, Point& pb); + + /** + * + * @param node - middle node + * @return the angle between 3 front nodes + */ + double HoleAngle(Node& node); + + /** + * The basin angle is decided against the horizontal line [1,0] + */ + double BasinAngle(Node& node); + + /** + * Fills a basin that has formed on the Advancing Front to the right + * of given node.
+ * First we decide a left,bottom and right node that forms the + * boundaries of the basin. Then we do a reqursive fill. + * + * @param tcx + * @param node - starting node, this or next node will be left node + */ + void FillBasin(SweepContext& tcx, Node& node); + + /** + * Recursive algorithm to fill a Basin with triangles + * + * @param tcx + * @param node - bottom_node + * @param cnt - counter used to alternate on even and odd numbers + */ + void FillBasinReq(SweepContext& tcx, Node* node); + + bool IsShallow(SweepContext& tcx, Node& node); + + bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq); + + void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + + void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + + void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + + void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p); + + /** + * After a flip we have two triangles and know that only one will still be + * intersecting the edge. So decide which to contiune with and legalize the other + * + * @param tcx + * @param o - should be the result of an orient2d( eq, op, ep ) + * @param t - triangle 1 + * @param ot - triangle 2 + * @param p - a point shared by both triangles + * @param op - another point shared by both triangles + * @return returns the triangle still intersecting the edge + */ + Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op); + + /** + * When we need to traverse from one triangle to the next we need + * the point in current triangle that is the opposite point to the next + * triangle. + * + * @param ep + * @param eq + * @param ot + * @param op + * @return + */ + Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op); + + /** + * Scan part of the FlipScan algorithm
+ * When a triangle pair isn't flippable we will scan for the next + * point that is inside the flip triangle scan area. When found + * we generate a new flipEdgeEvent + * + * @param tcx + * @param ep - last point on the edge we are traversing + * @param eq - first point on the edge we are traversing + * @param flipTriangle - the current triangle sharing the point eq with edge + * @param t + * @param p + */ + void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p); + + void FinalizationPolygon(SweepContext& tcx); + + std::vector nodes_; + +}; + +} + +#endif diff --git a/src/3rdparty/poly2tri/sweep/sweep_context.cpp b/src/3rdparty/poly2tri/sweep/sweep_context.cpp new file mode 100644 index 0000000..24dde11 --- /dev/null +++ b/src/3rdparty/poly2tri/sweep/sweep_context.cpp @@ -0,0 +1,216 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "sweep_context.h" +#include +#include "advancing_front.h" + +namespace p2t { + +SweepContext::SweepContext(std::vector polyline) : + front_(0), + head_(0), + tail_(0), + af_head_(0), + af_middle_(0), + af_tail_(0) +{ + basin = Basin(); + edge_event = EdgeEvent(); + + points_ = polyline; + + InitEdges(points_); +} + +void SweepContext::AddHole(std::vector polyline) +{ + InitEdges(polyline); + for (unsigned int i = 0; i < polyline.size(); i++) { + points_.push_back(polyline[i]); + } +} + +void SweepContext::AddPoint(Point* point) { + points_.push_back(point); +} + +std::vector SweepContext::GetTriangles() +{ + return triangles_; +} + +std::list SweepContext::GetMap() +{ + return map_; +} + +void SweepContext::InitTriangulation() +{ + double xmax(points_[0]->x), xmin(points_[0]->x); + double ymax(points_[0]->y), ymin(points_[0]->y); + + // Calculate bounds. + for (unsigned int i = 0; i < points_.size(); i++) { + Point& p = *points_[i]; + if (p.x > xmax) + xmax = p.x; + if (p.x < xmin) + xmin = p.x; + if (p.y > ymax) + ymax = p.y; + if (p.y < ymin) + ymin = p.y; + } + + double dx = kAlpha * (xmax - xmin); + double dy = kAlpha * (ymax - ymin); + head_ = new Point(xmax + dx, ymin - dy); + tail_ = new Point(xmin - dx, ymin - dy); + + // Sort points along y-axis + std::sort(points_.begin(), points_.end(), cmp); + +} + +void SweepContext::InitEdges(std::vector polyline) +{ + int num_points = polyline.size(); + for (int i = 0; i < num_points; i++) { + int j = i < num_points - 1 ? i + 1 : 0; + edge_list.push_back(new Edge(*polyline[i], *polyline[j])); + } +} + +Point* SweepContext::GetPoint(const int& index) +{ + return points_[index]; +} + +void SweepContext::AddToMap(Triangle* triangle) +{ + map_.push_back(triangle); +} + +Node& SweepContext::LocateNode(Point& point) +{ + // TODO implement search tree + return *front_->LocateNode(point.x); +} + +void SweepContext::CreateAdvancingFront(std::vector nodes) +{ + + (void) nodes; + // Initial triangle + Triangle* triangle = new Triangle(*points_[0], *tail_, *head_); + + map_.push_back(triangle); + + af_head_ = new Node(*triangle->GetPoint(1), *triangle); + af_middle_ = new Node(*triangle->GetPoint(0), *triangle); + af_tail_ = new Node(*triangle->GetPoint(2)); + front_ = new AdvancingFront(*af_head_, *af_tail_); + + // TODO: More intuitive if head is middles next and not previous? + // so swap head and tail + af_head_->next = af_middle_; + af_middle_->next = af_tail_; + af_middle_->prev = af_head_; + af_tail_->prev = af_middle_; +} + +void SweepContext::RemoveNode(Node* node) +{ + delete node; +} + +void SweepContext::MapTriangleToNodes(Triangle& t) +{ + for (int i = 0; i < 3; i++) { + if (!t.GetNeighbor(i)) { + Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i))); + if (n) + n->triangle = &t; + } + } +} + +void SweepContext::RemoveFromMap(Triangle* triangle) +{ + map_.remove(triangle); +} + +void SweepContext::MeshClean(Triangle& triangle) +{ + std::vector triangles; + triangles.push_back(&triangle); + + while(!triangles.empty()){ + Triangle *t = triangles.back(); + triangles.pop_back(); + + if (t != NULL && !t->IsInterior()) { + t->IsInterior(true); + triangles_.push_back(t); + for (int i = 0; i < 3; i++) { + if (!t->constrained_edge[i]) + triangles.push_back(t->GetNeighbor(i)); + } + } + } +} + +SweepContext::~SweepContext() +{ + + // Clean up memory + + delete head_; + delete tail_; + delete front_; + delete af_head_; + delete af_middle_; + delete af_tail_; + + typedef std::list type_list; + + for (type_list::iterator iter = map_.begin(); iter != map_.end(); ++iter) { + Triangle* ptr = *iter; + delete ptr; + } + + for (unsigned int i = 0; i < edge_list.size(); i++) { + delete edge_list[i]; + } + +} + +} diff --git a/src/3rdparty/poly2tri/sweep/sweep_context.h b/src/3rdparty/poly2tri/sweep/sweep_context.h new file mode 100644 index 0000000..c110a74 --- /dev/null +++ b/src/3rdparty/poly2tri/sweep/sweep_context.h @@ -0,0 +1,186 @@ +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SWEEP_CONTEXT_H +#define SWEEP_CONTEXT_H + +#include +#include +#include + +namespace p2t { + +// Initial triangle factor, seed triangle will extend 30% of +// PointSet width to both left and right. +const double kAlpha = 0.3; + +struct Point; +class Triangle; +struct Node; +struct Edge; +class AdvancingFront; + +class SweepContext { +public: + +/// Constructor +SweepContext(std::vector polyline); +/// Destructor +~SweepContext(); + +void set_head(Point* p1); + +Point* head(); + +void set_tail(Point* p1); + +Point* tail(); + +int point_count(); + +Node& LocateNode(Point& point); + +void RemoveNode(Node* node); + +void CreateAdvancingFront(std::vector nodes); + +/// Try to map a node to all sides of this triangle that don't have a neighbor +void MapTriangleToNodes(Triangle& t); + +void AddToMap(Triangle* triangle); + +Point* GetPoint(const int& index); + +Point* GetPoints(); + +void RemoveFromMap(Triangle* triangle); + +void AddHole(std::vector polyline); + +void AddPoint(Point* point); + +AdvancingFront* front(); + +void MeshClean(Triangle& triangle); + +std::vector GetTriangles(); +std::list GetMap(); + +std::vector edge_list; + +struct Basin { + Node* left_node; + Node* bottom_node; + Node* right_node; + double width; + bool left_highest; + + Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false) + { + } + + void Clear() + { + left_node = NULL; + bottom_node = NULL; + right_node = NULL; + width = 0.0; + left_highest = false; + } +}; + +struct EdgeEvent { + Edge* constrained_edge; + bool right; + + EdgeEvent() : constrained_edge(NULL), right(false) + { + } +}; + +Basin basin; +EdgeEvent edge_event; + +private: + +friend class Sweep; + +std::vector triangles_; +std::list map_; +std::vector points_; + +// Advancing front +AdvancingFront* front_; +// head point used with advancing front +Point* head_; +// tail point used with advancing front +Point* tail_; + +Node *af_head_, *af_middle_, *af_tail_; + +void InitTriangulation(); +void InitEdges(std::vector polyline); + +}; + +inline AdvancingFront* SweepContext::front() +{ + return front_; +} + +inline int SweepContext::point_count() +{ + return int(points_.size()); +} + +inline void SweepContext::set_head(Point* p1) +{ + head_ = p1; +} + +inline Point* SweepContext::head() +{ + return head_; +} + +inline void SweepContext::set_tail(Point* p1) +{ + tail_ = p1; +} + +inline Point* SweepContext::tail() +{ + return tail_; +} + +} + +#endif diff --git a/src/3rdparty/poly2tri_legal.qdoc b/src/3rdparty/poly2tri_legal.qdoc new file mode 100644 index 0000000..acbb264 --- /dev/null +++ b/src/3rdparty/poly2tri_legal.qdoc @@ -0,0 +1,37 @@ +/*! +\page legal-poly2tri.html +\title Poly2Tri Polygon Triangulation Library +\ingroup licensing + +\legalese +\code +Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +http://code.google.com/p/poly2tri/ + +All rights reserved. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of Poly2Tri nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\endcode +\endlegalese +*/ diff --git a/src/imports/imports.pro b/src/imports/imports.pro new file mode 100644 index 0000000..460fe15 --- /dev/null +++ b/src/imports/imports.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +qtHaveModule(positioning): SUBDIRS += positioning +qtHaveModule(location): SUBDIRS += location + diff --git a/src/imports/location/declarativeplaces/declarativeplaces.pri b/src/imports/location/declarativeplaces/declarativeplaces.pri new file mode 100644 index 0000000..b580ee4 --- /dev/null +++ b/src/imports/location/declarativeplaces/declarativeplaces.pri @@ -0,0 +1,50 @@ +INCLUDEPATH *= $$PWD +SOURCES += \ +#models + declarativeplaces/qdeclarativeplacecontentmodel.cpp \ + declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp \ + declarativeplaces/qdeclarativesearchsuggestionmodel.cpp \ + declarativeplaces/qdeclarativesearchresultmodel.cpp \ + declarativeplaces/qdeclarativereviewmodel.cpp \ + declarativeplaces/qdeclarativeplaceimagemodel.cpp \ + declarativeplaces/qdeclarativeplaceeditorialmodel.cpp \ +#data + declarativeplaces/qdeclarativecontactdetail.cpp \ + declarativeplaces/qdeclarativecategory.cpp \ + declarativeplaces/qdeclarativeplace.cpp \ + declarativeplaces/qdeclarativeplaceattribute.cpp \ + declarativeplaces/qdeclarativeplaceicon.cpp \ + declarativeplaces/qdeclarativeplaceuser.cpp \ + declarativeplaces/qdeclarativeratings.cpp \ + declarativeplaces/qdeclarativesupplier.cpp \ + declarativeplaces/qdeclarativesearchmodelbase.cpp + +HEADERS += \ +#models + declarativeplaces/qdeclarativeplacecontentmodel.h \ + declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h \ + declarativeplaces/qdeclarativesearchsuggestionmodel_p.h \ + declarativeplaces/qdeclarativesearchresultmodel_p.h \ + declarativeplaces/qdeclarativereviewmodel_p.h \ + declarativeplaces/qdeclarativeplaceimagemodel_p.h \ + declarativeplaces/qdeclarativeplaceeditorialmodel.h \ +#data + declarativeplaces/qdeclarativecontactdetail_p.h \ + declarativeplaces/qdeclarativecategory_p.h \ + declarativeplaces/qdeclarativeplace_p.h \ + declarativeplaces/qdeclarativeplaceattribute_p.h \ + declarativeplaces/qdeclarativeplaceicon_p.h \ + declarativeplaces/qdeclarativeplaceuser_p.h \ + declarativeplaces/qdeclarativeratings_p.h \ + declarativeplaces/qdeclarativesupplier_p.h \ + declarativeplaces/qdeclarativesearchmodelbase.h + + + + + + + + + + diff --git a/src/imports/location/declarativeplaces/qdeclarativecategory.cpp b/src/imports/location/declarativeplaces/qdeclarativecategory.cpp new file mode 100644 index 0000000..ae496c1 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativecategory.cpp @@ -0,0 +1,456 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativecategory_p.h" +#include "qdeclarativeplaceicon_p.h" +#include "qdeclarativegeoserviceprovider_p.h" +#include "error_messages.h" + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +/*! + \qmltype Category + \instantiates QDeclarativeCategory + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + + \since Qt Location 5.5 + + \brief The Category type represents a category that a \l Place can be associated with. + + Categories are used to search for places based on the categories they are associated with. The + list of available categories can be obtained from the \l CategoryModel. The + \l PlaceSearchModel has a \l {PlaceSearchModel::categories}{categories} property that is used + to limit the search results to places with the specified categories. + + If the \l Plugin supports it, categories can be created or removed. To create a new category + construct a new Category object and set its properties, then invoke the \l save() method. + + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml Category + \dots 0 + \snippet declarative/places.qml Category save + + To remove a category ensure that the \l plugin and categoryId properties are set and call the + \l remove() method. + + \sa CategoryModel +*/ + +QDeclarativeCategory::QDeclarativeCategory(QObject *parent) +: QObject(parent), m_icon(0), m_plugin(0), m_reply(0), m_complete(false), m_status(Ready) +{ +} + +QDeclarativeCategory::QDeclarativeCategory(const QPlaceCategory &category, + QDeclarativeGeoServiceProvider *plugin, + QObject *parent) +: QObject(parent), m_category(category), m_icon(0), m_plugin(plugin), m_reply(0), + m_complete(false), m_status(Ready) +{ + setCategory(category); +} + +QDeclarativeCategory::~QDeclarativeCategory() {} + +// From QQmlParserStatus +void QDeclarativeCategory::componentComplete() +{ + // delayed instantiation of QObject based properties. + if (!m_icon) { + m_icon = new QDeclarativePlaceIcon(this); + m_icon->setPlugin(m_plugin); + } + + m_complete = true; +} + +/*! + \qmlproperty Plugin Category::plugin + + This property holds the location based service to which the category belongs. +*/ +void QDeclarativeCategory::setPlugin(QDeclarativeGeoServiceProvider *plugin) +{ + if (m_plugin == plugin) + return; + + m_plugin = plugin; + if (m_complete) + emit pluginChanged(); + + if (m_icon && m_icon->parent() == this && !m_icon->plugin()) + m_icon->setPlugin(m_plugin); + + if (!m_plugin) + return; + + if (m_plugin->isAttached()) { + pluginReady(); + } else { + connect(m_plugin, SIGNAL(attached()), + this, SLOT(pluginReady())); + } +} + +QDeclarativeGeoServiceProvider *QDeclarativeCategory::plugin() const +{ + return m_plugin; +} + +/*! + \internal +*/ +void QDeclarativeCategory::pluginReady() +{ + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (!placeManager || serviceProvider->error() != QGeoServiceProvider::NoError) { + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR) + .arg(m_plugin->name()).arg(serviceProvider->errorString())); + return; + } +} + + +/*! + \qmlproperty QPlaceCategory Category::category + \keyword Category::category + + For details on how to use this property to interface between C++ and QML see + "\l {Category - QPlaceCategory} {Interfaces between C++ and QML Code}". +*/ +void QDeclarativeCategory::setCategory(const QPlaceCategory &category) +{ + QPlaceCategory previous = m_category; + m_category = category; + + if (category.name() != previous.name()) + emit nameChanged(); + + if (category.categoryId() != previous.categoryId()) + emit categoryIdChanged(); + + if (m_icon && m_icon->parent() == this) { + m_icon->setPlugin(m_plugin); + m_icon->setIcon(m_category.icon()); + } else if (!m_icon || m_icon->parent() != this) { + m_icon = new QDeclarativePlaceIcon(m_category.icon(), m_plugin, this); + emit iconChanged(); + } +} + +QPlaceCategory QDeclarativeCategory::category() +{ + m_category.setIcon(m_icon ? m_icon->icon() : QPlaceIcon()); + return m_category; +} + +/*! + \qmlproperty string Category::categoryId + + This property holds the identifier of the category. The categoryId is a string which uniquely + identifies this category within the categories \l plugin. +*/ +void QDeclarativeCategory::setCategoryId(const QString &id) +{ + if (m_category.categoryId() != id) { + m_category.setCategoryId(id); + emit categoryIdChanged(); + } +} + +QString QDeclarativeCategory::categoryId() const +{ + return m_category.categoryId(); +} + +/*! + \qmlproperty string Category::name + + This property holds string based name of the category. +*/ +void QDeclarativeCategory::setName(const QString &name) +{ + if (m_category.name() != name) { + m_category.setName(name); + emit nameChanged(); + } +} + +QString QDeclarativeCategory::name() const +{ + return m_category.name(); +} + +/*! + \qmlproperty enumeration Category::visibility + + This property holds the visibility of the category. It can be one of: + + \table + \row + \li Category.UnspecifiedVisibility + \li The visibility of the category is unspecified. If saving a category, the + plugin will automatically set a default visibility to the category saved in the backend. + This default is dependent on the plugin implementation. + \row + \li Category.DeviceVisibility + \li The category is limited to the current device. The category will not be transferred + off of the device. + \row + \li Category.PrivateVisibility + \li The category is private to the current user. The category may be transferred to an + online service but is only ever visible to the current user. + \row + \li Category.PublicVisibility + \li The category is public. + \endtable + + Note that visibility does not affect how \l{Place}s associated with + the category are displayed in the user-interface of an application + on the device. Instead, it defines the sharing semantics of the + category. +*/ +QDeclarativeCategory::Visibility QDeclarativeCategory::visibility() const +{ + return static_cast(m_category.visibility()); +} + +void QDeclarativeCategory::setVisibility(Visibility visibility) +{ + if (static_cast(m_category.visibility()) == visibility) + return; + + m_category.setVisibility(static_cast(visibility)); + emit visibilityChanged(); +} + +/*! + \qmlproperty PlaceIcon Category::icon + + This property holds the image source associated with the category. To display the icon you can use + the \l Image type. +*/ +QDeclarativePlaceIcon *QDeclarativeCategory::icon() const +{ + return m_icon; +} + +void QDeclarativeCategory::setIcon(QDeclarativePlaceIcon *icon) +{ + if (m_icon == icon) + return; + + if (m_icon && m_icon->parent() == this) + delete m_icon; + + m_icon = icon; + emit iconChanged(); +} + +/*! + \qmlmethod string Category::errorString() + + Returns a string description of the error of the last operation. + If the last operation completed successfully then the string is empty. +*/ +QString QDeclarativeCategory::errorString() const +{ + return m_errorString; +} + +void QDeclarativeCategory::setStatus(Status status, const QString &errorString) +{ + Status originalStatus = m_status; + m_status = status; + m_errorString = errorString; + + if (originalStatus != m_status) + emit statusChanged(); +} + +/*! + \qmlproperty enumeration Category::status + + This property holds the status of the category. It can be one of: + + \table + \row + \li Category.Ready + \li No error occurred during the last operation, further operations may be performed on + the category. + \row + \li Category.Saving + \li The category is currently being saved, no other operations may be performed until the + current operation completes. + \row + \li Category.Removing + \li The category is currently being removed, no other operations can be performed until + the current operation completes. + \row + \li Category.Error + \li An error occurred during the last operation, further operations can still be + performed on the category. + \endtable +*/ +QDeclarativeCategory::Status QDeclarativeCategory::status() const +{ + return m_status; +} + +/*! + \qmlmethod void Category::save() + + This method saves the category to the backend service. +*/ +void QDeclarativeCategory::save(const QString &parentId) +{ + QPlaceManager *placeManager = manager(); + if (!placeManager) + return; + + m_reply = placeManager->saveCategory(category(), parentId); + connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); + setStatus(QDeclarativeCategory::Saving); +} + +/*! + \qmlmethod void Category::remove() + + This method permanently removes the category from the backend service. +*/ +void QDeclarativeCategory::remove() +{ + QPlaceManager *placeManager = manager(); + if (!placeManager) + return; + + m_reply = placeManager->removeCategory(m_category.categoryId()); + connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); + setStatus(QDeclarativeCategory::Removing); +} + +/*! + \internal +*/ +void QDeclarativeCategory::replyFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() == QPlaceReply::NoError) { + switch (m_reply->type()) { + case (QPlaceReply::IdReply) : { + QPlaceIdReply *idReply = qobject_cast(m_reply); + + switch (idReply->operationType()) { + case QPlaceIdReply::SaveCategory: + setCategoryId(idReply->id()); + break; + case QPlaceIdReply::RemoveCategory: + setCategoryId(QString()); + break; + default: + //Other operation types shouldn't ever be received. + break; + } + break; + } + default: + //other types of replies shouldn't ever be received. + break; + } + + m_errorString.clear(); + + m_reply->deleteLater(); + m_reply = 0; + + setStatus(QDeclarativeCategory::Ready); + } else { + QString errorString = m_reply->errorString(); + + m_reply->deleteLater(); + m_reply = 0; + + setStatus(QDeclarativeCategory::Error, errorString); + } +} + +/*! + \internal + Helper function to return the manager, this manager is intended to be used to perform the next + operation. Sets status to Error and an appropriate m_errorString if the manager cannot be + obtained. +*/ +QPlaceManager *QDeclarativeCategory::manager() +{ + if (m_status != QDeclarativeCategory::Ready && m_status != QDeclarativeCategory::Error) + return 0; + + if (m_reply) { + m_reply->abort(); + m_reply->deleteLater(); + m_reply = 0; + } + + if (!m_plugin) { + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROPERTY_NOT_SET)); + return 0; + } + + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (!serviceProvider) { + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_NOT_VALID)); + return 0; + } + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (!placeManager) { + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR) + .arg(m_plugin->name()).arg(serviceProvider->errorString())); + return 0; + } + + return placeManager; +} diff --git a/src/imports/location/declarativeplaces/qdeclarativecategory_p.h b/src/imports/location/declarativeplaces/qdeclarativecategory_p.h new file mode 100644 index 0000000..63b255b --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativecategory_p.h @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVECATEGORY_P_H +#define QDECLARATIVECATEGORY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include + +#include "qdeclarativegeoserviceprovider_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativePlaceIcon; +class QPlaceReply; +class QPlaceManager; + +class QDeclarativeCategory : public QObject, public QQmlParserStatus +{ + Q_OBJECT + + Q_ENUMS(Status Visibility) + + + Q_PROPERTY(QPlaceCategory category READ category WRITE setCategory) + Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) + Q_PROPERTY(QString categoryId READ categoryId WRITE setCategoryId NOTIFY categoryIdChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) + Q_PROPERTY(QDeclarativePlaceIcon *icon READ icon WRITE setIcon NOTIFY iconChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + + Q_INTERFACES(QQmlParserStatus) + +public: + explicit QDeclarativeCategory(QObject *parent = 0); + QDeclarativeCategory(const QPlaceCategory &category, QDeclarativeGeoServiceProvider *plugin, QObject *parent = 0); + ~QDeclarativeCategory(); + + enum Visibility { + UnspecifiedVisibility = QLocation::UnspecifiedVisibility, + DeviceVisibility = QLocation::DeviceVisibility, + PrivateVisibility = QLocation::PrivateVisibility, + PublicVisibility = QLocation::PublicVisibility + }; + enum Status {Ready, Saving, Removing, Error}; + + //From QQmlParserStatus + virtual void classBegin() {} + virtual void componentComplete(); + + void setPlugin(QDeclarativeGeoServiceProvider *plugin); + QDeclarativeGeoServiceProvider *plugin() const; + + QPlaceCategory category(); + void setCategory(const QPlaceCategory &category); + + QString categoryId() const; + void setCategoryId(const QString &catID); + QString name() const; + void setName(const QString &name); + + Visibility visibility() const; + void setVisibility(Visibility visibility); + + QDeclarativePlaceIcon *icon() const; + void setIcon(QDeclarativePlaceIcon *icon); + + Q_INVOKABLE QString errorString() const; + + Status status() const; + void setStatus(Status status, const QString &errorString = QString()); + + Q_INVOKABLE void save(const QString &parentId = QString()); + Q_INVOKABLE void remove(); + +Q_SIGNALS: + void pluginChanged(); + void categoryIdChanged(); + void nameChanged(); + void visibilityChanged(); + void iconChanged(); + void statusChanged(); + +private Q_SLOTS: + void replyFinished(); + void pluginReady(); + +private: + QPlaceManager *manager(); + + QPlaceCategory m_category; + QDeclarativePlaceIcon *m_icon; + QDeclarativeGeoServiceProvider *m_plugin; + QPlaceReply *m_reply; + bool m_complete; + Status m_status; + QString m_errorString; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeCategory) + +#endif // QDECLARATIVECATEGORY_P_H diff --git a/src/imports/location/declarativeplaces/qdeclarativecontactdetail.cpp b/src/imports/location/declarativeplaces/qdeclarativecontactdetail.cpp new file mode 100644 index 0000000..c16c201 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativecontactdetail.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativecontactdetail_p.h" + +/*! + \qmltype ContactDetails + \instantiates QDeclarativeContactDetails + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + \since Qt Location 5.5 + + \brief The ContactDetails type holds contact details for a \l Place. + + The ContactDetails type is a map of \l {QtLocation::ContactDetail}{ContactDetail} objects. + To access contact details in the map use the \l keys() method to get the list of keys stored in + the map and then use the \c {[]} operator to access the + \l {QtLocation::ContactDetail}{ContactDetail} items. + + The following keys are defined in the API. \l Plugin implementations are free to define + additional keys. + + \list + \li phone + \li fax + \li email + \li website + \endlist + + ContactDetails instances are only ever used in the context of \l {Place}{Places}. It is not possible + to create a ContactDetails instance directly or re-assign ContactDetails instances to \l {Place}{Places}. + Modification of ContactDetails can only be accomplished via Javascript. + + \section1 Examples + + The following example shows how to access all \l {QtLocation::ContactDetail}{ContactDetails} + and print them to the console: + + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml ContactDetails read + + The returned list of contact details is an \l {QObjectList-based model}{object list} and so can be used directly as a data model. For example, the + following demonstrates how to display a list of contact phone numbers in a list view: + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml ContactDetails phoneList + + The following example demonstrates how to assign a single phone number to a place in JavaScript: + \snippet declarative/places.qml ContactDetails write single + + The following demonstrates how to assign multiple phone numbers to a place in JavaScript: + \snippet declarative/places.qml ContactDetails write multiple +*/ + +/*! + \qmlmethod variant ContactDetails::keys() + + Returns an array of contact detail keys currently stored in the map. +*/ +QDeclarativeContactDetails::QDeclarativeContactDetails(QObject *parent) + : QQmlPropertyMap(parent) +{ +} + +QVariant QDeclarativeContactDetails::updateValue(const QString &, const QVariant &input) +{ + if (input.userType() == QMetaType::QObjectStar) { + QDeclarativeContactDetail *detail = + qobject_cast(input.value()); + if (detail) { + QVariantList varList; + varList.append(input); + return varList; + } + } + + return input; +} + +/*! + \qmltype ContactDetail + \instantiates QDeclarativeContactDetail + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + \since Qt Location 5.5 + + \brief The ContactDetail type holds a contact detail such as a phone number or a website + address. + + The ContactDetail provides a single detail on how one could contact a \l Place. The + ContactDetail consists of a \l label, which is a localized string describing the contact + method, and a \l value representing the actual contact detail. + + \section1 Examples + + The following example demonstrates how to assign a single phone number to a place in JavaScript: + \snippet declarative/places.qml ContactDetails write single + + The following demonstrates how to assign multiple phone numbers to a place in JavaScript: + \snippet declarative/places.qml ContactDetails write multiple + + Note, due to limitations of the QQmlPropertyMap, it is not possible + to declaratively specify the contact details in QML, it can only be accomplished + via JavaScript. +*/ +QDeclarativeContactDetail::QDeclarativeContactDetail(QObject *parent) + : QObject(parent) +{ +} + +QDeclarativeContactDetail::QDeclarativeContactDetail(const QPlaceContactDetail &src, QObject *parent) + : QObject(parent), m_contactDetail(src) +{ +} + +QDeclarativeContactDetail::~QDeclarativeContactDetail() +{ +} + +/*! + \qmlproperty QPlaceContactDetail QtLocation::ContactDetail::contactDetail + + For details on how to use this property to interface between C++ and QML see + "\l {ContactDetail - QDeclarativeContactDetail} {Interfaces between C++ and QML Code}". +*/ +void QDeclarativeContactDetail::setContactDetail(const QPlaceContactDetail &src) +{ + QPlaceContactDetail prevContactDetail = m_contactDetail; + m_contactDetail = src; + + if (m_contactDetail.label() != prevContactDetail.label()) + emit labelChanged(); + if (m_contactDetail.value() != prevContactDetail.value()) + emit valueChanged(); +} + +QPlaceContactDetail QDeclarativeContactDetail::contactDetail() const +{ + return m_contactDetail; +} + +/*! + \qmlproperty string QtLocation::ContactDetail::label + + This property holds a label describing the contact detail. + + The label can potentially be localized. The language is dependent on the entity that sets it, + typically this is the \l {Plugin}. The \l {Plugin::locales} property defines + what language is used. +*/ +QString QDeclarativeContactDetail::label() const +{ + return m_contactDetail.label(); +} + +void QDeclarativeContactDetail::setLabel(const QString &label) +{ + if (m_contactDetail.label() != label) { + m_contactDetail.setLabel(label); + emit labelChanged(); + } +} + +/*! + \qmlproperty string QtLocation::ContactDetail::value + + This property holds the value of the contact detail which may be a phone number, an email + address, a website url and so on. +*/ +QString QDeclarativeContactDetail::value() const +{ + return m_contactDetail.value(); +} + +void QDeclarativeContactDetail::setValue(const QString &value) +{ + if (m_contactDetail.value() != value) { + m_contactDetail.setValue(value); + emit valueChanged(); + } +} diff --git a/src/imports/location/declarativeplaces/qdeclarativecontactdetail_p.h b/src/imports/location/declarativeplaces/qdeclarativecontactdetail_p.h new file mode 100644 index 0000000..9d404de --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativecontactdetail_p.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVECONTACTDETAIL_P_H +#define QDECLARATIVECONTACTDETAIL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeContactDetails : public QQmlPropertyMap +{ + Q_OBJECT + +public: + explicit QDeclarativeContactDetails(QObject *parent = 0); + virtual QVariant updateValue(const QString &key, const QVariant &input); +}; + +class QDeclarativeContactDetail : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPlaceContactDetail contactDetail READ contactDetail WRITE setContactDetail) + Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged) + Q_PROPERTY(QString value READ value WRITE setValue NOTIFY valueChanged) + +public: + explicit QDeclarativeContactDetail(QObject *parent = 0); + explicit QDeclarativeContactDetail(const QPlaceContactDetail &src, QObject *parent = 0); + ~QDeclarativeContactDetail(); + + QPlaceContactDetail contactDetail() const; + void setContactDetail(const QPlaceContactDetail &contactDetail); + + QString label() const; + void setLabel(const QString &label); + + QString value() const; + void setValue(const QString &value); + +Q_SIGNALS: + void labelChanged(); + void valueChanged(); + +private: + QPlaceContactDetail m_contactDetail; + +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeContactDetail) + +#endif diff --git a/src/imports/location/declarativeplaces/qdeclarativeperiod_p.h b/src/imports/location/declarativeplaces/qdeclarativeperiod_p.h new file mode 100644 index 0000000..3ded010 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeperiod_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPERIOD_P_H +#define QDECLARATIVEPERIOD_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativePeriod : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QDate startDate READ startDate WRITE setStartDate NOTIFY startDateChanged) + Q_PROPERTY(QTime startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged) + Q_PROPERTY(QDate endDate READ endDate WRITE setEndDate NOTIFY endDateChanged) + Q_PROPERTY(QTime endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged) + +public: + explicit QDeclarativePeriod(QObject *parent = 0); + explicit QDeclarativePeriod(const QPlacePeriod &period, QObject *parent = 0); + ~QDeclarativePeriod(); + + QPlacePeriod period() const; + void setPeriod(const QPlacePeriod &period); + + QDate startDate() const; + void setStartDate(const QDate &data); + QTime startTime() const; + void setStartTime(const QTime &data); + QDate endDate() const; + void setEndDate(const QDate &data); + QTime endTime() const; + void setEndTime(const QTime &data); + +Q_SIGNALS: + void startDateChanged(); + void startTimeChanged(); + void endDateChanged(); + void endTimeChanged(); + +private: + QPlacePeriod m_period; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativePeriod)); + +#endif // QDECLARATIVEPERIOD_P_H diff --git a/src/imports/location/declarativeplaces/qdeclarativeplace.cpp b/src/imports/location/declarativeplaces/qdeclarativeplace.cpp new file mode 100644 index 0000000..69ded2d --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplace.cpp @@ -0,0 +1,1227 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeplace_p.h" +#include "qdeclarativecontactdetail_p.h" +#include "qdeclarativegeoserviceprovider_p.h" +#include "qdeclarativeplaceattribute_p.h" +#include "qdeclarativeplaceicon_p.h" +#include "error_messages.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +/*! + \qmltype Place + \instantiates QDeclarativePlace + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + \since Qt Location 5.5 + + \brief The Place type represents a location that is a position of interest. + + The Place type represents a physical location with additional metadata describing that + location. Contrasted with \l Location, \l Address, and + \l {coordinate} type which are used to describe where a location is. + The basic properties of a Place are its \l name and \l location. + + Place objects are typically obtained from a search model and will generally only have their + basic properties set. The \l detailsFetched property can be used to test if further property + values need to be fetched from the \l Plugin. This can be done by invoking the \l getDetails() + method. Progress of the fetching operation can be monitored with the \l status property, which + will be set to Place.Fetching when the details are being fetched. + + The Place type has many properties holding information about the location. Details on how to + contact the place are available from the \l contactDetails property. Convenience properties + for obtaining the primary \l {primaryPhone}{phone}, \l {primaryFax}{fax}, + \l {primaryEmail}{email} and \l {primaryWebsite}{website} are also available. + + Each place is assigned zero or more \l categories. Categories are typically used when + searching for a particular kind of place, such as a restaurant or hotel. Some places have a + \l ratings object, which gives an indication of the quality of the place. + + Place metadata is provided by a \l supplier who may require that an \l attribution message be + displayed to the user when the place details are viewed. + + Places have an associated \l icon which can be used to represent a place on a map or to + decorate a delegate in a view. + + Places may have additional rich content associated with them. The currently supported rich + content include editorial descriptions, reviews and images. These are exposed as a set of + models for retrieving the content. Editorial descriptions of the place are available from the + \l editorialModel property. Reviews of the place are available from the \l reviewModel + property. A gallery of pictures of the place can be accessed using the \l imageModel property. + + Places may have additional attributes which are not covered in the formal API. The + \l extendedAttributes property provides access to these. The type of extended attributes + available is specific to each \l Plugin. + + A Place is almost always tied to a \l plugin. The \l plugin property must be set before it is + possible to call \l save(), \l remove() or \l getDetails(). The \l reviewModel, \l imageModel + and \l editorialModel are only valid then the \l plugin property is set. + + \section2 Saving a Place + + If the \l Plugin supports it, the Place type can be used to save a place. First create a new + Place and set its properties: + + \snippet declarative/places.qml Place savePlace def + + Then invoke the \l save() method: + + \snippet declarative/places.qml Place savePlace + + The \l status property will change to Place.Saving and then to Place.Ready if the save was + successful or to Place.Error if an error occurs. + + If the \l placeId property is set, the backend will update an existing place otherwise it will + create a new place. On success the \l placeId property will be updated with the identifier of the newly + saved place. + + \section3 Caveats + \input place-caveats.qdocinc + + \section3 Saving Between Plugins + When saving places between plugins, there are a few things to be aware of. + Some fields of a place such as the id, categories and icons are plugin specific entities. For example + the categories in one manager may not be recognised in another. + Therefore trying to save a place directly from one plugin to another is not possible. + + It is generally recommended that saving across plugins be handled as saving \l {Favorites}{favorites} + as explained in the Favorites section. However there is another approach which is to create a new place, + set its (destination) plugin and then use the \l copyFrom() method to copy the details of the original place. + Using \l copyFrom() only copies data that is supported by the destination plugin, + plugin specific data such as the place identifier is not copied over. Once the copy is done, + the place is in a suitable state to be saved. + + The following snippet provides an example of saving a place to a different plugin + using the \l copyFrom method: + + \snippet declarative/places.qml Place save to different plugin + + \section2 Removing a Place + + To remove a place, ensure that a Place object with a valid \l placeId property exists and call + its \l remove() method. The \l status property will change to Place.Removing and then to + Place.Ready if the save was successful or to Place.Error if an error occurs. + + \section2 Favorites + The Places API supports the concept of favorites. Favorites are generally implemented + by using two plugins, the first plugin is typically a read-only source of places (origin plugin) and a second + read/write plugin (destination plugin) is used to store places from the origin as favorites. + + Each Place has a favorite property which is intended to contain the corresponding place + from the destination plugin (the place itself is sourced from the origin plugin). Because both the original + place and favorite instances are available, the developer can choose which + properties to show to the user. For example the favorite may have a modified name which should + be displayed rather than the original name. + + \snippet declarative/places.qml Place favorite + + The following demonstrates how to save a new favorite instance. A call is made + to create/initialize the favorite instance and then the instance is saved. + + \snippet declarative/places.qml Place saveFavorite + + The following demonstrates favorite removal: + + \snippet declarative/places.qml Place removeFavorite 1 + \dots + \snippet declarative/places.qml Place removeFavorite 2 + + The PlaceSearchModel has a favoritesPlugin property. If the property is set, any places found + during a search are checked against the favoritesPlugin to see if there is a corresponding + favorite place. If so, the favorite property of the Place is set, otherwise the favorite + property is remains null. + + \sa PlaceSearchModel +*/ + +QDeclarativePlace::QDeclarativePlace(QObject *parent) +: QObject(parent), m_location(0), m_ratings(0), m_supplier(0), m_icon(0), + m_reviewModel(0), m_imageModel(0), m_editorialModel(0), + m_extendedAttributes(new QQmlPropertyMap(this)), + m_contactDetails(new QDeclarativeContactDetails(this)), m_reply(0), m_plugin(0), + m_complete(false), m_favorite(0), m_status(QDeclarativePlace::Ready) +{ + connect(m_contactDetails, SIGNAL(valueChanged(QString,QVariant)), + this, SLOT(contactsModified(QString,QVariant))); + + setPlace(QPlace()); +} + +QDeclarativePlace::QDeclarativePlace(const QPlace &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent) +: QObject(parent), m_location(0), m_ratings(0), m_supplier(0), m_icon(0), + m_reviewModel(0), m_imageModel(0), m_editorialModel(0), + m_extendedAttributes(new QQmlPropertyMap(this)), + m_contactDetails(new QDeclarativeContactDetails(this)), m_reply(0), m_plugin(plugin), + m_complete(false), m_favorite(0), m_status(QDeclarativePlace::Ready) +{ + Q_ASSERT(plugin); + + connect(m_contactDetails, SIGNAL(valueChanged(QString,QVariant)), + this, SLOT(contactsModified(QString,QVariant))); + + setPlace(src); +} + +QDeclarativePlace::~QDeclarativePlace() +{ +} + +// From QQmlParserStatus +void QDeclarativePlace::componentComplete() +{ + m_complete = true; +} + +/*! + \qmlproperty Plugin Place::plugin + + This property holds the \l Plugin that provided this place which can be used to retrieve more information about the service. +*/ +void QDeclarativePlace::setPlugin(QDeclarativeGeoServiceProvider *plugin) +{ + if (m_plugin == plugin) + return; + + m_plugin = plugin; + if (m_complete) + emit pluginChanged(); + + if (m_plugin->isAttached()) { + pluginReady(); + } else { + connect(m_plugin, SIGNAL(attached()), + this, SLOT(pluginReady())); + } +} + +void QDeclarativePlace::pluginReady() +{ + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (!placeManager || serviceProvider->error() != QGeoServiceProvider::NoError) { + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR) + .arg(m_plugin->name()).arg(serviceProvider->errorString())); + return; + } +} + +QDeclarativeGeoServiceProvider *QDeclarativePlace::plugin() const +{ + return m_plugin; +} + +/*! + \qmlproperty ReviewModel Place::reviewModel + + This property holds a model which can be used to retrieve reviews about the place. +*/ +QDeclarativeReviewModel *QDeclarativePlace::reviewModel() +{ + if (!m_reviewModel) { + m_reviewModel = new QDeclarativeReviewModel(this); + m_reviewModel->setPlace(this); + } + + return m_reviewModel; +} + +/*! + \qmlproperty ImageModel Place::imageModel + + This property holds a model which can be used to retrieve images of the place. +*/ +QDeclarativePlaceImageModel *QDeclarativePlace::imageModel() +{ + if (!m_imageModel) { + m_imageModel = new QDeclarativePlaceImageModel(this); + m_imageModel->setPlace(this); + } + + return m_imageModel; +} + +/*! + \qmlproperty EditorialModel Place::editorialModel + + This property holds a model which can be used to retrieve editorial descriptions of the place. +*/ +QDeclarativePlaceEditorialModel *QDeclarativePlace::editorialModel() +{ + if (!m_editorialModel) { + m_editorialModel = new QDeclarativePlaceEditorialModel(this); + m_editorialModel->setPlace(this); + } + + return m_editorialModel; +} + +/*! + \qmlproperty QPlace Place::place + + For details on how to use this property to interface between C++ and QML see + "\l {Place - QPlace} {Interfaces between C++ and QML Code}". +*/ +void QDeclarativePlace::setPlace(const QPlace &src) +{ + QPlace previous = m_src; + m_src = src; + + if (previous.categories() != m_src.categories()) { + synchronizeCategories(); + emit categoriesChanged(); + } + + if (m_location && m_location->parent() == this) { + m_location->setLocation(m_src.location()); + } else if (!m_location || m_location->parent() != this) { + m_location = new QDeclarativeGeoLocation(m_src.location(), this); + emit locationChanged(); + } + + if (m_ratings && m_ratings->parent() == this) { + m_ratings->setRatings(m_src.ratings()); + } else if (!m_ratings || m_ratings->parent() != this) { + m_ratings = new QDeclarativeRatings(m_src.ratings(), this); + emit ratingsChanged(); + } + + if (m_supplier && m_supplier->parent() == this) { + m_supplier->setSupplier(m_src.supplier(), m_plugin); + } else if (!m_supplier || m_supplier->parent() != this) { + m_supplier = new QDeclarativeSupplier(m_src.supplier(), m_plugin, this); + emit supplierChanged(); + } + + if (m_icon && m_icon->parent() == this) { + m_icon->setPlugin(m_plugin); + m_icon->setIcon(m_src.icon()); + } else if (!m_icon || m_icon->parent() != this) { + m_icon = new QDeclarativePlaceIcon(m_src.icon(), m_plugin, this); + emit iconChanged(); + } + + if (previous.name() != m_src.name()) { + emit nameChanged(); + } + if (previous.placeId() != m_src.placeId()) { + emit placeIdChanged(); + } + if (previous.attribution() != m_src.attribution()) { + emit attributionChanged(); + } + if (previous.detailsFetched() != m_src.detailsFetched()) { + emit detailsFetchedChanged(); + } + if (previous.primaryPhone() != m_src.primaryPhone()) { + emit primaryPhoneChanged(); + } + if (previous.primaryFax() != m_src.primaryFax()) { + emit primaryFaxChanged(); + } + if (previous.primaryEmail() != m_src.primaryEmail()) { + emit primaryEmailChanged(); + } + if (previous.primaryWebsite() != m_src.primaryWebsite()) { + emit primaryWebsiteChanged(); + } + + if (m_reviewModel && m_src.totalContentCount(QPlaceContent::ReviewType) >= 0) { + m_reviewModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ReviewType), + m_src.content(QPlaceContent::ReviewType)); + } + if (m_imageModel && m_src.totalContentCount(QPlaceContent::ImageType) >= 0) { + m_imageModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ImageType), + m_src.content(QPlaceContent::ImageType)); + } + if (m_editorialModel && m_src.totalContentCount(QPlaceContent::EditorialType) >= 0) { + m_editorialModel->initializeCollection(m_src.totalContentCount(QPlaceContent::EditorialType), + m_src.content(QPlaceContent::EditorialType)); + } + + synchronizeExtendedAttributes(); + synchronizeContacts(); +} + +QPlace QDeclarativePlace::place() +{ + // The following properties are not stored in m_src but instead stored in QDeclarative* objects + + QPlace result = m_src; + + // Categories + QList categories; + foreach (QDeclarativeCategory *value, m_categories) + categories.append(value->category()); + + result.setCategories(categories); + + // Location + result.setLocation(m_location ? m_location->location() : QGeoLocation()); + + // Rating + result.setRatings(m_ratings ? m_ratings->ratings() : QPlaceRatings()); + + // Supplier + result.setSupplier(m_supplier ? m_supplier->supplier() : QPlaceSupplier()); + + // Icon + result.setIcon(m_icon ? m_icon->icon() : QPlaceIcon()); + + //contact details + QList cppDetails; + foreach (const QString &key, m_contactDetails->keys()) { + cppDetails.clear(); + if (m_contactDetails->value(key).type() == QVariant::List) { + QVariantList detailsVarList = m_contactDetails->value(key).toList(); + foreach (const QVariant &detailVar, detailsVarList) { + QDeclarativeContactDetail *detail = qobject_cast(detailVar.value()); + if (detail) + cppDetails.append(detail->contactDetail()); + } + } else { + QDeclarativeContactDetail *detail = qobject_cast(m_contactDetails->value(key).value()); + if (detail) + cppDetails.append(detail->contactDetail()); + } + result.setContactDetails(key, cppDetails); + } + + return result; +} + +/*! + \qmlproperty QtPositioning::Location Place::location + + This property holds the location of the place which can be used to retrieve the coordinate, + address and the bounding box. +*/ +void QDeclarativePlace::setLocation(QDeclarativeGeoLocation *location) +{ + if (m_location == location) + return; + + if (m_location && m_location->parent() == this) + delete m_location; + + m_location = location; + emit locationChanged(); +} + +QDeclarativeGeoLocation *QDeclarativePlace::location() +{ + return m_location; +} + +/*! + \qmlproperty Ratings Place::ratings + + This property holds ratings of the place. The ratings provide an indication of the quality of a + place. +*/ +void QDeclarativePlace::setRatings(QDeclarativeRatings *rating) +{ + if (m_ratings == rating) + return; + + if (m_ratings && m_ratings->parent() == this) + delete m_ratings; + + m_ratings = rating; + emit ratingsChanged(); +} + +QDeclarativeRatings *QDeclarativePlace::ratings() +{ + + return m_ratings; +} + +/*! + \qmlproperty Supplier Place::supplier + + This property holds the supplier of the place data. + The supplier is typically a business or organization that collected the data about the place. +*/ +void QDeclarativePlace::setSupplier(QDeclarativeSupplier *supplier) +{ + if (m_supplier == supplier) + return; + + if (m_supplier && m_supplier->parent() == this) + delete m_supplier; + + m_supplier = supplier; + emit supplierChanged(); +} + +QDeclarativeSupplier *QDeclarativePlace::supplier() const +{ + return m_supplier; +} + +/*! + \qmlproperty Icon Place::icon + + This property holds a graphical icon which can be used to represent the place. +*/ +QDeclarativePlaceIcon *QDeclarativePlace::icon() const +{ + return m_icon; +} + +void QDeclarativePlace::setIcon(QDeclarativePlaceIcon *icon) +{ + if (m_icon == icon) + return; + + if (m_icon && m_icon->parent() == this) + delete m_icon; + + m_icon = icon; + emit iconChanged(); +} + +/*! + \qmlproperty string Place::name + + This property holds the name of the place which can be used to represent the place. +*/ +void QDeclarativePlace::setName(const QString &name) +{ + if (m_src.name() != name) { + m_src.setName(name); + emit nameChanged(); + } +} + +QString QDeclarativePlace::name() const +{ + return m_src.name(); +} + +/*! + \qmlproperty string Place::placeId + + This property holds the unique identifier of the place. The place identifier is only meaningful to the + \l Plugin that generated it and is not transferable between \l {Plugin}{Plugins}. The place id + is not guaranteed to be universally unique, but unique within the \l Plugin that generated it. + + If only the place identifier is known, all other place data can fetched from the \l Plugin. + + \snippet declarative/places.qml Place placeId +*/ +void QDeclarativePlace::setPlaceId(const QString &placeId) +{ + if (m_src.placeId() != placeId) { + m_src.setPlaceId(placeId); + emit placeIdChanged(); + } +} + +QString QDeclarativePlace::placeId() const +{ + return m_src.placeId(); +} + +/*! + \qmlproperty string Place::attribution + + This property holds a rich text attribution string for the place. + Some providers may require that the attribution be shown to the user + whenever a place is displayed. The contents of this property should + be shown to the user if it is not empty. +*/ +void QDeclarativePlace::setAttribution(const QString &attribution) +{ + if (m_src.attribution() != attribution) { + m_src.setAttribution(attribution); + emit attributionChanged(); + } +} + +QString QDeclarativePlace::attribution() const +{ + return m_src.attribution(); +} + +/*! + \qmlproperty bool Place::detailsFetched + + This property indicates whether the details of the place have been fetched. If this property + is false, the place details have not yet been fetched. Fetching can be done by invoking the + \l getDetails() method. + + \sa getDetails() +*/ +bool QDeclarativePlace::detailsFetched() const +{ + return m_src.detailsFetched(); +} + +/*! + \qmlproperty enumeration Place::status + + This property holds the status of the place. It can be one of: + + \table + \row + \li Place.Ready + \li No error occurred during the last operation, further operations may be performed on + the place. + \row + \li Place.Saving + \li The place is currently being saved, no other operation may be performed until + complete. + \row + \li Place.Fetching + \li The place details are currently being fetched, no other operations may be performed + until complete. + \row + \li Place.Removing + \li The place is currently being removed, no other operations can be performed until + complete. + \row + \li Place.Error + \li An error occurred during the last operation, further operations can still be + performed on the place. + \endtable + + The status of a place can be checked by connecting the status property + to a handler function, and then have the handler function process the change + in status. + + \snippet declarative/places.qml Place checkStatus + \dots + \snippet declarative/places.qml Place checkStatus handler + +*/ +void QDeclarativePlace::setStatus(Status status, const QString &errorString) +{ + Status originalStatus = m_status; + m_status = status; + m_errorString = errorString; + + if (originalStatus != m_status) + emit statusChanged(); +} + +QDeclarativePlace::Status QDeclarativePlace::status() const +{ + return m_status; +} + +/*! + \internal +*/ +void QDeclarativePlace::finished() +{ + if (!m_reply) + return; + + if (m_reply->error() == QPlaceReply::NoError) { + switch (m_reply->type()) { + case (QPlaceReply::IdReply) : { + QPlaceIdReply *idReply = qobject_cast(m_reply); + + switch (idReply->operationType()) { + case QPlaceIdReply::SavePlace: + setPlaceId(idReply->id()); + break; + case QPlaceIdReply::RemovePlace: + break; + default: + //Other operation types shouldn't ever be received. + break; + } + break; + } + case (QPlaceReply::DetailsReply): { + QPlaceDetailsReply *detailsReply = qobject_cast(m_reply); + setPlace(detailsReply->place()); + break; + } + default: + //other types of replies shouldn't ever be received. + break; + } + + m_errorString.clear(); + + m_reply->deleteLater(); + m_reply = 0; + + setStatus(QDeclarativePlace::Ready); + } else { + QString errorString = m_reply->errorString(); + + m_reply->deleteLater(); + m_reply = 0; + + setStatus(QDeclarativePlace::Error, errorString); + } +} + +/*! + \internal +*/ +void QDeclarativePlace::contactsModified(const QString &key, const QVariant &) +{ + primarySignalsEmission(key); +} + +/*! + \internal +*/ +void QDeclarativePlace::cleanupDeletedCategories() +{ + foreach (QDeclarativeCategory * category, m_categoriesToBeDeleted) { + if (category->parent() == this) + delete category; + } + m_categoriesToBeDeleted.clear(); +} + +/*! + \qmlmethod void Place::getDetails() + + This method starts fetching place details. + + The \l status property will change to Place.Fetching while the fetch is in progress. On + success the object's properties will be updated, \l status will be set to Place.Ready and + \l detailsFetched will be set to true. On error \l status will be set to Place.Error. The + \l errorString() method can be used to get the details of the error. +*/ +void QDeclarativePlace::getDetails() +{ + QPlaceManager *placeManager = manager(); + if (!placeManager) + return; + + m_reply = placeManager->getPlaceDetails(placeId()); + connect(m_reply, SIGNAL(finished()), this, SLOT(finished())); + setStatus(QDeclarativePlace::Fetching); +} + +/*! + \qmlmethod void Place::save() + + This method performs a save operation on the place. + + The \l status property will change to Place.Saving while the save operation is in progress. On + success the \l status will be set to Place.Ready. On error \l status will be set to Place.Error. + The \l errorString() method can be used to get the details of the error. + + If the \l placeId property was previously empty, it will be assigned a valid value automatically + during a successful save operation. + + Note that a \l PlaceSearchModel will call Place::getDetails on any place that it detects an update + on. A consequence of this is that whenever a Place from a \l PlaceSearchModel is successfully saved, + it will be followed by a fetch of place details, leading to a sequence of state changes + of \c Saving, \c Ready, \c Fetching, \c Ready. + +*/ +void QDeclarativePlace::save() +{ + QPlaceManager *placeManager = manager(); + if (!placeManager) + return; + + m_reply = placeManager->savePlace(place()); + connect(m_reply, SIGNAL(finished()), this, SLOT(finished())); + setStatus(QDeclarativePlace::Saving); +} + +/*! + \qmlmethod void Place::remove() + + This method performs a remove operation on the place. + + The \l status property will change to Place.Removing while the save operation is in progress. + On success \l status will be set to Place.Ready. On error \l status will be set to + Place.Error. The \l errorString() method can be used to get the details of the error. +*/ +void QDeclarativePlace::remove() +{ + QPlaceManager *placeManager = manager(); + if (!placeManager) + return; + + m_reply = placeManager->removePlace(place().placeId()); + connect(m_reply, SIGNAL(finished()), this, SLOT(finished())); + setStatus(QDeclarativePlace::Removing); +} + +/*! + \qmlmethod string Place::errorString() + + Returns a string description of the error of the last operation. If the last operation + completed successfully then the string is empty. +*/ +QString QDeclarativePlace::errorString() const +{ + return m_errorString; +} + +/*! + \qmlproperty string Place::primaryPhone + + This property holds the primary phone number of the place. If no "phone" contact detail is + defined for this place, this property will be an empty string. It is equivalent to: + + + \snippet declarative/places.qml Place primaryPhone +*/ +QString QDeclarativePlace::primaryPhone() const +{ + return primaryValue(QPlaceContactDetail::Phone); +} + +/*! + \qmlproperty string Place::primaryFax + + This property holds the primary fax number of the place. If no "fax" contact detail is + defined for this place this property will be an empty string. It is equivalent to + + \snippet declarative/places.qml Place primaryFax +*/ +QString QDeclarativePlace::primaryFax() const +{ + return primaryValue(QPlaceContactDetail::Fax); +} + +/*! + \qmlproperty string Place::primaryEmail + + This property holds the primary email address of the place. If no "email" contact detail is + defined for this place this property will be an empty string. It is equivalent to + + \snippet declarative/places.qml Place primaryEmail +*/ +QString QDeclarativePlace::primaryEmail() const +{ + return primaryValue(QPlaceContactDetail::Email); +} + +/*! + \qmlproperty string Place::primaryWebsite + + This property holds the primary website url of the place. If no "website" contact detail is + defined for this place this property will be an empty string. It is equivalent to + + \snippet declarative/places.qml Place primaryWebsite +*/ + +QUrl QDeclarativePlace::primaryWebsite() const +{ + return QUrl(primaryValue(QPlaceContactDetail::Website)); +} + +/*! + \qmlproperty ExtendedAttributes Place::extendedAttributes + + This property holds the extended attributes of a place. Extended attributes are additional + information about a place not covered by the place's properties. +*/ +QQmlPropertyMap *QDeclarativePlace::extendedAttributes() const +{ + return m_extendedAttributes; +} + +/*! + \qmlproperty ContactDetails Place::contactDetails + + This property holds the contact information for this place, for example a phone number or + a website URL. This property is a map of \l ContactDetail objects. +*/ +QDeclarativeContactDetails *QDeclarativePlace::contactDetails() const +{ + return m_contactDetails; +} + +/*! + \qmlproperty list Place::categories + + This property holds the list of categories this place is a member of. The categories that can + be assigned to a place are specific to each \l plugin. +*/ +QQmlListProperty QDeclarativePlace::categories() +{ + return QQmlListProperty(this, + 0, // opaque data parameter + category_append, + category_count, + category_at, + category_clear); +} + +/*! + \internal +*/ +void QDeclarativePlace::category_append(QQmlListProperty *prop, + QDeclarativeCategory *value) +{ + QDeclarativePlace *object = static_cast(prop->object); + + if (object->m_categoriesToBeDeleted.contains(value)) + object->m_categoriesToBeDeleted.removeAll(value); + + if (!object->m_categories.contains(value)) { + object->m_categories.append(value); + QList list = object->m_src.categories(); + list.append(value->category()); + object->m_src.setCategories(list); + + emit object->categoriesChanged(); + } +} + +/*! + \internal +*/ +int QDeclarativePlace::category_count(QQmlListProperty *prop) +{ + return static_cast(prop->object)->m_categories.count(); +} + +/*! + \internal +*/ +QDeclarativeCategory *QDeclarativePlace::category_at(QQmlListProperty *prop, + int index) +{ + QDeclarativePlace *object = static_cast(prop->object); + QDeclarativeCategory *res = NULL; + if (object->m_categories.count() > index && index > -1) { + res = object->m_categories[index]; + } + return res; +} + +/*! + \internal +*/ +void QDeclarativePlace::category_clear(QQmlListProperty *prop) +{ + QDeclarativePlace *object = static_cast(prop->object); + if (object->m_categories.isEmpty()) + return; + + for (int i = 0; i < object->m_categories.count(); ++i) { + if (object->m_categories.at(i)->parent() == object) + object->m_categoriesToBeDeleted.append(object->m_categories.at(i)); + } + + object->m_categories.clear(); + object->m_src.setCategories(QList()); + emit object->categoriesChanged(); + QMetaObject::invokeMethod(object, "cleanupDeletedCategories", Qt::QueuedConnection); +} + +/*! + \internal +*/ +void QDeclarativePlace::synchronizeCategories() +{ + qDeleteAll(m_categories); + m_categories.clear(); + foreach (const QPlaceCategory &value, m_src.categories()) { + QDeclarativeCategory *declarativeValue = new QDeclarativeCategory(value, m_plugin, this); + m_categories.append(declarativeValue); + } +} + +/*! + \qmlproperty enumeration Place::visibility + + This property holds the visibility of the place. It can be one of: + + \table + \row + \li Place.UnspecifiedVisibility + \li The visibility of the place is unspecified, the default visibility of the \l Plugin + will be used. + \row + \li Place.DeviceVisibility + \li The place is limited to the current device. The place will not be transferred off + of the device. + \row + \li Place.PrivateVisibility + \li The place is private to the current user. The place may be transferred to an online + service but is only ever visible to the current user. + \row + \li Place.PublicVisibility + \li The place is public. + \endtable + + Note that visibility does not affect how the place is displayed + in the user-interface of an application on the device. Instead, + it defines the sharing semantics of the place. +*/ +QDeclarativePlace::Visibility QDeclarativePlace::visibility() const +{ + return static_cast(m_src.visibility()); +} + +void QDeclarativePlace::setVisibility(Visibility visibility) +{ + if (static_cast(m_src.visibility()) == visibility) + return; + + m_src.setVisibility(static_cast(visibility)); + emit visibilityChanged(); +} + +/*! + \qmlproperty Place Place::favorite + + This property holds the favorite instance of a place. +*/ +QDeclarativePlace *QDeclarativePlace::favorite() const +{ + return m_favorite; +} + +void QDeclarativePlace::setFavorite(QDeclarativePlace *favorite) +{ + + if (m_favorite == favorite) + return; + + if (m_favorite && m_favorite->parent() == this) + delete m_favorite; + + m_favorite = favorite; + emit favoriteChanged(); +} + +/*! + \qmlmethod void Place::copyFrom(Place original) + + Copies data from an \a original place into this place. Only data that is supported by this + place's plugin is copied over and plugin specific data such as place identifier is not copied over. +*/ +void QDeclarativePlace::copyFrom(QDeclarativePlace *original) +{ + QPlaceManager *placeManager = manager(); + if (!placeManager) + return; + + setPlace(placeManager->compatiblePlace(original->place())); +} + +/*! + \qmlmethod void Place::initializeFavorite(Plugin destinationPlugin) + + Creates a favorite instance for the place which is to be saved into the + \a destination plugin. This method does nothing if the favorite property is + not null. +*/ +void QDeclarativePlace::initializeFavorite(QDeclarativeGeoServiceProvider *plugin) +{ + if (m_favorite == 0) { + QDeclarativePlace *place = new QDeclarativePlace(this); + place->setPlugin(plugin); + place->copyFrom(this); + setFavorite(place); + } +} + +/*! + \internal +*/ +void QDeclarativePlace::synchronizeExtendedAttributes() +{ + QStringList keys = m_extendedAttributes->keys(); + foreach (const QString &key, keys) + m_extendedAttributes->clear(key); + + QStringList attributeTypes = m_src.extendedAttributeTypes(); + foreach (const QString &attributeType, attributeTypes) { + m_extendedAttributes->insert(attributeType, + qVariantFromValue(new QDeclarativePlaceAttribute(m_src.extendedAttribute(attributeType)))); + } + + emit extendedAttributesChanged(); +} + +/*! + \internal +*/ +void QDeclarativePlace::synchronizeContacts() +{ + //clear out contact data + foreach (const QString &contactType, m_contactDetails->keys()) { + QList contacts = m_contactDetails->value(contactType).toList(); + foreach (const QVariant &var, contacts) { + QObject *obj = var.value(); + if (obj->parent() == this) + delete obj; + } + m_contactDetails->insert(contactType, QVariantList()); + } + + //insert new contact data from source place + foreach (const QString &contactType, m_src.contactTypes()) { + QList sourceContacts = m_src.contactDetails(contactType); + QVariantList declContacts; + foreach (const QPlaceContactDetail &sourceContact, sourceContacts) { + QDeclarativeContactDetail *declContact = new QDeclarativeContactDetail(this); + declContact->setContactDetail(sourceContact); + declContacts.append(QVariant::fromValue(qobject_cast(declContact))); + } + m_contactDetails->insert(contactType, declContacts); + } + primarySignalsEmission(); +} + +/*! + \internal + Helper function to emit the signals for the primary___() + fields. It is expected that the values of the primary___() + functions have already been modified to new values. +*/ +void QDeclarativePlace::primarySignalsEmission(const QString &type) +{ + if (type.isEmpty() || type == QPlaceContactDetail::Phone) { + if (m_prevPrimaryPhone != primaryPhone()) { + m_prevPrimaryPhone = primaryPhone(); + emit primaryPhoneChanged(); + } + if (!type.isEmpty()) + return; + } + + if (type.isEmpty() || type == QPlaceContactDetail::Email) { + if (m_prevPrimaryEmail != primaryEmail()) { + m_prevPrimaryEmail = primaryEmail(); + emit primaryEmailChanged(); + } + if (!type.isEmpty()) + return; + } + + if (type.isEmpty() || type == QPlaceContactDetail::Website) { + if (m_prevPrimaryWebsite != primaryWebsite()) { + m_prevPrimaryWebsite = primaryWebsite(); + emit primaryWebsiteChanged(); + } + if (!type.isEmpty()) + return; + } + + if (type.isEmpty() || type == QPlaceContactDetail::Fax) { + if (m_prevPrimaryFax != primaryFax()) { + m_prevPrimaryFax = primaryFax(); + emit primaryFaxChanged(); + } + } +} + +/*! + \internal + Helper function to return the manager, this manager is intended to be used + to perform the next operation. If a an operation is currently underway + then return a null pointer. +*/ +QPlaceManager *QDeclarativePlace::manager() +{ + if (m_status != QDeclarativePlace::Ready && m_status != QDeclarativePlace::Error) + return 0; + + if (m_reply) { + m_reply->abort(); + m_reply->deleteLater(); + m_reply = 0; + } + + if (!m_plugin) { + qmlInfo(this) << QStringLiteral("Plugin is not assigned to place."); + return 0; + } + + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (!serviceProvider) + return 0; + + QPlaceManager *placeManager = serviceProvider->placeManager(); + + if (!placeManager) { + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR) + .arg(m_plugin->name()).arg(serviceProvider->errorString())); + return 0; + } + + return placeManager; +} + +/*! + \internal +*/ +QString QDeclarativePlace::primaryValue(const QString &contactType) const +{ + QVariant value = m_contactDetails->value(contactType); + if (value.userType() == qMetaTypeId()) + value = value.value().toVariant(); + + if (value.userType() == QVariant::List) { + QVariantList detailList = m_contactDetails->value(contactType).toList(); + if (!detailList.isEmpty()) { + QDeclarativeContactDetail *primaryDetail = qobject_cast(detailList.at(0).value()); + if (primaryDetail) + return primaryDetail->value(); + } + } else if (value.userType() == QMetaType::QObjectStar) { + QDeclarativeContactDetail *primaryDetail = qobject_cast(m_contactDetails->value(contactType).value()); + if (primaryDetail) + return primaryDetail->value(); + } + + return QString(); +} diff --git a/src/imports/location/declarativeplaces/qdeclarativeplace_p.h b/src/imports/location/declarativeplaces/qdeclarativeplace_p.h new file mode 100644 index 0000000..7855709 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplace_p.h @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPLACE_P_H +#define QDECLARATIVEPLACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +#include "qdeclarativegeolocation_p.h" +#include "qdeclarativecategory_p.h" +#include "qdeclarativecontactdetail_p.h" +#include "qdeclarativesupplier_p.h" +#include "qdeclarativeratings_p.h" +#include "qdeclarativereviewmodel_p.h" +#include "qdeclarativeplaceimagemodel_p.h" +#include "qdeclarativeplaceeditorialmodel.h" + +QT_BEGIN_NAMESPACE + +class QPlaceReply; + +class QPlaceManager; +class QDeclarativePlaceIcon; + +class QDeclarativePlace : public QObject, public QQmlParserStatus +{ + Q_OBJECT + + Q_ENUMS(Status Visibility) + + Q_PROPERTY(QPlace place READ place WRITE setPlace) + Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) + Q_PROPERTY(QQmlListProperty categories READ categories NOTIFY categoriesChanged) + Q_PROPERTY(QDeclarativeGeoLocation *location READ location WRITE setLocation NOTIFY locationChanged) + Q_PROPERTY(QDeclarativeRatings *ratings READ ratings WRITE setRatings NOTIFY ratingsChanged) + Q_PROPERTY(QDeclarativeSupplier *supplier READ supplier WRITE setSupplier NOTIFY supplierChanged) + Q_PROPERTY(QDeclarativePlaceIcon *icon READ icon WRITE setIcon NOTIFY iconChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString placeId READ placeId WRITE setPlaceId NOTIFY placeIdChanged) + Q_PROPERTY(QString attribution READ attribution WRITE setAttribution NOTIFY attributionChanged) + + Q_PROPERTY(QDeclarativeReviewModel *reviewModel READ reviewModel NOTIFY reviewModelChanged) + Q_PROPERTY(QDeclarativePlaceImageModel *imageModel READ imageModel NOTIFY imageModelChanged) + Q_PROPERTY(QDeclarativePlaceEditorialModel *editorialModel READ editorialModel NOTIFY editorialModelChanged) + + Q_PROPERTY(QObject *extendedAttributes READ extendedAttributes NOTIFY extendedAttributesChanged) + Q_PROPERTY(QObject *contactDetails READ contactDetails NOTIFY contactDetailsChanged) + Q_PROPERTY(bool detailsFetched READ detailsFetched NOTIFY detailsFetchedChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + + Q_PROPERTY(QString primaryPhone READ primaryPhone NOTIFY primaryPhoneChanged) + Q_PROPERTY(QString primaryFax READ primaryFax NOTIFY primaryFaxChanged) + Q_PROPERTY(QString primaryEmail READ primaryEmail NOTIFY primaryEmailChanged) + Q_PROPERTY(QUrl primaryWebsite READ primaryWebsite NOTIFY primaryWebsiteChanged) + + Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) + Q_PROPERTY(QDeclarativePlace *favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged) + + Q_INTERFACES(QQmlParserStatus) + +public: + explicit QDeclarativePlace(QObject *parent = 0); + QDeclarativePlace(const QPlace &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent = 0); + ~QDeclarativePlace(); + + enum Status {Ready, Saving, Fetching, Removing, Error}; + enum Visibility { + UnspecifiedVisibility = QLocation::UnspecifiedVisibility, + DeviceVisibility = QLocation::DeviceVisibility, + PrivateVisibility = QLocation::PrivateVisibility, + PublicVisibility = QLocation::PublicVisibility + }; + + //From QQmlParserStatus + virtual void classBegin() {} + virtual void componentComplete(); + + void setPlugin(QDeclarativeGeoServiceProvider *plugin); + QDeclarativeGeoServiceProvider *plugin() const; + + QDeclarativeReviewModel *reviewModel(); + QDeclarativePlaceImageModel *imageModel(); + QDeclarativePlaceEditorialModel *editorialModel(); + + QPlace place(); + void setPlace(const QPlace &src); + + QQmlListProperty categories(); + static void category_append(QQmlListProperty *prop, + QDeclarativeCategory *value); + static int category_count(QQmlListProperty *prop); + static QDeclarativeCategory *category_at(QQmlListProperty *prop, int index); + static void category_clear(QQmlListProperty *prop); + + QDeclarativeGeoLocation *location(); + void setLocation(QDeclarativeGeoLocation *location); + QDeclarativeRatings *ratings(); + void setRatings(QDeclarativeRatings *ratings); + QDeclarativeSupplier *supplier() const; + void setSupplier(QDeclarativeSupplier *supplier); + QDeclarativePlaceIcon *icon() const; + void setIcon(QDeclarativePlaceIcon *icon); + QString name() const; + void setName(const QString &name); + QString placeId() const; + void setPlaceId(const QString &placeId); + QString attribution() const; + void setAttribution(const QString &attribution); + bool detailsFetched() const; + + Status status() const; + void setStatus(Status status, const QString &errorString = QString()); + + Q_INVOKABLE void getDetails(); + Q_INVOKABLE void save(); + Q_INVOKABLE void remove(); + Q_INVOKABLE QString errorString() const; + + QString primaryPhone() const; + QString primaryFax() const; + QString primaryEmail() const; + QUrl primaryWebsite() const; + + QQmlPropertyMap *extendedAttributes() const; + + QDeclarativeContactDetails *contactDetails() const; + + Visibility visibility() const; + void setVisibility(Visibility visibility); + + QDeclarativePlace *favorite() const; + void setFavorite(QDeclarativePlace *favorite); + + Q_INVOKABLE void copyFrom(QDeclarativePlace *original); + Q_INVOKABLE void initializeFavorite(QDeclarativeGeoServiceProvider *plugin); + +Q_SIGNALS: + void pluginChanged(); + void categoriesChanged(); + void locationChanged(); + void ratingsChanged(); + void supplierChanged(); + void iconChanged(); + void nameChanged(); + void placeIdChanged(); + void attributionChanged(); + void detailsFetchedChanged(); + void reviewModelChanged(); + void imageModelChanged(); + void editorialModelChanged(); + + void primaryPhoneChanged(); + void primaryFaxChanged(); + void primaryEmailChanged(); + void primaryWebsiteChanged(); + + void extendedAttributesChanged(); + void contactDetailsChanged(); + void statusChanged(); + void visibilityChanged(); + void favoriteChanged(); + +private Q_SLOTS: + void finished(); + void contactsModified(const QString &, const QVariant &); + void pluginReady(); + void cleanupDeletedCategories(); +private: + void synchronizeCategories(); + void synchronizeExtendedAttributes(); + void synchronizeContacts(); + void primarySignalsEmission(const QString &type = QString()); + QString primaryValue(const QString &contactType) const; + +private: + QPlaceManager *manager(); + + QList m_categories; + QDeclarativeGeoLocation *m_location; + QDeclarativeRatings *m_ratings; + QDeclarativeSupplier *m_supplier; + QDeclarativePlaceIcon *m_icon; + QDeclarativeReviewModel *m_reviewModel; + QDeclarativePlaceImageModel *m_imageModel; + QDeclarativePlaceEditorialModel *m_editorialModel; + QQmlPropertyMap *m_extendedAttributes; + QDeclarativeContactDetails *m_contactDetails; + + QPlace m_src; + + QPlaceReply *m_reply; + + QDeclarativeGeoServiceProvider *m_plugin; + bool m_complete; + + QString m_prevPrimaryPhone; + QString m_prevPrimaryEmail; + QString m_prevPrimaryFax; + QUrl m_prevPrimaryWebsite; + + QDeclarativePlace *m_favorite; + + Status m_status; + QString m_errorString; + + QListm_categoriesToBeDeleted; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativePlace) + +#endif // QDECLARATIVEPLACE_P_H diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceattribute.cpp b/src/imports/location/declarativeplaces/qdeclarativeplaceattribute.cpp new file mode 100644 index 0000000..9a04d38 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceattribute.cpp @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeplaceattribute_p.h" + +/*! + \qmltype ExtendedAttributes + \instantiates QQmlPropertyMap + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + \since Qt Location 5.5 + + \brief The ExtendedAttributes type holds additional data about a \l Place. + + The ExtendedAttributes type is a map of \l {PlaceAttribute}{PlaceAttributes}. To access + attributes in the map use the \l keys() method to get the list of keys stored in the map and + use the \c {[]} operator to access the \l PlaceAttribute items. + + The following are standard keys that are defined by the API. \l Plugin + implementations are free to define additional keys. Custom keys should + be qualified by a unique prefix to avoid clashes. + \table + \header + \li key + \li description + \row + \li openingHours + \li The trading hours of the place + \row + \li payment + \li The types of payment the place accepts, for example visa, mastercard. + \row + \li x_provider + \li The name of the provider that a place is sourced from + \row + \li x_id_ (for example x_id_here) + \li An alternative identifier which identifies the place from the + perspective of the specified provider. + \endtable + + Some plugins may not support attributes at all, others may only support a + certain set, others still may support a dynamically changing set of attributes + over time or even allow attributes to be arbitrarily defined by the client + application. The attributes could also vary on a place by place basis, + for example one place may have opening hours while another does not. + Consult the \l {Plugin References and Parameters}{plugin + references} for details. + + Some attributes may not be intended to be readable by end users, the label field + of such attributes is empty to indicate this fact. + + \note ExtendedAttributes instances are only ever used in the context of \l {Place}s. It is not + possible to create an ExtendedAttributes instance directly or re-assign a \l {Place}'s + ExtendedAttributes property. Modification of ExtendedAttributes can only be accomplished + via Javascript. + + The following example shows how to access all \l {PlaceAttribute}{PlaceAttributes} and print + them to the console: + + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml ExtendedAttributes read + + The following example shows how to assign and modify an attribute: + \snippet declarative/places.qml ExtendedAttributes write + + \sa PlaceAttribute, QQmlPropertyMap +*/ + +/*! + \qmlmethod variant ExtendedAttributes::keys() + + Returns an array of place attribute keys currently stored in the map. +*/ + +/*! + \qmlsignal void ExtendedAttributes::valueChanged(string key, variant value) + + This signal is emitted when the set of attributes changes. \a key is the key + corresponding to the \a value that was changed. + + The corresponding handler is \c onValueChanged. +*/ + +/*! + \qmltype PlaceAttribute + \instantiates QDeclarativePlaceAttribute + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + \since Qt Location 5.5 + + \brief The PlaceAttribute type holds generic place attribute information. + + A place attribute stores an additional piece of information about a \l Place that is not + otherwise exposed through the \l Place type. A PlaceAttribute is a textual piece of data, + accessible through the \l text property, and a \l label. Both the \l text and \l label + properties are intended to be displayed to the user. PlaceAttributes are stored in an + \l ExtendedAttributes map with a unique key. + + The following example shows how to display all attributes in a list: + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml ExtendedAttributes + + The following example shows how to assign and modify an attribute: + \snippet declarative/places.qml ExtendedAttributes write +*/ + +QDeclarativePlaceAttribute::QDeclarativePlaceAttribute(QObject *parent) + : QObject(parent) +{ +} + +QDeclarativePlaceAttribute::QDeclarativePlaceAttribute(const QPlaceAttribute &src, QObject *parent) + : QObject(parent),m_attribute(src) +{ +} + +QDeclarativePlaceAttribute::~QDeclarativePlaceAttribute() +{ +} + +/*! + \qmlproperty QPlaceAttribute PlaceAttribute::attribute + + For details on how to use this property to interface between C++ and QML see + "\l {PlaceAttribute - QPlaceAttribute} {Interfaces between C++ and QML Code}". +*/ +void QDeclarativePlaceAttribute::setAttribute(const QPlaceAttribute &src) +{ + QPlaceAttribute prevAttribute = m_attribute; + m_attribute = src; + + if (m_attribute.label() != prevAttribute.label()) + emit labelChanged(); + if (m_attribute.text() != prevAttribute.text()) + emit textChanged(); +} + +QPlaceAttribute QDeclarativePlaceAttribute::attribute() const +{ + return m_attribute; +} + +/*! + \qmlproperty string PlaceAttribute::label + + This property holds the attribute label which is a user visible string + describing the attribute. +*/ +void QDeclarativePlaceAttribute::setLabel(const QString &label) +{ + if (m_attribute.label() != label) { + m_attribute.setLabel(label); + emit labelChanged(); + } +} + +QString QDeclarativePlaceAttribute::label() const +{ + return m_attribute.label(); +} + +/*! + \qmlproperty string PlaceAttribute::text + + This property holds the attribute text which can be used to show additional information about the place. +*/ +void QDeclarativePlaceAttribute::setText(const QString &text) +{ + if (m_attribute.text() != text) { + m_attribute.setText(text); + emit textChanged(); + } +} + +QString QDeclarativePlaceAttribute::text() const +{ + return m_attribute.text(); +} diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceattribute_p.h b/src/imports/location/declarativeplaces/qdeclarativeplaceattribute_p.h new file mode 100644 index 0000000..f1c873c --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceattribute_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPLACEATTRIBUTE_P_H +#define QDECLARATIVEPLACEATTRIBUTE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativePlaceAttribute : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPlaceAttribute attribute READ attribute WRITE setAttribute) + Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + +public: + explicit QDeclarativePlaceAttribute(QObject *parent = 0); + explicit QDeclarativePlaceAttribute(const QPlaceAttribute &src, QObject *parent = 0); + ~QDeclarativePlaceAttribute(); + + QPlaceAttribute attribute() const; + void setAttribute(const QPlaceAttribute &place); + + QString text() const; + void setText(const QString &text); + + + QString label() const; + void setLabel(const QString &label); + +Q_SIGNALS: + void labelChanged(); + void textChanged(); + +private: + QPlaceAttribute m_attribute; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativePlaceAttribute) + +#endif diff --git a/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp b/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp new file mode 100644 index 0000000..b031e0c --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp @@ -0,0 +1,397 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeplacecontentmodel.h" +#include "qdeclarativeplace_p.h" +#include "qdeclarativegeoserviceprovider_p.h" +#include "qdeclarativeplaceuser_p.h" +#include "error_messages.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QDeclarativePlaceContentModel::QDeclarativePlaceContentModel(QPlaceContent::Type type, + QObject *parent) +: QAbstractListModel(parent), m_place(0), m_type(type), m_batchSize(1), m_contentCount(-1), + m_reply(0), m_complete(false) +{ +} + +QDeclarativePlaceContentModel::~QDeclarativePlaceContentModel() +{ +} + +/*! + \internal +*/ +QDeclarativePlace *QDeclarativePlaceContentModel::place() const +{ + return m_place; +} + +/*! + \internal +*/ +void QDeclarativePlaceContentModel::setPlace(QDeclarativePlace *place) +{ + if (m_place != place) { + beginResetModel(); + + int initialCount = m_contentCount; + clearData(); + m_place = place; + endResetModel(); + + emit placeChanged(); + if (initialCount != -1) + emit totalCountChanged(); + + fetchMore(QModelIndex()); + } +} + +/*! + \internal +*/ +int QDeclarativePlaceContentModel::batchSize() const +{ + return m_batchSize; +} + +/*! + \internal +*/ +void QDeclarativePlaceContentModel::setBatchSize(int batchSize) +{ + if (m_batchSize != batchSize) { + m_batchSize = batchSize; + emit batchSizeChanged(); + } +} + +/*! + \internal +*/ +int QDeclarativePlaceContentModel::totalCount() const +{ + return m_contentCount; +} + +/*! + \internal + Clears the model data but does not reset it. +*/ +void QDeclarativePlaceContentModel::clearData() +{ + qDeleteAll(m_users); + m_users.clear(); + + qDeleteAll(m_suppliers); + m_suppliers.clear(); + + m_content.clear(); + + m_contentCount = -1; + + if (m_reply) { + m_reply->abort(); + m_reply->deleteLater(); + m_reply = 0; + } + + m_nextRequest.clear(); +} + +/*! + \internal +*/ +void QDeclarativePlaceContentModel::initializeCollection(int totalCount, const QPlaceContent::Collection &collection) +{ + beginResetModel(); + + int initialCount = m_contentCount; + clearData(); + + QMapIterator i(collection); + while (i.hasNext()) { + i.next(); + + const QPlaceContent &content = i.value(); + if (content.type() != m_type) + continue; + + m_content.insert(i.key(), content); + if (!m_suppliers.contains(content.supplier().supplierId())) { + m_suppliers.insert(content.supplier().supplierId(), + new QDeclarativeSupplier(content.supplier(), m_place->plugin(), this)); + } + if (!m_users.contains(content.user().userId())) { + m_users.insert(content.user().userId(), + new QDeclarativePlaceUser(content.user(), this)); + } + } + + m_contentCount = totalCount; + + if (initialCount != totalCount) + emit totalCountChanged(); + + endResetModel(); +} + +/*! + \internal +*/ +int QDeclarativePlaceContentModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return m_content.count(); +} + +/*! + \internal +*/ +QVariant QDeclarativePlaceContentModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= rowCount(index.parent()) || index.row() < 0) + return QVariant(); + + const QPlaceContent &content = m_content.value(index.row()); + + switch (role) { + case SupplierRole: + return QVariant::fromValue(static_cast(m_suppliers.value(content.supplier().supplierId()))); + case PlaceUserRole: + return QVariant::fromValue(static_cast(m_users.value(content.user().userId()))); + case AttributionRole: + return content.attribution(); + default: + return QVariant(); + } +} + +QHash QDeclarativePlaceContentModel::roleNames() const +{ + QHash roles = QAbstractListModel::roleNames(); + roles.insert(SupplierRole, "supplier"); + roles.insert(PlaceUserRole, "user"); + roles.insert(AttributionRole, "attribution"); + return roles; +} + +/*! + \internal +*/ +bool QDeclarativePlaceContentModel::canFetchMore(const QModelIndex &parent) const +{ + if (parent.isValid()) + return false; + + if (!m_place) + return false; + + if (m_contentCount == -1) + return true; + + return m_content.count() != m_contentCount; +} + +/*! + \internal +*/ +void QDeclarativePlaceContentModel::fetchMore(const QModelIndex &parent) +{ + if (parent.isValid()) + return; + + if (!m_place) + return; + + if (m_reply) + return; + + if (!m_place->plugin()) + return; + + QDeclarativeGeoServiceProvider *plugin = m_place->plugin(); + + QGeoServiceProvider *serviceProvider = plugin->sharedGeoServiceProvider(); + if (!serviceProvider) + return; + + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (!placeManager) + return; + + if (m_nextRequest == QPlaceContentRequest()) { + QPlaceContentRequest request; + request.setContentType(m_type); + request.setPlaceId(m_place->place().placeId()); + request.setLimit(m_batchSize); + + m_reply = placeManager->getPlaceContent(request); + } else { + m_reply = placeManager->getPlaceContent(m_nextRequest); + } + + connect(m_reply, SIGNAL(finished()), this, SLOT(fetchFinished()), Qt::QueuedConnection); +} + +/*! + \internal +*/ +void QDeclarativePlaceContentModel::classBegin() +{ +} + +/*! + \internal +*/ +void QDeclarativePlaceContentModel::componentComplete() +{ + m_complete = true; + fetchMore(QModelIndex()); +} + +/*! + \internal +*/ +void QDeclarativePlaceContentModel::fetchFinished() +{ + if (!m_reply) + return; + + QPlaceContentReply *reply = m_reply; + m_reply = 0; + + m_nextRequest = reply->nextPageRequest(); + + if (m_contentCount != reply->totalCount()) { + m_contentCount = reply->totalCount(); + emit totalCountChanged(); + } + + if (!reply->content().isEmpty()) { + QPlaceContent::Collection contents = reply->content(); + + //find out which indexes are new and which ones have changed. + QMapIterator it(contents); + QList changedIndexes; + QList newIndexes; + while (it.hasNext()) { + it.next(); + if (!m_content.contains(it.key())) + newIndexes.append(it.key()); + else if (it.value() != m_content.value(it.key())) + changedIndexes.append(it.key()); + } + + //insert new indexes in blocks where within each + //block, the indexes are consecutive. + QListIterator newIndexesIter(newIndexes); + int startIndex = -1; + while (newIndexesIter.hasNext()) { + int currentIndex = newIndexesIter.next(); + if (startIndex == -1) + startIndex = currentIndex; + + if (!newIndexesIter.hasNext() || (newIndexesIter.hasNext() && (newIndexesIter.peekNext() > (currentIndex + 1)))) { + beginInsertRows(QModelIndex(),startIndex,currentIndex); + for (int i = startIndex; i <= currentIndex; ++i) { + const QPlaceContent &content = contents.value(i); + + m_content.insert(i, content); + if (!m_suppliers.contains(content.supplier().supplierId())) { + m_suppliers.insert(content.supplier().supplierId(), + new QDeclarativeSupplier(content.supplier(), m_place->plugin(), this)); + } + if (!m_users.contains(content.user().userId())) { + m_users.insert(content.user().userId(), + new QDeclarativePlaceUser(content.user(), this)); + } + } + endInsertRows(); + startIndex = -1; + } + } + + //modify changed indexes in blocks where within each + //block, the indexes are consecutive. + startIndex = -1; + QListIterator changedIndexesIter(changedIndexes); + while (changedIndexesIter.hasNext()) { + int currentIndex = changedIndexesIter.next(); + if (startIndex == -1) + startIndex = currentIndex; + + if (!changedIndexesIter.hasNext() || (changedIndexesIter.hasNext() && changedIndexesIter.peekNext() > (currentIndex + 1))) { + for (int i = startIndex; i <= currentIndex; ++i) { + const QPlaceContent &content = contents.value(i); + m_content.insert(i, content); + if (!m_suppliers.contains(content.supplier().supplierId())) { + m_suppliers.insert(content.supplier().supplierId(), + new QDeclarativeSupplier(content.supplier(), m_place->plugin(), this)); + } + if (!m_users.contains(content.user().userId())) { + m_users.insert(content.user().userId(), + new QDeclarativePlaceUser(content.user(), this)); + } + } + emit dataChanged(index(startIndex),index(currentIndex)); + startIndex = -1; + } + } + + // The fetch didn't add any new content and we haven't fetched all content yet. This is + // likely due to the model being prepopulated by Place::getDetails(). Keep fetching more + // data until new content is available. + if (newIndexes.isEmpty() && m_content.count() != m_contentCount) + fetchMore(QModelIndex()); + } + + reply->deleteLater(); +} + +QT_END_NAMESPACE diff --git a/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.h b/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.h new file mode 100644 index 0000000..d839b92 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPLACECONTENTMODEL_H +#define QDECLARATIVEPLACECONTENTMODEL_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativePlace; +class QDeclarativeGeoServiceProvider; +class QGeoServiceProvider; +class QDeclarativeSupplier; +class QDeclarativePlaceUser; + +class QDeclarativePlaceContentModel : public QAbstractListModel, public QQmlParserStatus +{ + Q_OBJECT + + Q_PROPERTY(QDeclarativePlace *place READ place WRITE setPlace NOTIFY placeChanged) + Q_PROPERTY(int batchSize READ batchSize WRITE setBatchSize NOTIFY batchSizeChanged) + Q_PROPERTY(int totalCount READ totalCount NOTIFY totalCountChanged) + + Q_INTERFACES(QQmlParserStatus) + +public: + explicit QDeclarativePlaceContentModel(QPlaceContent::Type type, QObject *parent = 0); + ~QDeclarativePlaceContentModel(); + + QDeclarativePlace *place() const; + void setPlace(QDeclarativePlace *place); + + int batchSize() const; + void setBatchSize(int batchSize); + + int totalCount() const; + + void clearData(); + + void initializeCollection(int totalCount, const QPlaceContent::Collection &collection); + + // from QAbstractListModel + int rowCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + QHash roleNames() const; + + enum Roles { + SupplierRole = Qt::UserRole, + PlaceUserRole, + AttributionRole, + UserRole //indicator for next conten type specific role + }; + + bool canFetchMore(const QModelIndex &parent) const; + void fetchMore(const QModelIndex &parent); + + // from QQmlParserStatus + void classBegin(); + void componentComplete(); + +Q_SIGNALS: + void placeChanged(); + void batchSizeChanged(); + void totalCountChanged(); + +private Q_SLOTS: + void fetchFinished(); + +protected: + QPlaceContent::Collection m_content; + QMap m_suppliers; + QMapm_users; + +private: + QDeclarativePlace *m_place; + QPlaceContent::Type m_type; + int m_batchSize; + int m_contentCount; + + QPlaceContentReply *m_reply; + QPlaceContentRequest m_nextRequest; + + bool m_complete; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEPLACECONTENTMODEL_H diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceeditorialmodel.cpp b/src/imports/location/declarativeplaces/qdeclarativeplaceeditorialmodel.cpp new file mode 100644 index 0000000..ebde46c --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceeditorialmodel.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeplaceeditorialmodel.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype EditorialModel + \instantiates QDeclarativePlaceEditorialModel + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-models + \since Qt Location 5.5 + + \brief The EditorialModel type provides a model of place editorials. + + The EditorialModel is a read-only model used to fetch editorials related to a \l Place. + Binding a \l Place via \l EditorialModel::place initiates an initial fetch of editorials. + The model performs fetches incrementally and is intended to be used in conjunction + with a View such as a \l ListView. When the View reaches the last of the editorials + currently in the model, a fetch is performed to retrieve more if they are available. + The View is automatically updated as the editorials are received. The number of + editorials which are fetched at a time is specified by the \l batchSize property. + The total number of editorials available can be accessed via the \l totalCount property. + + The model returns data for the following roles: + + \table + \header + \li Role + \li Type + \li Description + \row + \li text + \li string + \li The editorial's textual description of the place. It can be either rich (HTML based) text or plain text + depending upon the provider. + \row + \li title + \li string + \li The title of the editorial. + \row + \li language + \li string + \li The language that the editorial is written in. + \row + \li supplier + \li \l Supplier + \li The supplier of the editorial. + \row + \li user + \li \l {QtLocation::User}{User} + \li The user who contributed the editorial. + \row + \li attribution + \li string + \li Attribution text which must be displayed when displaying the editorial. + \endtable + + \section1 Example + + The following example shows how to display editorials for a place: + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml EditorialModel + +*/ + +/*! + \qmlproperty Place EditorialModel::place + + This property holds the Place that the editorials are for. +*/ + +/*! + \qmlproperty int EditorialModel::batchSize + + This property holds the batch size to use when fetching more editorials items. +*/ + +/*! + \qmlproperty int EditorialModel::totalCount + + This property holds the total number of editorial items for the place. +*/ + +QDeclarativePlaceEditorialModel::QDeclarativePlaceEditorialModel(QObject *parent) +: QDeclarativePlaceContentModel(QPlaceContent::EditorialType, parent) +{ +} + +QDeclarativePlaceEditorialModel::~QDeclarativePlaceEditorialModel() +{ +} + +/*! + \internal +*/ +QVariant QDeclarativePlaceEditorialModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= rowCount(index.parent()) || index.row() < 0) + return QVariant(); + + const QPlaceEditorial &description = m_content.value(index.row()); + + switch (role) { + case TextRole: + return description.text(); + case TitleRole: + return description.title(); + case LanguageRole: + return description.language(); + } + + return QDeclarativePlaceContentModel::data(index, role); +} + +QHash QDeclarativePlaceEditorialModel::roleNames() const +{ + QHash roleNames = QDeclarativePlaceContentModel::roleNames(); + roleNames.insert(TextRole, "text"); + roleNames.insert(TitleRole, "title"); + roleNames.insert(LanguageRole, "language"); + return roleNames; +} + +QT_END_NAMESPACE diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceeditorialmodel.h b/src/imports/location/declarativeplaces/qdeclarativeplaceeditorialmodel.h new file mode 100644 index 0000000..eb2faf6 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceeditorialmodel.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPLACEEDITORIALMODEL_H +#define QDECLARATIVEPLACEEDITORIALMODEL_H + +#include "qdeclarativeplacecontentmodel.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativePlaceEditorialModel : public QDeclarativePlaceContentModel +{ + Q_OBJECT + +public: + explicit QDeclarativePlaceEditorialModel(QObject *parent = 0); + ~QDeclarativePlaceEditorialModel(); + + QVariant data(const QModelIndex &index, int role) const; + QHash roleNames() const; + + enum Roles { + TextRole = UserRole, + TitleRole, + LanguageRole + }; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEPLACEEDITORIALMODEL_H diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceicon.cpp b/src/imports/location/declarativeplaces/qdeclarativeplaceicon.cpp new file mode 100644 index 0000000..d10b2b0 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceicon.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeplaceicon_p.h" +#include "error_messages.h" + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +/*! + \qmltype Icon + \instantiates QDeclarativePlaceIcon + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + \since Qt Location 5.5 + + \brief The Icon type represents an icon image source which can have multiple sizes. + + The Icon type can be used in conjunction with an \l Image type to display an icon. + The \l url() function is used to construct an icon URL of a requested size, + the icon which most closely matches the requested size is returned. + + The Icon type also has a parameters map which is a set of key value pairs. The precise + keys to use depend on the + \l {Qt Location#Plugin References and Parameters}{plugin} being used. + The parameters map is used by the \l Plugin to determine which URL to return. + + In the case where an icon can only possibly have one image URL, the + parameter key of \c "singleUrl" can be used with a QUrl value. Any Icon with this + parameter will always return the specified URL regardless of the requested icon + size and not defer to any Plugin. + + The following code shows how to display a 64x64 pixel icon: + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml Icon + + Alternatively, a default sized icon can be specified like so: + \snippet declarative/places.qml Icon default +*/ + +QDeclarativePlaceIcon::QDeclarativePlaceIcon(QObject *parent) +: QObject(parent), m_plugin(0), m_parameters(new QQmlPropertyMap(this)) +{ +} + +QDeclarativePlaceIcon::QDeclarativePlaceIcon(const QPlaceIcon &icon, QDeclarativeGeoServiceProvider *plugin, QObject *parent) +: QObject(parent), m_parameters(new QQmlPropertyMap(this)) +{ + if (icon.isEmpty()) + m_plugin = 0; + else + m_plugin = plugin; + + initParameters(icon.parameters()); +} + +QDeclarativePlaceIcon::~QDeclarativePlaceIcon() +{ +} + +/*! + \qmlproperty QPlaceIcon Icon::icon + + For details on how to use this property to interface between C++ and QML see + "\l {Icon - QPlaceIcon} {Interfaces between C++ and QML Code}". +*/ +QPlaceIcon QDeclarativePlaceIcon::icon() const +{ + QPlaceIcon result; + + if (m_plugin) + result.setManager(manager()); + else + result.setManager(0); + + QVariantMap params; + foreach (const QString &key, m_parameters->keys()) { + const QVariant value = m_parameters->value(key); + if (value.isValid()) { + params.insert(key, value); + } + } + + result.setParameters(params); + + return result; +} + +void QDeclarativePlaceIcon::setIcon(const QPlaceIcon &src) +{ + initParameters(src.parameters()); +} + +/*! + \qmlmethod url Icon::url(size size) + + Returns a URL for the icon image that most closely matches the given \a size. + + If no plugin has been assigned to the icon, and the parameters do not contain the 'singleUrl' key, a default constructed URL + is returned. + +*/ +QUrl QDeclarativePlaceIcon::url(const QSize &size) const +{ + return icon().url(size); +} + +/*! + \qmlproperty Object Icon::parameters + + This property holds the parameters of the icon and is a map. These parameters + are used by the plugin to return the appropriate URL when url() is called and to + specify locations to save to when saving icons. + + Consult the \l {Qt Location#Plugin References and Parameters}{plugin documentation} + for what parameters are supported and how they should be used. + + Note, due to limitations of the QQmlPropertyMap, it is not possible + to declaratively specify the parameters in QML, assignment of parameters keys + and values can only be accomplished by JavaScript. + +*/ +QQmlPropertyMap *QDeclarativePlaceIcon::parameters() const +{ + return m_parameters; +} + +/*! + \qmlproperty Plugin Icon::plugin + + The property holds the plugin that is responsible for managing this icon. +*/ +QDeclarativeGeoServiceProvider *QDeclarativePlaceIcon::plugin() const +{ + return m_plugin; +} + +void QDeclarativePlaceIcon::setPlugin(QDeclarativeGeoServiceProvider *plugin) +{ + if (m_plugin == plugin) + return; + + m_plugin = plugin; + emit pluginChanged(); + + if (!m_plugin) + return; + + if (m_plugin->isAttached()) { + pluginReady(); + } else { + connect(m_plugin, SIGNAL(attached()), + this, SLOT(pluginReady())); + } +} + +/*! + \internal +*/ +void QDeclarativePlaceIcon::pluginReady() +{ + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (!placeManager || serviceProvider->error() != QGeoServiceProvider::NoError) { + qmlInfo(this) << QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR) + .arg(m_plugin->name()).arg(serviceProvider->errorString()); + return; + } +} + +/*! + \internal + Helper function to return the manager from the plugin +*/ +QPlaceManager *QDeclarativePlaceIcon::manager() const +{ + if (!m_plugin) { + qmlInfo(this) << QStringLiteral("Plugin is not assigned to place."); + return 0; + } + + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (!serviceProvider) + return 0; + + QPlaceManager *placeManager = serviceProvider->placeManager(); + + if (!placeManager) + return 0; + + return placeManager; +} + +/*! + \internal +*/ +void QDeclarativePlaceIcon::initParameters(const QVariantMap ¶meterMap) +{ + //clear out old parameters + foreach (const QString &key, m_parameters->keys()) + m_parameters->clear(key); + + foreach (const QString &key, parameterMap.keys()) { + QVariant value = parameterMap.value(key); + m_parameters->insert(key, value); + } +} diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h b/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h new file mode 100644 index 0000000..23acb36 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPLACEICON_P_H +#define QDECLARATIVEPLACEICON_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeoserviceprovider_p.h" + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QQmlPropertyMap; + +class QDeclarativePlaceIcon : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPlaceIcon icon READ icon WRITE setIcon) + Q_PROPERTY(QObject *parameters READ parameters NOTIFY parametersChanged) + Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) + +public: + explicit QDeclarativePlaceIcon(QObject *parent = 0); + QDeclarativePlaceIcon(const QPlaceIcon &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent = 0); + ~QDeclarativePlaceIcon(); + + QPlaceIcon icon() const; + void setIcon(const QPlaceIcon &src); + + Q_INVOKABLE QUrl url(const QSize &size = QSize()) const; + + QQmlPropertyMap *parameters() const; + + void setPlugin(QDeclarativeGeoServiceProvider *plugin); + QDeclarativeGeoServiceProvider *plugin() const; + +Q_SIGNALS: + void pluginChanged(); + void parametersChanged(); //in practice is never emitted since parameters cannot be re-assigned + //the declaration is needed to avoid warnings about non-notifyable properties + +private Q_SLOTS: + void pluginReady(); + +private: + QPlaceManager *manager() const; + void initParameters(const QVariantMap ¶meterMap); + QDeclarativeGeoServiceProvider *m_plugin; + QQmlPropertyMap *m_parameters; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel.cpp b/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel.cpp new file mode 100644 index 0000000..4da3708 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeplaceimagemodel_p.h" +#include "qdeclarativesupplier_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype ImageModel + \instantiates QDeclarativePlaceImageModel + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-models + \since Qt Location 5.5 + + \brief The ImageModel type provides a model of place images. + + The ImageModel is a read-only model used to fetch images related to a \l Place. + Binding a \l Place via \l ImageModel::place initiates an initial fetch of images. + The model performs fetches incrementally and is intended to be used in conjunction + with a View such as a \l ListView. When the View reaches the last of the images + currently in the model, a fetch is performed to retrieve more if they are available. + The View is automatically updated as the images are received. The number of images + which are fetched at a time is specified by the \l batchSize property. The total number + of images available can be accessed via the \l totalCount property. + + The model returns data for the following roles: + + \table + \header + \li Role + \li Type + \li Description + \row + \li url + \li url + \li The URL of the image. + \row + \li imageId + \li string + \li The identifier of the image. + \row + \li mimeType + \li string + \li The MIME type of the image. + \row + \li supplier + \li \l Supplier + \li The supplier of the image. + \row + \li user + \li \l {QtLocation::User}{User} + \li The user who contributed the image. + \row + \li attribution + \li string + \li Attribution text which must be displayed when displaying the image. + \endtable + + + \section1 Example + + The following example shows how to display images for a place: + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml ImageModel +*/ + +/*! + \qmlproperty Place ImageModel::place + + This property holds the Place that the images are for. +*/ + +/*! + \qmlproperty int ImageModel::batchSize + + This property holds the batch size to use when fetching more image items. +*/ + +/*! + \qmlproperty int ImageModel::totalCount + + This property holds the total number of image items for the place. +*/ + +QDeclarativePlaceImageModel::QDeclarativePlaceImageModel(QObject *parent) +: QDeclarativePlaceContentModel(QPlaceContent::ImageType, parent) +{ +} + +QDeclarativePlaceImageModel::~QDeclarativePlaceImageModel() +{ + qDeleteAll(m_suppliers); +} + +/*! + \internal +*/ +QVariant QDeclarativePlaceImageModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= rowCount(index.parent()) || index.row() < 0) + return QVariant(); + + const QPlaceImage &image = m_content.value(index.row()); + + switch (role) { + case UrlRole: + return image.url(); + case ImageIdRole: + return image.imageId(); + case MimeTypeRole: + return image.mimeType(); + } + + return QDeclarativePlaceContentModel::data(index, role); +} + +QHash QDeclarativePlaceImageModel::roleNames() const +{ + QHash roles = QDeclarativePlaceContentModel::roleNames(); + roles.insert(UrlRole, "url"); + roles.insert(ImageIdRole, "imageId"); + roles.insert(MimeTypeRole, "mimeType"); + return roles; +} + +QT_END_NAMESPACE diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h b/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h new file mode 100644 index 0000000..8f8f3f4 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPLACEIMAGEMODEL_P_H +#define QDECLARATIVEPLACEIMAGEMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativeplacecontentmodel.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativeSupplier; + +class QDeclarativePlaceImageModel : public QDeclarativePlaceContentModel +{ + Q_OBJECT + +public: + explicit QDeclarativePlaceImageModel(QObject *parent = 0); + ~QDeclarativePlaceImageModel(); + + QVariant data(const QModelIndex &index, int role) const; + QHash roleNames() const; + + enum Roles { + UrlRole = UserRole, + ImageIdRole, + MimeTypeRole + }; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceuser.cpp b/src/imports/location/declarativeplaces/qdeclarativeplaceuser.cpp new file mode 100644 index 0000000..d8bae3f --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceuser.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeplaceuser_p.h" + +QT_USE_NAMESPACE + +/*! + \qmltype User + \instantiates QDeclarativePlaceUser + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + \since Qt Location 5.5 + + \brief The User type identifies a user who contributed a particular \l Place content item. + + Each \l Place content item has an associated user who contributed the content. This type + provides information about that user. + + \sa ImageModel, ReviewModel, EditorialModel + + \section1 Example + + The following example shows how to display information about the user who + submitted an editorial: + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml EditorialModel +*/ + +QDeclarativePlaceUser::QDeclarativePlaceUser(QObject *parent) + : QObject(parent) {} + +QDeclarativePlaceUser::QDeclarativePlaceUser(const QPlaceUser &user, + QObject *parent) + : QObject(parent), + m_user(user) {} + +QDeclarativePlaceUser::~QDeclarativePlaceUser() {} + +/*! + \qmlproperty QPlaceUser QtLocation::User::user + + For details on how to use this property to interface between C++ and QML see + "\l {User - QPlaceUser} {Interfaces between C++ and QML Code}". +*/ +void QDeclarativePlaceUser::setUser(const QPlaceUser &user) +{ + QPlaceUser previousUser = m_user; + m_user = user; + + if (m_user.userId() != previousUser.userId()) + emit userIdChanged(); + + if (m_user.name() != previousUser.name()) + emit nameChanged(); +} + +QPlaceUser QDeclarativePlaceUser::user() const +{ + return m_user; +} + +/*! + \qmlproperty string QtLocation::User::userId + + This property holds the unique identifier of the user. +*/ + +void QDeclarativePlaceUser::setUserId(const QString &id) +{ + if (m_user.userId() == id) + return; + + m_user.setUserId(id); + emit userIdChanged(); +} + +QString QDeclarativePlaceUser::userId() const +{ + return m_user.userId(); +} + +/*! + \qmlproperty string QtLocation::User::name + + This property holds the name of a user. +*/ +void QDeclarativePlaceUser::setName(const QString &name) +{ + if (m_user.name() == name) + return; + + m_user.setName(name); + emit nameChanged(); +} + +QString QDeclarativePlaceUser::name() const +{ + return m_user.name(); +} + diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceuser_p.h b/src/imports/location/declarativeplaces/qdeclarativeplaceuser_p.h new file mode 100644 index 0000000..6c6ecec --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceuser_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPLACEUSER_P_H +#define QDECLARATIVEPLACEUSER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativePlaceUser : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPlaceUser user READ user WRITE setUser) + Q_PROPERTY(QString userId READ userId WRITE setUserId NOTIFY userIdChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + +public: + explicit QDeclarativePlaceUser(QObject *parent = 0); + explicit QDeclarativePlaceUser(const QPlaceUser &src, QObject *parent = 0); + ~QDeclarativePlaceUser(); + + QPlaceUser user() const; + void setUser(const QPlaceUser &src); + + QString userId() const; + void setUserId(const QString &id); + + QString name() const; + void setName(const QString &name); + +Q_SIGNALS: + void userIdChanged(); + void nameChanged(); + +private: + QPlaceUser m_user; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativePlaceUser) + +#endif diff --git a/src/imports/location/declarativeplaces/qdeclarativeratings.cpp b/src/imports/location/declarativeplaces/qdeclarativeratings.cpp new file mode 100644 index 0000000..ff04412 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeratings.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeratings_p.h" + +QT_USE_NAMESPACE + +/*! + \qmltype Ratings + \instantiates QDeclarativeRatings + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + \since Qt Location 5.5 + + \brief The Ratings type holds place rating information. + + Rating information is used to describe how \e good a place is conceived to be. Typically this + information is visualized as a number of stars. The \l average property gives an aggregated + ratings value out of a possible maximum as given by the \l maximum property. + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml Ratings +*/ + +QDeclarativeRatings::QDeclarativeRatings(QObject *parent) + : QObject(parent) {} + +QDeclarativeRatings::QDeclarativeRatings(const QPlaceRatings &rating, + QObject *parent) + : QObject(parent), + m_ratings(rating) {} + +QDeclarativeRatings::~QDeclarativeRatings() {} + +/*! + \qmlproperty QPlaceRatings Ratings::ratings + + For details on how to use this property to interface between C++ and QML see + "\l {Ratings - QPlaceRatings} {Interfaces between C++ and QML Code}". +*/ +void QDeclarativeRatings::setRatings(const QPlaceRatings &ratings) +{ + QPlaceRatings previous = m_ratings; + m_ratings = ratings; + + if (ratings.average() != previous.average()) { + emit averageChanged(); + } + if (ratings.count() != previous.count()) { + emit countChanged(); + } +} + +QPlaceRatings QDeclarativeRatings::ratings() const +{ + return m_ratings; +} + +/*! + \qmlproperty real Ratings::average + + This property holds the average of the individual ratings. + + \sa maximum +*/ +void QDeclarativeRatings::setAverage(qreal average) +{ + if (m_ratings.average() != average) { + m_ratings.setAverage(average); + emit averageChanged(); + } +} + +qreal QDeclarativeRatings::average() const +{ + return m_ratings.average(); +} + +/*! + \qmlproperty real Ratings::maximum + + This property holds the maximum rating value. +*/ +void QDeclarativeRatings::setMaximum(qreal max) +{ + if (m_ratings.maximum() == max) + return; + + m_ratings.setMaximum(max); + emit maximumChanged(); +} + +qreal QDeclarativeRatings::maximum() const +{ + return m_ratings.maximum(); +} + +/*! + \qmlproperty int Ratings::count + + This property holds the total number of individual user ratings + used in determining the overall ratings \l average. +*/ +void QDeclarativeRatings::setCount(int count) +{ + if (m_ratings.count() != count) { + m_ratings.setCount(count); + emit countChanged(); + } +} + +int QDeclarativeRatings::count() const +{ + return m_ratings.count(); +} + diff --git a/src/imports/location/declarativeplaces/qdeclarativeratings_p.h b/src/imports/location/declarativeplaces/qdeclarativeratings_p.h new file mode 100644 index 0000000..7583e70 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativeratings_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVERATINGS_P_H +#define QDECLARATIVERATINGS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeRatings : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPlaceRatings ratings READ ratings WRITE setRatings) + Q_PROPERTY(qreal average READ average WRITE setAverage NOTIFY averageChanged) + Q_PROPERTY(qreal maximum READ maximum WRITE setMaximum NOTIFY maximumChanged) + Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged) + +public: + explicit QDeclarativeRatings(QObject *parent = 0); + explicit QDeclarativeRatings(const QPlaceRatings &src, QObject *parent = 0); + ~QDeclarativeRatings(); + + QPlaceRatings ratings() const; + void setRatings(const QPlaceRatings &src); + + qreal average() const; + void setAverage(qreal average); + + qreal maximum() const; + void setMaximum(qreal max); + + int count() const; + void setCount(int count); + +Q_SIGNALS: + void averageChanged(); + void maximumChanged(); + void countChanged(); + +private: + QPlaceRatings m_ratings; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeRatings) + +#endif // QDECLARATIVERATING_P_H diff --git a/src/imports/location/declarativeplaces/qdeclarativereviewmodel.cpp b/src/imports/location/declarativeplaces/qdeclarativereviewmodel.cpp new file mode 100644 index 0000000..b7237bc --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativereviewmodel.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativereviewmodel_p.h" +#include "qdeclarativesupplier_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype ReviewModel + \instantiates QDeclarativeReviewModel + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-models + \since Qt Location 5.5 + + \brief Provides access to reviews of a \l Place. + + The ReviewModel is a read-only model used to fetch reviews about a \l Place. The model + incrementally fetches. The number of reviews which are fetched at a time is specified + by the \l batchSize property. The total number of reviews available can be accessed via the + \l totalCount property. + + To use the ReviewModel we need a view and a delegate. In this snippet we + see the setting up of a ListView with a ReviewModel model and a delegate. + + \snippet places/views/ReviewView.qml ReviewModel delegate + + The model returns data for the following roles: + + \table + \header + \li Role + \li Type + \li Description + \row + \li dateTime + \li datetime + \li The date and time that the review was posted. + \row + \li text + \li string + \li The review's textual description of the place. It can be either rich (HTML based) text or plain text + depending on the provider. + \row + \li language + \li string + \li The language that the review is written in. + \row + \li rating + \li real + \li The rating that the reviewer gave to the place. + \row + \li reviewId + \li string + \li The identifier of the review. + \row + \li title + \li string + \li The title of the review. + \row + \li supplier + \li \l Supplier + \li The supplier of the review. + \row + \li user + \li \l {QtLocation::User}{User} + \li The user who contributed the review. + \row + \li attribution + \li string + \li Attribution text which must be displayed when displaying the review. + \endtable +*/ + +/*! + \qmlproperty Place QtLocation::ReviewModel::place + + This property holds the Place that the reviews are for. +*/ + +/*! + \qmlproperty int QtLocation::ReviewModel::batchSize + + This property holds the batch size to use when fetching more reviews. +*/ + +/*! + \qmlproperty int QtLocation::ReviewModel::totalCount + + This property holds the total number of reviews for the place. +*/ + +QDeclarativeReviewModel::QDeclarativeReviewModel(QObject *parent) +: QDeclarativePlaceContentModel(QPlaceContent::ReviewType, parent) +{ +} + +QDeclarativeReviewModel::~QDeclarativeReviewModel() +{ + qDeleteAll(m_suppliers); +} + +/*! + \internal +*/ +QVariant QDeclarativeReviewModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= rowCount(index.parent()) || index.row() < 0) + return QVariant(); + + const QPlaceReview &review = m_content.value(index.row()); + + switch (role) { + case DateTimeRole: + return review.dateTime(); + case TextRole: + return review.text(); + case LanguageRole: + return review.language(); + case RatingRole: + return review.rating(); + case ReviewIdRole: + return review.reviewId(); + case TitleRole: + return review.title(); + } + + return QDeclarativePlaceContentModel::data(index, role); +} + +QHash QDeclarativeReviewModel::roleNames() const +{ + QHash roles = QDeclarativePlaceContentModel::roleNames(); + roles.insert(DateTimeRole, "dateTime"); + roles.insert(TextRole, "text"); + roles.insert(LanguageRole, "language"); + roles.insert(RatingRole, "rating"); + roles.insert(ReviewIdRole, "reviewId"); + roles.insert(TitleRole, "title"); + return roles; +} + +QT_END_NAMESPACE diff --git a/src/imports/location/declarativeplaces/qdeclarativereviewmodel_p.h b/src/imports/location/declarativeplaces/qdeclarativereviewmodel_p.h new file mode 100644 index 0000000..06bf7aa --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativereviewmodel_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEREVIEWMODEL_P_H +#define QDECLARATIVEREVIEWMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativeplacecontentmodel.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativeReviewModel : public QDeclarativePlaceContentModel +{ + Q_OBJECT + +public: + explicit QDeclarativeReviewModel(QObject *parent = 0); + ~QDeclarativeReviewModel(); + + QVariant data(const QModelIndex &index, int role) const; + QHash roleNames() const; + enum Roles { + DateTimeRole = UserRole, + TextRole, + LanguageRole, + RatingRole, + ReviewIdRole, + TitleRole + }; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEREVIEWMODEL_P_H diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.cpp b/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.cpp new file mode 100644 index 0000000..acfb54d --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.cpp @@ -0,0 +1,358 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativesearchmodelbase.h" +#include "qdeclarativeplace_p.h" +#include "error_messages.h" + +#include +#include +#include +#include +#include +#include +#include + +QDeclarativeSearchModelBase::QDeclarativeSearchModelBase(QObject *parent) +: QAbstractListModel(parent), m_plugin(0), m_reply(0), m_complete(false), m_status(Null) +{ +} + +QDeclarativeSearchModelBase::~QDeclarativeSearchModelBase() +{ +} + +/*! + \internal +*/ +QDeclarativeGeoServiceProvider *QDeclarativeSearchModelBase::plugin() const +{ + return m_plugin; +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::setPlugin(QDeclarativeGeoServiceProvider *plugin) +{ + if (m_plugin == plugin) + return; + + initializePlugin(plugin); + + if (m_complete) + emit pluginChanged(); +} + +/*! + \internal +*/ +QVariant QDeclarativeSearchModelBase::searchArea() const +{ + QGeoShape s = m_request.searchArea(); + if (s.type() == QGeoShape::RectangleType) + return QVariant::fromValue(QGeoRectangle(s)); + else if (s.type() == QGeoShape::CircleType) + return QVariant::fromValue(QGeoCircle(s)); + else + return QVariant::fromValue(s); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::setSearchArea(const QVariant &searchArea) +{ + QGeoShape s; + + if (searchArea.userType() == qMetaTypeId()) + s = searchArea.value(); + else if (searchArea.userType() == qMetaTypeId()) + s = searchArea.value(); + else if (searchArea.userType() == qMetaTypeId()) + s = searchArea.value(); + + if (m_request.searchArea() == s) + return; + + m_request.setSearchArea(s); + emit searchAreaChanged(); +} + +/*! + \internal +*/ +int QDeclarativeSearchModelBase::limit() const +{ + return m_request.limit(); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::setLimit(int limit) +{ + if (m_request.limit() == limit) + return; + + m_request.setLimit(limit); + emit limitChanged(); +} + +/*! + \internal +*/ +bool QDeclarativeSearchModelBase::previousPagesAvailable() const +{ + return m_previousPageRequest != QPlaceSearchRequest(); +} + +/*! + \internal +*/ +bool QDeclarativeSearchModelBase::nextPagesAvailable() const +{ + return m_nextPageRequest != QPlaceSearchRequest(); +} + +/*! + \internal +*/ +QDeclarativeSearchModelBase::Status QDeclarativeSearchModelBase::status() const +{ + return m_status; +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::setStatus(Status status, const QString &errorString) +{ + Status prevStatus = m_status; + + m_status = status; + m_errorString = errorString; + + if (prevStatus != m_status) + emit statusChanged(); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::update() +{ + if (m_reply) + return; + + setStatus(Loading); + + if (!m_plugin) { + clearData(); + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROPERTY_NOT_SET)); + return; + } + + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (!serviceProvider) { + clearData(); + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROVIDER_ERROR) + .arg(m_plugin->name())); + return; + } + + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (!placeManager) { + clearData(); + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR) + .arg(m_plugin->name()).arg(serviceProvider->errorString())); + return; + } + + m_reply = sendQuery(placeManager, m_request); + if (!m_reply) { + clearData(); + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, UNABLE_TO_MAKE_REQUEST)); + return; + } + + m_reply->setParent(this); + connect(m_reply, SIGNAL(finished()), this, SLOT(queryFinished())); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::cancel() +{ + if (!m_reply) + return; + + if (!m_reply->isFinished()) + m_reply->abort(); + + if (m_reply) { + m_reply->deleteLater(); + m_reply = 0; + } + + setStatus(Ready); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::reset() +{ + beginResetModel(); + clearData(); + setStatus(Null); + endResetModel(); +} + +/*! + \internal +*/ +QString QDeclarativeSearchModelBase::errorString() const +{ + return m_errorString; +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::previousPage() +{ + if (m_previousPageRequest == QPlaceSearchRequest()) + return; + + m_request = m_previousPageRequest; + update(); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::nextPage() +{ + if (m_nextPageRequest == QPlaceSearchRequest()) + return; + + m_request = m_nextPageRequest; + update(); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::clearData(bool suppressSignal) +{ + Q_UNUSED(suppressSignal) +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::classBegin() +{ +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::componentComplete() +{ + m_complete = true; +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::initializePlugin(QDeclarativeGeoServiceProvider *plugin) +{ + beginResetModel(); + if (plugin != m_plugin) { + if (m_plugin) + disconnect(m_plugin, SIGNAL(nameChanged(QString)), this, SLOT(pluginNameChanged())); + if (plugin) + connect(plugin, SIGNAL(nameChanged(QString)), this, SLOT(pluginNameChanged())); + m_plugin = plugin; + } + + if (m_plugin) { + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (serviceProvider) { + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (placeManager) { + if (placeManager->childCategoryIds().isEmpty()) { + QPlaceReply *reply = placeManager->initializeCategories(); + connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater())); + } + } + } + } + + endResetModel(); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::pluginNameChanged() +{ + initializePlugin(m_plugin); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::setPreviousPageRequest(const QPlaceSearchRequest &previous) +{ + if (m_previousPageRequest == previous) + return; + + m_previousPageRequest = previous; + emit previousPagesAvailableChanged(); +} + +void QDeclarativeSearchModelBase::setNextPageRequest(const QPlaceSearchRequest &next) +{ + if (m_nextPageRequest == next) + return; + + m_nextPageRequest = next; + emit nextPagesAvailableChanged(); +} diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.h b/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.h new file mode 100644 index 0000000..4547045 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESEARCHMODELBASE_H +#define QDECLARATIVESEARCHMODELBASE_H + +#include +#include +#include +#include +#include + +#include "qdeclarativegeoserviceprovider_p.h" + +QT_BEGIN_NAMESPACE + +class QPlaceManager; +class QPlaceSearchRequest; +class QPlaceSearchReply; +class QDeclarativePlace; + +class QDeclarativeSearchModelBase : public QAbstractListModel, public QQmlParserStatus +{ + Q_OBJECT + + Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) + Q_PROPERTY(QVariant searchArea READ searchArea WRITE setSearchArea NOTIFY searchAreaChanged) + Q_PROPERTY(int limit READ limit WRITE setLimit NOTIFY limitChanged) + Q_PROPERTY(bool previousPagesAvailable READ previousPagesAvailable NOTIFY previousPagesAvailableChanged) + Q_PROPERTY(bool nextPagesAvailable READ nextPagesAvailable NOTIFY nextPagesAvailableChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + + Q_ENUMS(Status) + + Q_INTERFACES(QQmlParserStatus) + +public: + enum Status { + Null, + Ready, + Loading, + Error + }; + + explicit QDeclarativeSearchModelBase(QObject *parent = 0); + ~QDeclarativeSearchModelBase(); + + QDeclarativeGeoServiceProvider *plugin() const; + void setPlugin(QDeclarativeGeoServiceProvider *plugin); + + QVariant searchArea() const; + void setSearchArea(const QVariant &searchArea); + + int limit() const; + void setLimit(int limit); + + bool previousPagesAvailable() const; + bool nextPagesAvailable() const; + + Status status() const; + void setStatus(Status status, const QString &errorString = QString()); + + Q_INVOKABLE void update(); + + Q_INVOKABLE void cancel(); + Q_INVOKABLE void reset(); + + Q_INVOKABLE QString errorString() const; + + Q_INVOKABLE void previousPage(); + Q_INVOKABLE void nextPage(); + + virtual void clearData(bool suppressSignal = false); + + // From QQmlParserStatus + virtual void classBegin(); + virtual void componentComplete(); + +Q_SIGNALS: + void pluginChanged(); + void searchAreaChanged(); + void limitChanged(); + void previousPagesAvailableChanged(); + void nextPagesAvailableChanged(); + void statusChanged(); + +protected: + virtual void initializePlugin(QDeclarativeGeoServiceProvider *plugin); + +protected Q_SLOTS: + virtual void queryFinished() = 0; + +private Q_SLOTS: + void pluginNameChanged(); + +protected: + virtual QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request) = 0; + void setPreviousPageRequest(const QPlaceSearchRequest &previous); + void setNextPageRequest(const QPlaceSearchRequest &next); + + QPlaceSearchRequest m_request; + QDeclarativeGeoServiceProvider *m_plugin; + QPlaceReply *m_reply; + +private: + bool m_complete; + Status m_status; + QString m_errorString; + QPlaceSearchRequest m_previousPageRequest; + QPlaceSearchRequest m_nextPageRequest; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVESEARCHMODELBASE_H diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel.cpp b/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel.cpp new file mode 100644 index 0000000..3c7c261 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel.cpp @@ -0,0 +1,916 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativesearchresultmodel_p.h" +#include "qdeclarativeplace_p.h" +#include "qdeclarativeplaceicon_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +/*! + \qmltype PlaceSearchModel + \instantiates QDeclarativeSearchResultModel + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-models + \since Qt Location 5.5 + + \brief Provides access to place search results. + + PlaceSearchModel provides a model of place search results within the \l searchArea. The + \l searchTerm and \l categories properties can be set to restrict the search results to + places matching those criteria. + + The PlaceSearchModel returns both sponsored and + \l {http://en.wikipedia.org/wiki/Organic_search}{organic search results}. Sponsored search + results will have the \c sponsored role set to true. + + \target PlaceSearchModel Roles + The model returns data for the following roles: + + \table + \header + \li Role + \li Type + \li Description + \row + \li type + \li enum + \li The type of search result. + \row + \li title + \li string + \li A string describing the search result. + \row + \li icon + \li PlaceIcon + \li Icon representing the search result. + \row + \li distance + \li real + \li Valid only when the \c type role is \c PlaceResult, the distance to the place + from the center of the \l searchArea. If no \l searchArea + has been specified, the distance is NaN. + \row + \li place + \li \l Place + \li Valid only when the \c type role is \c PlaceResult, an object representing the + place. + \row + \li sponsored + \li bool + \li Valid only when the \c type role is \c PlaceResult, true if the search result is a + sponsored result. + \endtable + + \section2 Search Result Types + + The \c type role can take on the following values: + + \table + \row + \li PlaceSearchModel.UnknownSearchResult + \li The contents of the search result are unknown. + \row + \li PlaceSearchModel.PlaceResult + \li The search result contains a place. + \row + \li PlaceSearchModel.ProposedSearchResult + \li The search result contains a proposed search which may be relevant. + \endtable + + + It can often be helpful to use a \l Loader to create a delegate + that will choose different \l {Component}s based on the search result type. + + \snippet declarative/places_loader.qml Handle Result Types + + \section1 Detection of Updated and Removed Places + + The PlaceSearchModel listens for places that have been updated or removed from its plugin's backend. + If it detects that a place has been updated and that place is currently present in the model, then + it will call \l Place::getDetails to refresh the details. If it detects that a place has been + removed, then correspondingly the place will be removed from the model if it is currently + present. + + \section1 Example + + The following example shows how to use the PlaceSearchModel to search for Pizza restaurants in + close proximity of a given position. A \l searchTerm and \l searchArea are provided to the model + and \l update() is used to perform a lookup query. Note that the model does not incrementally + fetch search results, but rather performs a single fetch when \l update() is run. The \l count + is set to the number of search results returned during the fetch. + + \snippet places_list/places_list.qml Imports + \codeline + \snippet places_list/places_list.qml PlaceSearchModel + + \sa CategoryModel, {QPlaceManager} + + \section1 Paging + The PlaceSearchModel API has some limited support + for paging. The \l nextPage() and \l previousPage() functions as well as + the \l limit property can be used to access + paged search results. When the \l limit property is set + the search result page contains at most \l limit entries (of type place result). + For example, if the backend has 5 search results in total + [a,b,c,d,e], and assuming the first page is shown and limit of 3 has been set + then a,b,c is returned. The \l nextPage() would return d,e. The + \l nextPagesAvailable and \l previousPagesAvailable properties + can be used to check for further pages. At the moment the API does not + support the means to retrieve the total number of items available from the + backed. Note that support for \l nextPage(), previousPage() and \l limit can vary + according to the \l plugin. +*/ + +/*! + \qmlproperty Plugin PlaceSearchModel::plugin + + This property holds the \l Plugin which will be used to perform the search. +*/ + +/*! + \qmlproperty Plugin PlaceSearchModel::favoritesPlugin + + This property holds the \l Plugin which will be used to search for favorites. + Any places from the search which can be cross-referenced or matched + in the favoritesPlugin will have their \l {Place::favorite}{favorite} property + set to the corresponding \l Place from the favoritesPlugin. + + If the favoritesPlugin is not set, the \l {Place::favorite}{favorite} property + of the places in the results will always be null. + + \sa Favorites +*/ + +/*! + \qmlproperty VariantMap PlaceSearchModel::favoritesMatchParameters + + This property holds a set of parameters used to specify how search result places + are matched to favorites in the favoritesPlugin. + + By default the parameter map is empty and implies that the favorites plugin + matches by \l {Alternative Identifier Cross-Referencing}{alternative identifiers}. Generally, + an application developer will not need to set this property. + + In cases where the favorites plugin does not support matching by alternative identifiers, + then the \l {Qt Location#Plugin References and Parameters}{plugin documentation} should + be consulted to see precisely what key-value parameters to set. +*/ + +/*! + \qmlproperty variant PlaceSearchModel::searchArea + + This property holds the search area. The search result returned by the model will be within + the search area. + + If this property is set to a \l {geocircle} its + \l {geocircle}{radius} property may be left unset, in which case the \l Plugin + will choose an appropriate radius for the search. + + Support for specifying a search area can vary according to the \l plugin backend + implementation. For example, some may support a search center only while others may only + support geo rectangles. +*/ + +/*! + \qmlproperty int PlaceSearchModel::limit + + This property holds the limit of the number of items that will be returned. +*/ + +/*! + \qmlproperty bool PlaceSearchModel::previousPagesAvailable + + This property holds whether there is one or more previous pages of search results available. + + \sa previousPage() +*/ + +/*! + \qmlproperty bool PlaceSearchModel::nextPagesAvailable + + This property holds whether there is one or more additional pages of search results available. + + \sa nextPage() +*/ + +/*! + \qmlproperty enum PlaceSearchModel::status + + This property holds the status of the model. It can be one of: + + \table + \row + \li PlaceSearchModel.Null + \li No search query has been executed. The model is empty. + \row + \li PlaceSearchModel.Ready + \li The search query has completed, and the results are available. + \row + \li PlaceSearchModel.Loading + \li A search query is currently being executed. + \row + \li PlaceSearchModel.Error + \li An error occurred when executing the previous search query. + \endtable +*/ + +/*! + \qmlmethod void PlaceSearchModel::update() + + Updates the model based on the provided query parameters. The model will be populated with a + list of places matching the search parameters specified by the type's properties. Search + criteria is specified by setting properties such as the \l searchTerm, \l categories, \l searchArea and \l limit. + Support for these properties may vary according to \l plugin. \c update() then + submits the set of criteria to the \l plugin to process. + + While the model is updating the \l status of the model is set to + \c PlaceSearchModel.Loading. If the model is successfully updated the \l status is set to + \c PlaceSearchModel.Ready, while if it unsuccessfully completes, the \l status is set to + \c PlaceSearchModel.Error and the model cleared. + + \code + PlaceSearchModel { + id: model + plugin: backendPlugin + searchArea: QtPositioning.circle(QtPositioning.coordinate(10, 10)) + ... + } + + MouseArea { + ... + onClicked: { + model.searchTerm = "pizza"; + model.categories = null; //not searching by any category + model.searchArea.center.latitude = -27.5; + model.searchArea.center.longitude = 153; + model.update(); + } + } + \endcode + + \sa cancel(), status +*/ + +/*! + \qmlmethod void PlaceSearchModel::cancel() + + Cancels an ongoing search operation immediately and sets the model + status to PlaceSearchModel.Ready. The model retains any search + results it had before the operation was started. + + If an operation is not ongoing, invoking cancel() has no effect. + + \sa update(), status +*/ + +/*! + \qmlmethod void PlaceSearchModel::reset() + + Resets the model. All search results are cleared, any outstanding requests are aborted and + possible errors are cleared. Model status will be set to PlaceSearchModel.Null. +*/ + +/*! + \qmlmethod string PlaceSearchModel::errorString() const + + This read-only property holds the textual presentation of the latest place search model error. + If no error has occurred or if the model was cleared, an empty string is returned. + + An empty string may also be returned if an error occurred which has no associated + textual representation. +*/ + +/*! + \qmlmethod void PlaceSearchModel::previousPage() + + Updates the model to display the previous page of search results. If there is no previous page + then this method does nothing. +*/ + +/*! + \qmlmethod void PlaceSearchModel::nextPage() + + Updates the model to display the next page of search results. If there is no next page then + this method does nothing. +*/ + +QDeclarativeSearchResultModel::QDeclarativeSearchResultModel(QObject *parent) + : QDeclarativeSearchModelBase(parent), m_favoritesPlugin(0) +{ +} + +QDeclarativeSearchResultModel::~QDeclarativeSearchResultModel() +{ +} + +/*! + \qmlproperty string PlaceSearchModel::searchTerm + + This property holds search term used in query. The search term is a free-form text string. +*/ +QString QDeclarativeSearchResultModel::searchTerm() const +{ + return m_request.searchTerm(); +} + +void QDeclarativeSearchResultModel::setSearchTerm(const QString &searchTerm) +{ + m_request.setSearchContext(QVariant()); + + if (m_request.searchTerm() == searchTerm) + return; + + m_request.setSearchTerm(searchTerm); + emit searchTermChanged(); +} + +/*! + \qmlproperty list PlaceSearchModel::categories + + This property holds a list of categories to be used when searching. Returned search results + will be for places that match at least one of the categories. +*/ +QQmlListProperty QDeclarativeSearchResultModel::categories() +{ + return QQmlListProperty(this, + 0, // opaque data parameter + categories_append, + categories_count, + category_at, + categories_clear); +} + +void QDeclarativeSearchResultModel::categories_append(QQmlListProperty *list, + QDeclarativeCategory *declCategory) +{ + QDeclarativeSearchResultModel *searchModel = qobject_cast(list->object); + if (searchModel && declCategory) { + searchModel->m_request.setSearchContext(QVariant()); + searchModel->m_categories.append(declCategory); + QList categories = searchModel->m_request.categories(); + categories.append(declCategory->category()); + searchModel->m_request.setCategories(categories); + emit searchModel->categoriesChanged(); + } +} + +int QDeclarativeSearchResultModel::categories_count(QQmlListProperty *list) +{ + QDeclarativeSearchResultModel *searchModel = qobject_cast(list->object); + if (searchModel) + return searchModel->m_categories.count(); + else + return -1; +} + +QDeclarativeCategory *QDeclarativeSearchResultModel::category_at(QQmlListProperty *list, + int index) +{ + QDeclarativeSearchResultModel *searchModel = qobject_cast(list->object); + if (searchModel && (searchModel->m_categories.count() > index) && (index > -1)) + return searchModel->m_categories.at(index); + else + return 0; +} + +void QDeclarativeSearchResultModel::categories_clear(QQmlListProperty *list) +{ + QDeclarativeSearchResultModel *searchModel = qobject_cast(list->object); + if (searchModel) { + //note: we do not need to delete each of the objects in m_categories since the search model + //should never be the parent of the categories anyway. + searchModel->m_request.setSearchContext(QVariant()); + searchModel->m_categories.clear(); + searchModel->m_request.setCategories(QList()); + emit searchModel->categoriesChanged(); + } +} + +/*! + \qmlproperty string PlaceSearchModel::recommendationId + + This property holds the placeId to be used in order to find recommendations + for similar places. +*/ +QString QDeclarativeSearchResultModel::recommendationId() const +{ + return m_request.recommendationId(); +} + +void QDeclarativeSearchResultModel::setRecommendationId(const QString &placeId) +{ + if (m_request.recommendationId() == placeId) + return; + + m_request.setRecommendationId(placeId); + emit recommendationIdChanged(); +} + +/*! + \qmlproperty enumeration PlaceSearchModel::relevanceHint + + This property holds a relevance hint used in the search query. The hint is given to the + provider to help but not dictate the ranking of results. For example, the distance hint may + give closer places a higher ranking but it does not necessarily mean the results will be + strictly ordered according to distance. A provider may ignore the hint altogether. + + \table + \row + \li SearchResultModel.UnspecifiedHint + \li No relevance hint is given to the provider. + \row + \li SearchResultModel.DistanceHint + \li The distance of the place from the user's current location is important to the user. + This hint is only meaningful when a circular search area is used. + \row + \li SearchResultModel.LexicalPlaceNameHint + \li The lexical ordering of place names (in ascending alphabetical order) is relevant to + the user. This hint is useful for providers based on a local data store. + \endtable +*/ +QDeclarativeSearchResultModel::RelevanceHint QDeclarativeSearchResultModel::relevanceHint() const +{ + return static_cast(m_request.relevanceHint()); +} + +void QDeclarativeSearchResultModel::setRelevanceHint(QDeclarativeSearchResultModel::RelevanceHint hint) +{ + if (m_request.relevanceHint() != static_cast(hint)) { + m_request.setRelevanceHint(static_cast(hint)); + emit relevanceHintChanged(); + } +} + +/*! + \qmlproperty enum PlaceSearchModel::visibilityScope + + This property holds the visibility scope of the places to search. Only places with the + specified visibility will be returned in the search results. + + The visibility scope can be one of: + + \table + \row + \li Place.UnspecifiedVisibility + \li No explicit visibility scope specified, places with any visibility may be part of + search results. + \row + \li Place.DeviceVisibility + \li Only places stored on the local device will be part of the search results. + \row + \li Place.PrivateVisibility + \li Only places that are private to the current user will be part of the search results. + \row + \li Place.PublicVisibility + \li Only places that are public will be part of the search results. + \endtable +*/ +QDeclarativePlace::Visibility QDeclarativeSearchResultModel::visibilityScope() const +{ + return QDeclarativePlace::Visibility(int(m_visibilityScope)); +} + +void QDeclarativeSearchResultModel::setVisibilityScope(QDeclarativePlace::Visibility visibilityScope) +{ + QLocation::VisibilityScope scope = QLocation::VisibilityScope(visibilityScope); + + if (m_visibilityScope == scope) + return; + + m_visibilityScope = scope; + emit visibilityScopeChanged(); +} + +/*! + \internal +*/ +QDeclarativeGeoServiceProvider *QDeclarativeSearchResultModel::favoritesPlugin() const +{ + return m_favoritesPlugin; +} + +/*! + \internal +*/ +void QDeclarativeSearchResultModel::setFavoritesPlugin(QDeclarativeGeoServiceProvider *plugin) +{ + + if (m_favoritesPlugin == plugin) + return; + + m_favoritesPlugin = plugin; + + if (m_favoritesPlugin) { + QGeoServiceProvider *serviceProvider = m_favoritesPlugin->sharedGeoServiceProvider(); + if (serviceProvider) { + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (placeManager) { + if (placeManager->childCategoryIds().isEmpty()) { + QPlaceReply *reply = placeManager->initializeCategories(); + connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater())); + } + } + } + } + + emit favoritesPluginChanged(); +} + +/*! + \internal +*/ +QVariantMap QDeclarativeSearchResultModel::favoritesMatchParameters() const +{ + return m_matchParameters; +} + +/*! + \internal +*/ +void QDeclarativeSearchResultModel::setFavoritesMatchParameters(const QVariantMap ¶meters) +{ + if (m_matchParameters == parameters) + return; + + m_matchParameters = parameters; + emit favoritesMatchParametersChanged(); +} + +/*! + \internal +*/ +int QDeclarativeSearchResultModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return m_results.count(); +} + +void QDeclarativeSearchResultModel::clearData(bool suppressSignal) +{ + QDeclarativeSearchModelBase::clearData(suppressSignal); + + qDeleteAll(m_places); + m_places.clear(); + qDeleteAll(m_icons); + m_icons.clear(); + if (!m_results.isEmpty()) { + m_results.clear(); + + if (!suppressSignal) + emit rowCountChanged(); + } +} + +QVariant QDeclarativeSearchResultModel::data(const QModelIndex &index, int role) const +{ + if (index.row() > m_results.count()) + return QVariant(); + + const QPlaceSearchResult &result = m_results.at(index.row()); + + switch (role) { + case SearchResultTypeRole: + return result.type(); + case Qt::DisplayRole: + case TitleRole: + return result.title(); + case IconRole: + return QVariant::fromValue(static_cast(m_icons.at(index.row()))); + case DistanceRole: + if (result.type() == QPlaceSearchResult::PlaceResult) { + QPlaceResult placeResult = result; + return placeResult.distance(); + } + break; + case PlaceRole: + if (result.type() == QPlaceSearchResult::PlaceResult) + return QVariant::fromValue(static_cast(m_places.at(index.row()))); + case SponsoredRole: + if (result.type() == QPlaceSearchResult::PlaceResult) { + QPlaceResult placeResult = result; + return placeResult.isSponsored(); + } + break; + } + return QVariant(); +} + +/*! + \internal +*/ +QVariant QDeclarativeSearchResultModel::data(int index, const QString &role) const +{ + QModelIndex modelIndex = createIndex(index, 0); + return data(modelIndex, roleNames().key(role.toLatin1())); +} + +QHash QDeclarativeSearchResultModel::roleNames() const +{ + QHash roles = QDeclarativeSearchModelBase::roleNames(); + roles.insert(SearchResultTypeRole, "type"); + roles.insert(TitleRole, "title"); + roles.insert(IconRole, "icon"); + roles.insert(DistanceRole, "distance"); + roles.insert(PlaceRole, "place"); + roles.insert(SponsoredRole, "sponsored"); + + return roles; +} + +/*! + \qmlmethod void PlaceSearchModel::updateWith(int proposedSearchIndex) + + Updates the model based on the ProposedSearchResult at index \a proposedSearchIndex. The model + will be populated with a list of places matching the proposed search. Model status will be set + to PlaceSearchModel.Loading. If the model is updated successfully status will be set to + PlaceSearchModel.Ready. If an error occurs status will be set to PlaceSearchModel.Error and the + model cleared. + + If \a proposedSearchIndex does not reference a ProposedSearchResult this method does nothing. +*/ +void QDeclarativeSearchResultModel::updateWith(int proposedSearchIndex) +{ + if (m_results.at(proposedSearchIndex).type() != QPlaceSearchResult::ProposedSearchResult) + return; + + m_request = QPlaceProposedSearchResult(m_results.at(proposedSearchIndex)).searchRequest(); + update(); +} + +QPlaceReply *QDeclarativeSearchResultModel::sendQuery(QPlaceManager *manager, + const QPlaceSearchRequest &request) +{ + Q_ASSERT(manager); + return manager->search(request); +} + +/*! + \internal +*/ +void QDeclarativeSearchResultModel::initializePlugin(QDeclarativeGeoServiceProvider *plugin) +{ + //disconnect the manager of the old plugin if we have one + if (m_plugin) { + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (serviceProvider) { + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (placeManager) { + disconnect(placeManager, SIGNAL(placeUpdated(QString)), this, SLOT(placeUpdated(QString))); + disconnect(placeManager, SIGNAL(placeRemoved(QString)), this, SLOT(placeRemoved(QString))); + connect(placeManager, SIGNAL(dataChanged()), this, SIGNAL(dataChanged())); + } + } + } + + //connect to the manager of the new plugin. + if (plugin) { + QGeoServiceProvider *serviceProvider = plugin->sharedGeoServiceProvider(); + if (serviceProvider) { + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (placeManager) { + connect(placeManager, SIGNAL(placeUpdated(QString)), this, SLOT(placeUpdated(QString))); + connect(placeManager, SIGNAL(placeRemoved(QString)), this, SLOT(placeRemoved(QString))); + disconnect(placeManager, SIGNAL(dataChanged()), this, SIGNAL(dataChanged())); + } + } + } + QDeclarativeSearchModelBase::initializePlugin(plugin); +} + +/*! + \internal +*/ +void QDeclarativeSearchResultModel::queryFinished() +{ + if (!m_reply) + return; + QPlaceReply *reply = m_reply; + m_reply = 0; + if (reply->error() != QPlaceReply::NoError) { + m_resultsBuffer.clear(); + updateLayout(); + setStatus(Error, reply->errorString()); + reply->deleteLater(); + return; + } + + if (reply->type() == QPlaceReply::SearchReply) { + QPlaceSearchReply *searchReply = qobject_cast(reply); + Q_ASSERT(searchReply); + + m_resultsBuffer = searchReply->results(); + setPreviousPageRequest(searchReply->previousPageRequest()); + setNextPageRequest(searchReply->nextPageRequest()); + + reply->deleteLater(); + + if (!m_favoritesPlugin) { + updateLayout(); + setStatus(Ready); + } else { + QGeoServiceProvider *serviceProvider = m_favoritesPlugin->sharedGeoServiceProvider(); + if (!serviceProvider) { + updateLayout(); + setStatus(Error, QStringLiteral("Favorites plugin returns a null QGeoServiceProvider instance")); + return; + } + + QPlaceManager *favoritesManager = serviceProvider->placeManager(); + if (!favoritesManager) { + updateLayout(); + setStatus(Error, QStringLiteral("Favorites plugin returns a null QPlaceManager")); + return; + } + + QPlaceMatchRequest request; + if (m_matchParameters.isEmpty()) { + if (!m_plugin) { + reply->deleteLater(); + setStatus(Error, QStringLiteral("Plugin not assigned")); + return; + } + + QVariantMap params; + params.insert(QPlaceMatchRequest::AlternativeId, QString::fromLatin1("x_id_") + m_plugin->name()); + request.setParameters(params); + } else { + request.setParameters(m_matchParameters); + } + + request.setResults(m_resultsBuffer); + m_reply = favoritesManager->matchingPlaces(request); + connect(m_reply, SIGNAL(finished()), this, SLOT(queryFinished())); + } + } else if (reply->type() == QPlaceReply::MatchReply) { + QPlaceMatchReply *matchReply = qobject_cast(reply); + Q_ASSERT(matchReply); + updateLayout(matchReply->places()); + setStatus(Ready); + reply->deleteLater(); + } else { + setStatus(Error, QStringLiteral("Unknown reply type")); + reply->deleteLater(); + } +} + +/*! + \qmlmethod void PlaceSearchModel::data(int index, string role) + + Returns the data for a given \a role at the specified row \a index. +*/ + +/*! + \qmlproperty int PlaceSearchModel::count + + This property holds the number of results the model has. + + Note that it does not refer to the total number of search results + available in the backend. The total number of search results + is not currently supported by the API. +*/ + +/*! + \internal + Note: m_results buffer should be correctly populated before + calling this function +*/ +void QDeclarativeSearchResultModel::updateLayout(const QList &favoritePlaces) +{ + int oldRowCount = rowCount(); + + beginResetModel(); + clearData(true); + m_results = m_resultsBuffer; + m_resultsBuffer.clear(); + + for (int i = 0; i < m_results.count(); ++i) { + const QPlaceSearchResult &result = m_results.at(i); + + if (result.type() == QPlaceSearchResult::PlaceResult) { + QPlaceResult placeResult = result; + QDeclarativePlace *place = new QDeclarativePlace(placeResult.place(), plugin(), this); + m_places.append(place); + + if ((favoritePlaces.count() == m_results.count()) && favoritePlaces.at(i) != QPlace()) + m_places[i]->setFavorite(new QDeclarativePlace(favoritePlaces.at(i), + m_favoritesPlugin, m_places[i])); + } else if (result.type() == QPlaceSearchResult::ProposedSearchResult) { + m_places.append(0); + } + + QDeclarativePlaceIcon *icon = 0; + if (!result.icon().isEmpty()) + icon = new QDeclarativePlaceIcon(result.icon(), plugin(), this); + m_icons.append(icon); + } + + endResetModel(); + if (m_results.count() != oldRowCount) + emit rowCountChanged(); +} + +/*! + \internal +*/ +void QDeclarativeSearchResultModel::placeUpdated(const QString &placeId) +{ + int row = getRow(placeId); + if (row < 0 || row > m_places.count()) + return; + + if (m_places.at(row)) + m_places.at(row)->getDetails(); +} + +/*! + \internal +*/ +void QDeclarativeSearchResultModel::placeRemoved(const QString &placeId) +{ + int row = getRow(placeId); + if (row < 0 || row > m_places.count()) + return; + + beginRemoveRows(QModelIndex(), row, row); + delete m_places.at(row); + m_places.removeAt(row); + m_results.removeAt(row); + endRemoveRows(); + + emit rowCountChanged(); +} + +/*! + \internal +*/ +int QDeclarativeSearchResultModel::getRow(const QString &placeId) const +{ + for (int i = 0; i < m_places.count(); ++i) { + if (!m_places.at(i)) + continue; + else if (m_places.at(i)->placeId() == placeId) + return i; + } + + return -1; +} + +/*! + \qmlsignal PlaceSearchResultModel::dataChanged() + + This signal is emitted when significant changes have been made to the underlying datastore. + + Applications should act on this signal at their own discretion. The data + provided by the model could be out of date and so the model should be reupdated + sometime, however an immediate reupdate may be disconcerting to users if the results + change without any action on their part. + + The corresponding handler is \c onDataChanged. +*/ + diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel_p.h b/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel_p.h new file mode 100644 index 0000000..73bf16d --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel_p.h @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESEARCHRESULTMODEL_P_H +#define QDECLARATIVESEARCHRESULTMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativesearchmodelbase.h" +#include "qdeclarativecategory_p.h" +#include "qdeclarativeplace_p.h" +#include "qdeclarativeplaceicon_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoServiceProvider; + +class QDeclarativeSearchResultModel : public QDeclarativeSearchModelBase +{ + Q_OBJECT + + Q_PROPERTY(QString searchTerm READ searchTerm WRITE setSearchTerm NOTIFY searchTermChanged) + Q_PROPERTY(QQmlListProperty categories READ categories NOTIFY categoriesChanged) + Q_PROPERTY(QString recommendationId READ recommendationId WRITE setRecommendationId NOTIFY recommendationIdChanged) + Q_PROPERTY(RelevanceHint relevanceHint READ relevanceHint WRITE setRelevanceHint NOTIFY relevanceHintChanged) + Q_PROPERTY(QDeclarativePlace::Visibility visibilityScope READ visibilityScope WRITE setVisibilityScope NOTIFY visibilityScopeChanged) + + Q_PROPERTY(int count READ rowCount NOTIFY rowCountChanged) + Q_PROPERTY(QDeclarativeGeoServiceProvider *favoritesPlugin READ favoritesPlugin WRITE setFavoritesPlugin NOTIFY favoritesPluginChanged) + Q_PROPERTY(QVariantMap favoritesMatchParameters READ favoritesMatchParameters WRITE setFavoritesMatchParameters NOTIFY favoritesMatchParametersChanged) + + Q_ENUMS(SearchResultType RelevanceHint) + +public: + enum SearchResultType { + UnknownSearchResult = QPlaceSearchResult::UnknownSearchResult, + PlaceResult = QPlaceSearchResult::PlaceResult, + ProposedSearchResult = QPlaceSearchResult::ProposedSearchResult + }; + + enum RelevanceHint { + UnspecifiedHint = QPlaceSearchRequest::UnspecifiedHint, + DistanceHint = QPlaceSearchRequest::DistanceHint, + LexicalPlaceNameHint = QPlaceSearchRequest::LexicalPlaceNameHint + }; + + explicit QDeclarativeSearchResultModel(QObject *parent = 0); + ~QDeclarativeSearchResultModel(); + + QString searchTerm() const; + void setSearchTerm(const QString &searchTerm); + + QQmlListProperty categories(); + static void categories_append(QQmlListProperty *list, + QDeclarativeCategory *category); + static int categories_count(QQmlListProperty *list); + static QDeclarativeCategory *category_at(QQmlListProperty *list, int index); + static void categories_clear(QQmlListProperty *list); + + QString recommendationId() const; + void setRecommendationId(const QString &recommendationId); + + QDeclarativeSearchResultModel::RelevanceHint relevanceHint() const; + void setRelevanceHint(QDeclarativeSearchResultModel::RelevanceHint hint); + + QDeclarativePlace::Visibility visibilityScope() const; + void setVisibilityScope(QDeclarativePlace::Visibility visibilityScope); + + QDeclarativeGeoServiceProvider *favoritesPlugin() const; + void setFavoritesPlugin(QDeclarativeGeoServiceProvider *plugin); + + QVariantMap favoritesMatchParameters() const; + void setFavoritesMatchParameters(const QVariantMap ¶meters); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + virtual void clearData(bool suppressSignal = false); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + Q_INVOKABLE QVariant data(int index, const QString &roleName) const; + QHash roleNames() const; + + Q_INVOKABLE void updateWith(int proposedSearchIndex); + + void updateSearchRequest(); + +Q_SIGNALS: + void searchTermChanged(); + void categoriesChanged(); + void recommendationIdChanged(); + void relevanceHintChanged(); + void visibilityScopeChanged(); + + void rowCountChanged(); + void favoritesPluginChanged(); + void favoritesMatchParametersChanged(); + void dataChanged(); + +protected: + QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request); + virtual void initializePlugin(QDeclarativeGeoServiceProvider *plugin); + +protected Q_SLOTS: + virtual void queryFinished(); + +private Q_SLOTS: + void updateLayout(const QList &favoritePlaces = QList()); + + void placeUpdated(const QString &placeId); + void placeRemoved(const QString &placeId); + +private: + enum Roles { + SearchResultTypeRole = Qt::UserRole, + TitleRole, + IconRole, + DistanceRole, + PlaceRole, + SponsoredRole + }; + + int getRow(const QString &placeId) const; + QList m_categories; + QLocation::VisibilityScope m_visibilityScope; + + QList m_results; + QList m_resultsBuffer; + QList m_places; + QList m_icons; + + QDeclarativeGeoServiceProvider *m_favoritesPlugin; + QVariantMap m_matchParameters; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVESEARCHRESULTMODEL_P_H diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel.cpp b/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel.cpp new file mode 100644 index 0000000..abc845f --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel.cpp @@ -0,0 +1,351 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativesearchsuggestionmodel_p.h" +#include "qdeclarativegeoserviceprovider_p.h" + +#include +#include + +#include +#include + +QT_USE_NAMESPACE + +/*! + \qmltype PlaceSearchSuggestionModel + \instantiates QDeclarativeSearchSuggestionModel + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-models + \since Qt Location 5.5 + + \brief Provides access to search term suggestions. + + The PlaceSearchSuggestionModel can be used to provide search term suggestions as the user enters their + search term. The properties of this model should match that of the \l PlaceSearchModel, which + will be used to perform the actual search query, to ensure that the search suggestion results are + relevant. + + There are two ways of accessing the data provided by this model, either through the + \l suggestions property or through views and delegates. The latter is the preferred + method. + + The \l offset and \l limit properties can be used to access paged suggestions. When the + \l offset and \l limit properties are set the suggestions between \l offset and + (\l offset + \l limit - 1) will be returned. Support for paging may vary + from plugin to plugin. + + The model returns data for the following roles: + + \table + \header + \li Role + \li Type + \li Description + \row + \li suggestion + \li string + \li Suggested search term. + \endtable + + The following example shows how to use the PlaceSearchSuggestionModel to get suggested search terms + from a partial search term. The \l searchArea is set to match what would be used to perform the + actual place search with \l PlaceSearchModel. + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml SearchSuggestionModel + + \sa PlaceSearchModel, {QPlaceManager} +*/ + +/*! + \qmlproperty Plugin PlaceSearchSuggestionModel::plugin + + This property holds the provider \l Plugin which will be used to perform the search. +*/ + +/*! + \qmlproperty geoshape PlaceSearchSuggestionModel::searchArea + + This property holds the search area. Search suggestion results returned by the model will be + relevant to the given search area. + + If this property is set to a \l {geocircle} its + \l {geocircle}{radius} property may be left unset, in which case the \l Plugin + will choose an appropriate radius for the search. +*/ + +/*! + \qmlproperty int PlaceSearchSuggestionModel::offset + + This property holds the index of the first item in the model. + + \sa limit +*/ + +/*! + \qmlproperty int PlaceSearchSuggestionModel::limit + + This property holds the limit of the number of items that will be returned. + + \sa offset +*/ + +/*! + \qmlproperty enum PlaceSearchSuggestionModel::status + + This property holds the status of the model. It can be one of: + + \table + \row + \li PlaceSearchSuggestionModel.Null + \li No search query has been executed. The model is empty. + \row + \li PlaceSearchSuggestionModel.Ready + \li The search query has completed, and the results are available. + \row + \li PlaceSearchSuggestionModel.Loading + \li A search query is currently being executed. + \row + \li PlaceSearchSuggestionModel.Error + \li An error occurred when executing the previous search query. + \endtable +*/ + +/*! + \qmlmethod void PlaceSearchSuggestionModel::update() + + Updates the model based on the provided query parameters. The model will be populated with a + list of search suggestions for the partial \l searchTerm and \l searchArea. If the \l plugin + supports it, other parameters such as \l limit and \l offset may be specified. \c update() + submits the set of parameters to the \l plugin to process. + + + While the model is updating the \l status of the model is set to + \c PlaceSearchSuggestionModel.Loading. If the model is successfully updated, the \l status is + set to \c PlaceSearchSuggestionModel.Ready, while if it unsuccessfully completes, the \l status + is set to \c PlaceSearchSuggestionModel.Error and the model cleared. + + This example shows use of the model + \code + PlaceSeachSuggestionModel { + id: model + plugin: backendPlugin + searchArea: QtPositioning.circle(QtPositioning.coordinate(10, 10)) + ... + } + + MouseArea { + ... + onClicked: { + model.searchTerm = "piz" + model.searchArea.center.latitude = -27.5; + model.searchArea.cetner.longitude = 153; + model.update(); + } + } + \endcode + + A more detailed example can be found in the in + \l {Places (QML)#Presenting-Search-Suggestions}{Places (QML)} example. + + \sa cancel(), status +*/ + +/*! + \qmlmethod void PlaceSearchSuggestionModel::cancel() + + Cancels an ongoing search suggestion operation immediately and sets the model + status to PlaceSearchSuggestionModel.Ready. The model retains any search + suggestions it had before the operation was started. + + If an operation is not ongoing, invoking cancel() has no effect. + + \sa update(), status +*/ + +/*! + \qmlmethod void PlaceSearchSuggestionModel::reset() + + Resets the model. All search suggestions are cleared, any outstanding requests are aborted and + possible errors are cleared. Model status will be set to PlaceSearchSuggestionModel.Null. +*/ + + +/*! + \qmlmethod string QtLocation::PlaceSearchSuggestionModel::errorString() const + + This read-only property holds the textual presentation of the latest search suggestion model error. + If no error has occurred, or if the model was cleared, an empty string is returned. + + An empty string may also be returned if an error occurred which has no associated + textual representation. +*/ + +QDeclarativeSearchSuggestionModel::QDeclarativeSearchSuggestionModel(QObject *parent) +: QDeclarativeSearchModelBase(parent) +{ +} + +QDeclarativeSearchSuggestionModel::~QDeclarativeSearchSuggestionModel() +{ +} + +/*! + \qmlproperty string PlaceSearchSuggestionModel::searchTerm + + This property holds the partial search term used in query. +*/ +QString QDeclarativeSearchSuggestionModel::searchTerm() const +{ + return m_request.searchTerm(); +} + +void QDeclarativeSearchSuggestionModel::setSearchTerm(const QString &searchTerm) +{ + if (m_request.searchTerm() == searchTerm) + return; + + m_request.setSearchTerm(searchTerm); + emit searchTermChanged(); +} + +/*! + \qmlproperty stringlist PlaceSearchSuggestionModel::suggestions + + This property holds the list of predicted search terms that the model currently has. +*/ +QStringList QDeclarativeSearchSuggestionModel::suggestions() const +{ + return m_suggestions; +} + +/*! + \internal +*/ +void QDeclarativeSearchSuggestionModel::clearData(bool suppressSignal) +{ + QDeclarativeSearchModelBase::clearData(suppressSignal); + + if (!m_suggestions.isEmpty()) { + m_suggestions.clear(); + + if (!suppressSignal) + emit suggestionsChanged(); + } +} + +/*! + \internal +*/ +int QDeclarativeSearchSuggestionModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return m_suggestions.count(); +} + +/*! + \internal +*/ +QVariant QDeclarativeSearchSuggestionModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= rowCount(index.parent()) || index.row() < 0) + return QVariant(); + + switch (role) { + case Qt::DisplayRole: + case SearchSuggestionRole: + return m_suggestions.at(index.row()); + } + + return QVariant(); +} + +QHash QDeclarativeSearchSuggestionModel::roleNames() const +{ + QHash roleNames = QDeclarativeSearchModelBase::roleNames(); + roleNames.insert(SearchSuggestionRole, "suggestion"); + return roleNames; +} + +/*! + \internal +*/ +void QDeclarativeSearchSuggestionModel::queryFinished() +{ + if (!m_reply) + return; + + QPlaceReply *reply = m_reply; + m_reply = 0; + + int initialCount = m_suggestions.count(); + beginResetModel(); + + clearData(true); + + QPlaceSearchSuggestionReply *suggestionReply = qobject_cast(reply); + m_suggestions = suggestionReply->suggestions(); + + if (initialCount != m_suggestions.count()) + emit suggestionsChanged(); + + endResetModel(); + + if (suggestionReply->error() != QPlaceReply::NoError) + setStatus(Error, suggestionReply->errorString()); + else + setStatus(Ready); + + + reply->deleteLater(); +} + +/*! + \internal +*/ +QPlaceReply *QDeclarativeSearchSuggestionModel::sendQuery(QPlaceManager *manager, + const QPlaceSearchRequest &request) +{ + return manager->searchSuggestions(request); +} diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h b/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h new file mode 100644 index 0000000..49e0998 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESEARCHSUGGESTIONMODEL_P_H +#define QDECLARATIVESEARCHSUGGESTIONMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativesearchmodelbase.h" + +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoServiceProvider; +class QGeoServiceProvider; + +class QDeclarativeSearchSuggestionModel : public QDeclarativeSearchModelBase +{ + Q_OBJECT + + Q_PROPERTY(QString searchTerm READ searchTerm WRITE setSearchTerm NOTIFY searchTermChanged) + Q_PROPERTY(QStringList suggestions READ suggestions NOTIFY suggestionsChanged) + +public: + explicit QDeclarativeSearchSuggestionModel(QObject *parent = 0); + ~QDeclarativeSearchSuggestionModel(); + + QString searchTerm() const; + void setSearchTerm(const QString &searchTerm); + + QStringList suggestions() const; + + void clearData(bool suppressSignal = false); + + // From QAbstractListModel + int rowCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + QHash roleNames() const; + + enum Roles { + SearchSuggestionRole = Qt::UserRole + }; + +protected Q_SLOTS: + virtual void queryFinished(); + +Q_SIGNALS: + void searchTermChanged(); + void suggestionsChanged(); + +protected: + QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request); + +private: + QStringList m_suggestions; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/declarativeplaces/qdeclarativesupplier.cpp b/src/imports/location/declarativeplaces/qdeclarativesupplier.cpp new file mode 100644 index 0000000..8fca9e8 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesupplier.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativesupplier_p.h" + +#include + +QT_USE_NAMESPACE + +/*! + \qmltype Supplier + \instantiates QDeclarativeSupplier + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-data + \since Qt Location 5.5 + + \brief Holds data regarding the supplier of a place, a place's image, review, or editorial. + + Each instance represents a set of data about a supplier, which can include + supplier's name, url and icon. The supplier is typically a business or organization. + + Note: The Places API only supports suppliers as 'retrieve-only' objects. Submitting + suppliers to a provider is not a supported use case. + + \sa ImageModel, ReviewModel, EditorialModel + + \section1 Example + + The following example shows how to create and display a supplier in QML: + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml Supplier +*/ + +QDeclarativeSupplier::QDeclarativeSupplier(QObject *parent) + : QObject(parent), m_icon(0) +{ +} + +QDeclarativeSupplier::QDeclarativeSupplier(const QPlaceSupplier &src, + QDeclarativeGeoServiceProvider *plugin, + QObject *parent) + : QObject(parent), + m_src(src), + m_icon(0) +{ + setSupplier(src, plugin); +} + +QDeclarativeSupplier::~QDeclarativeSupplier() +{ +} + +/*! + \internal +*/ +void QDeclarativeSupplier::componentComplete() +{ + // delayed instantiation of QObject based properties. + if (!m_icon) + m_icon = new QDeclarativePlaceIcon(this); +} + +/*! + \qmlproperty QPlaceSupplier Supplier::supplier + + For details on how to use this property to interface between C++ and QML see + "\l {Supplier - QPlaceSupplier} {Interfaces between C++ and QML Code}". +*/ +void QDeclarativeSupplier::setSupplier(const QPlaceSupplier &src, QDeclarativeGeoServiceProvider *plugin) +{ + QPlaceSupplier previous = m_src; + m_src = src; + + if (previous.name() != m_src.name()) + emit nameChanged(); + + if (previous.supplierId() != m_src.supplierId()) + emit supplierIdChanged(); + + if (previous.url() != m_src.url()) + emit urlChanged(); + + if (m_icon && m_icon->parent() == this) { + m_icon->setPlugin(plugin); + m_icon->setIcon(m_src.icon()); + } else if (!m_icon || m_icon->parent() != this) { + m_icon = new QDeclarativePlaceIcon(m_src.icon(), plugin, this); + emit iconChanged(); + } +} + +QPlaceSupplier QDeclarativeSupplier::supplier() +{ + m_src.setIcon(m_icon ? m_icon->icon() : QPlaceIcon()); + return m_src; +} + +/*! + \qmlproperty string Supplier::supplierId + + This property holds the identifier of the supplier. The identifier is unique + to the Plugin backend which provided the supplier and is generally + not suitable for displaying to the user. +*/ + +void QDeclarativeSupplier::setSupplierId(const QString &supplierId) +{ + if (m_src.supplierId() != supplierId) { + m_src.setSupplierId(supplierId); + emit supplierIdChanged(); + } +} + +QString QDeclarativeSupplier::supplierId() const +{ + return m_src.supplierId(); +} + +/*! + \qmlproperty string Supplier::name + + This property holds the name of the supplier which can be displayed + to the user. + + The name can potentially be localized. The language is dependent on the + entity that sets it, typically this is the \l Plugin. The \l {Plugin::locales} + property defines what language is used. +*/ + +void QDeclarativeSupplier::setName(const QString &name) +{ + if (m_src.name() != name) { + m_src.setName(name); + emit nameChanged(); + } +} + +QString QDeclarativeSupplier::name() const +{ + return m_src.name(); +} + +/*! + \qmlproperty url Supplier::url + + This property holds the URL of the supplier's website. +*/ + +void QDeclarativeSupplier::setUrl(const QUrl &url) +{ + if (m_src.url() != url) { + m_src.setUrl(url); + emit urlChanged(); + } +} + +QUrl QDeclarativeSupplier::url() const +{ + return m_src.url(); +} + +/*! + \qmlproperty PlaceIcon Supplier::icon + + This property holds the icon of the supplier. +*/ +QDeclarativePlaceIcon *QDeclarativeSupplier::icon() const +{ + return m_icon; +} + +void QDeclarativeSupplier::setIcon(QDeclarativePlaceIcon *icon) +{ + if (m_icon == icon) + return; + + if (m_icon && m_icon->parent() == this) + delete m_icon; + + m_icon = icon; + emit iconChanged(); +} diff --git a/src/imports/location/declarativeplaces/qdeclarativesupplier_p.h b/src/imports/location/declarativeplaces/qdeclarativesupplier_p.h new file mode 100644 index 0000000..35b1dbd --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesupplier_p.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESUPPLIER_P_H +#define QDECLARATIVESUPPLIER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +#include "qdeclarativeplaceicon_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativeSupplier : public QObject, public QQmlParserStatus +{ + Q_OBJECT + + Q_PROPERTY(QPlaceSupplier supplier READ supplier WRITE setSupplier) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString supplierId READ supplierId WRITE setSupplierId NOTIFY supplierIdChanged) + Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) + Q_PROPERTY(QDeclarativePlaceIcon *icon READ icon WRITE setIcon NOTIFY iconChanged) + + Q_INTERFACES(QQmlParserStatus) + +public: + explicit QDeclarativeSupplier(QObject *parent = 0); + explicit QDeclarativeSupplier(const QPlaceSupplier &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent = 0); + ~QDeclarativeSupplier(); + + // From QQmlParserStatus + void classBegin() { } + void componentComplete(); + + QPlaceSupplier supplier(); + void setSupplier(const QPlaceSupplier &src, QDeclarativeGeoServiceProvider *plugin = 0); + + QString name() const; + void setName(const QString &data); + QString supplierId() const; + void setSupplierId(const QString &data); + QUrl url() const; + void setUrl(const QUrl &data); + + QDeclarativePlaceIcon *icon() const; + void setIcon(QDeclarativePlaceIcon *icon); + +Q_SIGNALS: + void nameChanged(); + void supplierIdChanged(); + void urlChanged(); + void iconChanged(); + +private: + QPlaceSupplier m_src; + QDeclarativePlaceIcon *m_icon; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeSupplier) + +#endif // QDECLARATIVESUPPLIER_P_H diff --git a/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp new file mode 100644 index 0000000..2865957 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp @@ -0,0 +1,687 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Aaron McCarthy +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativesupportedcategoriesmodel_p.h" +#include "qdeclarativeplaceicon_p.h" +#include "qgeoserviceprovider.h" +#include "error_messages.h" + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +/*! + \qmltype CategoryModel + \instantiates QDeclarativeSupportedCategoriesModel + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-places + \ingroup qml-QtLocation5-places-models + \since Qt Location 5.5 + + \brief The CategoryModel type provides a model of the categories supported by a \l Plugin. + + The CategoryModel type provides a model of the categories that are available from the + current \l Plugin. The model supports both a flat list of categories and a hierarchical tree + representing category groupings. This can be controlled by the \l hierarchical property. + + The model supports the following roles: + + \table + \header + \li Role + \li Type + \li Description + \row + \li category + \li \l Category + \li Category object for the current item. + \row + \li parentCategory + \li \l Category + \li Parent category object for the current item. + If there is no parent, null is returned. + \endtable + + The following example displays a flat list of all available categories: + + \snippet declarative/places.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/places.qml CategoryView + + To access the hierarchical category model it is necessary to use a \l DelegateModel to access + the child items. +*/ + +/*! + \qmlproperty Plugin CategoryModel::plugin + + This property holds the provider \l Plugin used by this model. +*/ + +/*! + \qmlproperty bool CategoryModel::hierarchical + + This property holds whether the model provides a hierarchical tree of categories or a flat + list. The default is true. +*/ + +/*! + \qmlmethod string QtLocation::CategoryModel::data(ModelIndex index, int role) + \internal + + This method retrieves the model's data per \a index and \a role. +*/ + +/*! + \qmlmethod string QtLocation::CategoryModel::errorString() const + + This read-only property holds the textual presentation of the latest category model error. + If no error has occurred, an empty string is returned. + + An empty string may also be returned if an error occurred which has no associated + textual representation. +*/ + +/*! + \internal + \enum QDeclarativeSupportedCategoriesModel::Roles +*/ + +QDeclarativeSupportedCategoriesModel::QDeclarativeSupportedCategoriesModel(QObject *parent) +: QAbstractItemModel(parent), m_response(0), m_plugin(0), m_hierarchical(true), + m_complete(false), m_status(Null) +{ +} + +QDeclarativeSupportedCategoriesModel::~QDeclarativeSupportedCategoriesModel() +{ + qDeleteAll(m_categoriesTree); +} + +/*! + \internal +*/ +// From QQmlParserStatus +void QDeclarativeSupportedCategoriesModel::componentComplete() +{ + m_complete = true; +} + +/*! + \internal +*/ +int QDeclarativeSupportedCategoriesModel::rowCount(const QModelIndex &parent) const +{ + if (m_categoriesTree.keys().isEmpty()) + return 0; + + PlaceCategoryNode *node = static_cast(parent.internalPointer()); + if (!node) + node = m_categoriesTree.value(QString()); + else if (m_categoriesTree.keys(node).isEmpty()) + return 0; + + return node->childIds.count(); +} + +/*! + \internal +*/ +int QDeclarativeSupportedCategoriesModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return 1; +} + +/*! + \internal +*/ +QModelIndex QDeclarativeSupportedCategoriesModel::index(int row, int column, const QModelIndex &parent) const +{ + if (column != 0 || row < 0) + return QModelIndex(); + + PlaceCategoryNode *node = static_cast(parent.internalPointer()); + + if (!node) + node = m_categoriesTree.value(QString()); + else if (m_categoriesTree.keys(node).isEmpty()) //return root index if parent is non-existent + return QModelIndex(); + + if (row > node->childIds.count()) + return QModelIndex(); + + QString id = node->childIds.at(row); + Q_ASSERT(m_categoriesTree.contains(id)); + + return createIndex(row, 0, m_categoriesTree.value(id)); +} + +/*! + \internal +*/ +QModelIndex QDeclarativeSupportedCategoriesModel::parent(const QModelIndex &child) const +{ + PlaceCategoryNode *childNode = static_cast(child.internalPointer()); + if (m_categoriesTree.keys(childNode).isEmpty()) + return QModelIndex(); + + return index(childNode->parentId); +} + +/*! + \internal +*/ +QVariant QDeclarativeSupportedCategoriesModel::data(const QModelIndex &index, int role) const +{ + PlaceCategoryNode *node = static_cast(index.internalPointer()); + if (!node) + node = m_categoriesTree.value(QString()); + else if (m_categoriesTree.keys(node).isEmpty()) + return QVariant(); + + QDeclarativeCategory *category = node->declCategory.data(); + + switch (role) { + case Qt::DisplayRole: + return category->name(); + case CategoryRole: + return QVariant::fromValue(category); + case ParentCategoryRole: { + if (!m_categoriesTree.keys().contains(node->parentId)) + return QVariant(); + else + return QVariant::fromValue(m_categoriesTree.value(node->parentId)->declCategory.data()); + } + default: + return QVariant(); + } +} + +QHash QDeclarativeSupportedCategoriesModel::roleNames() const +{ + QHash roles = QAbstractItemModel::roleNames(); + roles.insert(CategoryRole, "category"); + roles.insert(ParentCategoryRole, "parentCategory"); + return roles; +} + +/*! + \internal +*/ +void QDeclarativeSupportedCategoriesModel::setPlugin(QDeclarativeGeoServiceProvider *plugin) +{ + if (m_plugin == plugin) + return; + + //disconnect the manager of the old plugin if we have one + if (m_plugin) { + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (serviceProvider) { + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (placeManager) { + disconnect(placeManager, SIGNAL(categoryAdded(QPlaceCategory,QString)), + this, SLOT(addedCategory(QPlaceCategory,QString))); + disconnect(placeManager, SIGNAL(categoryUpdated(QPlaceCategory,QString)), + this, SLOT(updatedCategory(QPlaceCategory,QString))); + disconnect(placeManager, SIGNAL(categoryRemoved(QString,QString)), + this, SLOT(removedCategory(QString,QString))); + disconnect(placeManager, SIGNAL(dataChanged()), + this, SIGNAL(dataChanged())); + } + } + } + + m_plugin = plugin; + + // handle plugin name changes -> update categories + if (m_plugin) { + connect(m_plugin, SIGNAL(nameChanged(QString)), this, SLOT(connectNotificationSignals())); + connect(m_plugin, SIGNAL(nameChanged(QString)), this, SLOT(update())); + } + + connectNotificationSignals(); + + if (m_complete) + emit pluginChanged(); +} + +/*! + \internal +*/ +QDeclarativeGeoServiceProvider *QDeclarativeSupportedCategoriesModel::plugin() const +{ + return m_plugin; +} + +/*! + \internal +*/ +void QDeclarativeSupportedCategoriesModel::setHierarchical(bool hierarchical) +{ + if (m_hierarchical == hierarchical) + return; + + m_hierarchical = hierarchical; + emit hierarchicalChanged(); + + updateLayout(); +} + +/*! + \internal +*/ +bool QDeclarativeSupportedCategoriesModel::hierarchical() const +{ + return m_hierarchical; +} + +/*! + \internal +*/ +void QDeclarativeSupportedCategoriesModel::replyFinished() +{ + if (!m_response) + return; + + m_response->deleteLater(); + + if (m_response->error() == QPlaceReply::NoError) { + m_errorString.clear(); + + m_response = 0; + + updateLayout(); + setStatus(QDeclarativeSupportedCategoriesModel::Ready); + } else { + const QString errorString = m_response->errorString(); + + m_response = 0; + + setStatus(Error, errorString); + } +} + +/*! + \internal +*/ +void QDeclarativeSupportedCategoriesModel::addedCategory(const QPlaceCategory &category, + const QString &parentId) +{ + if (m_response) + return; + + if (!m_categoriesTree.contains(parentId)) + return; + + if (category.categoryId().isEmpty()) + return; + + PlaceCategoryNode *parentNode = m_categoriesTree.value(parentId); + if (!parentNode) + return; + + int rowToBeAdded = rowToAddChild(parentNode, category); + QModelIndex parentIndex = index(parentId); + beginInsertRows(parentIndex, rowToBeAdded, rowToBeAdded); + PlaceCategoryNode *categoryNode = new PlaceCategoryNode; + categoryNode->parentId = parentId; + categoryNode->declCategory = QSharedPointer(new QDeclarativeCategory(category, m_plugin, this)); + + m_categoriesTree.insert(category.categoryId(), categoryNode); + parentNode->childIds.insert(rowToBeAdded,category.categoryId()); + endInsertRows(); + + //this is a workaround to deal with the fact that the hasModelChildren field of DelegateModel + //does not get updated when a child is added to a model + beginResetModel(); + endResetModel(); +} + +/*! + \internal +*/ +void QDeclarativeSupportedCategoriesModel::updatedCategory(const QPlaceCategory &category, + const QString &parentId) +{ + if (m_response) + return; + + QString categoryId = category.categoryId(); + + if (!m_categoriesTree.contains(parentId)) + return; + + if (category.categoryId().isEmpty() || !m_categoriesTree.contains(categoryId)) + return; + + PlaceCategoryNode *newParentNode = m_categoriesTree.value(parentId); + if (!newParentNode) + return; + + PlaceCategoryNode *categoryNode = m_categoriesTree.value(categoryId); + if (!categoryNode) + return; + + categoryNode->declCategory->setCategory(category); + + if (categoryNode->parentId == parentId) { //reparenting to same parent + QModelIndex parentIndex = index(parentId); + int rowToBeAdded = rowToAddChild(newParentNode, category); + int oldRow = newParentNode->childIds.indexOf(categoryId); + + //check if we are changing the position of the category + if (qAbs(rowToBeAdded - newParentNode->childIds.indexOf(categoryId)) > 1) { + //if the position has changed we are moving rows + beginMoveRows(parentIndex, oldRow, oldRow, + parentIndex, rowToBeAdded); + + newParentNode->childIds.removeAll(categoryId); + newParentNode->childIds.insert(rowToBeAdded, categoryId); + endMoveRows(); + } else {// if the position has not changed we modifying an existing row + QModelIndex categoryIndex = index(categoryId); + emit dataChanged(categoryIndex, categoryIndex); + } + } else { //reparenting to different parents + QPlaceCategory oldCategory = categoryNode->declCategory->category(); + PlaceCategoryNode *oldParentNode = m_categoriesTree.value(categoryNode->parentId); + if (!oldParentNode) + return; + QModelIndex oldParentIndex = index(categoryNode->parentId); + QModelIndex newParentIndex = index(parentId); + + int rowToBeAdded = rowToAddChild(newParentNode, category); + beginMoveRows(oldParentIndex, oldParentNode->childIds.indexOf(categoryId), + oldParentNode->childIds.indexOf(categoryId), newParentIndex, rowToBeAdded); + oldParentNode->childIds.removeAll(oldCategory.categoryId()); + newParentNode->childIds.insert(rowToBeAdded, categoryId); + categoryNode->parentId = parentId; + endMoveRows(); + + //this is a workaround to deal with the fact that the hasModelChildren field of DelegateModel + //does not get updated when an index is updated to contain children + beginResetModel(); + endResetModel(); + } +} + +/*! + \internal +*/ +void QDeclarativeSupportedCategoriesModel::removedCategory(const QString &categoryId, const QString &parentId) +{ + if (m_response) + return; + + if (!m_categoriesTree.contains(categoryId) || !m_categoriesTree.contains(parentId)) + return; + + QModelIndex parentIndex = index(parentId); + QModelIndex categoryIndex = index(categoryId); + + beginRemoveRows(parentIndex, categoryIndex.row(), categoryIndex.row()); + PlaceCategoryNode *parentNode = m_categoriesTree.value(parentId); + parentNode->childIds.removeAll(categoryId); + delete m_categoriesTree.take(categoryId); + endRemoveRows(); +} + +/*! + \internal +*/ +void QDeclarativeSupportedCategoriesModel::connectNotificationSignals() +{ + if (!m_plugin) + return; + + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (!serviceProvider || serviceProvider->error() != QGeoServiceProvider::NoError) + return; + + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (!placeManager) + return; + + // listen for any category notifications so that we can reupdate the categories + // model. + connect(placeManager, SIGNAL(categoryAdded(QPlaceCategory,QString)), + this, SLOT(addedCategory(QPlaceCategory,QString))); + connect(placeManager, SIGNAL(categoryUpdated(QPlaceCategory,QString)), + this, SLOT(updatedCategory(QPlaceCategory,QString))); + connect(placeManager, SIGNAL(categoryRemoved(QString,QString)), + this, SLOT(removedCategory(QString,QString))); + connect(placeManager, SIGNAL(dataChanged()), + this, SIGNAL(dataChanged())); +} + +/*! + \internal +*/ +void QDeclarativeSupportedCategoriesModel::update() +{ + if (m_response) + return; + + setStatus(Loading); + + if (!m_plugin) { + updateLayout(); + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROPERTY_NOT_SET)); + return; + } + + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (!serviceProvider || serviceProvider->error() != QGeoServiceProvider::NoError) { + updateLayout(); + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROVIDER_ERROR) + .arg(m_plugin->name())); + return; + } + + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (!placeManager) { + updateLayout(); + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR) + .arg(m_plugin->name()).arg(serviceProvider->errorString())); + return; + } + + m_response = placeManager->initializeCategories(); + if (m_response) { + connect(m_response, SIGNAL(finished()), this, SLOT(replyFinished())); + } else { + updateLayout(); + setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, + CATEGORIES_NOT_INITIALIZED)); + } +} + +/*! + \internal +*/ +void QDeclarativeSupportedCategoriesModel::updateLayout() +{ + beginResetModel(); + qDeleteAll(m_categoriesTree); + m_categoriesTree.clear(); + + if (m_plugin) { + QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider(); + if (serviceProvider && serviceProvider->error() == QGeoServiceProvider::NoError) { + QPlaceManager *placeManager = serviceProvider->placeManager(); + if (placeManager) { + PlaceCategoryNode *node = new PlaceCategoryNode; + node->childIds = populateCategories(placeManager, QPlaceCategory()); + m_categoriesTree.insert(QString(), node); + node->declCategory = QSharedPointer + (new QDeclarativeCategory(QPlaceCategory(), m_plugin, this)); + } + } + } + + endResetModel(); +} + +QString QDeclarativeSupportedCategoriesModel::errorString() const +{ + return m_errorString; +} + +/*! + \qmlproperty enumeration CategoryModel::status + + This property holds the status of the model. It can be one of: + + \table + \row + \li CategoryModel.Null + \li No category fetch query has been executed. The model is empty. + \row + \li CategoryModel.Ready + \li No error occurred during the last operation, further operations may be performed on + the model. + \row + \li CategoryModel.Loading + \li The model is being updated, no other operations may be performed until complete. + \row + \li CategoryModel.Error + \li An error occurred during the last operation, further operations can still be + performed on the model. + \endtable +*/ +void QDeclarativeSupportedCategoriesModel::setStatus(Status status, const QString &errorString) +{ + Status originalStatus = m_status; + m_status = status; + m_errorString = errorString; + + if (originalStatus != m_status) + emit statusChanged(); +} + +QDeclarativeSupportedCategoriesModel::Status QDeclarativeSupportedCategoriesModel::status() const +{ + return m_status; +} + +/*! + \internal +*/ +QStringList QDeclarativeSupportedCategoriesModel::populateCategories(QPlaceManager *manager, const QPlaceCategory &parent) +{ + Q_ASSERT(manager); + + QStringList childIds; + PlaceCategoryNode *node; + + QMap sortedCategories; + foreach ( const QPlaceCategory &category, manager->childCategories(parent.categoryId())) + sortedCategories.insert(category.name(), category); + + QMapIterator iter(sortedCategories); + while (iter.hasNext()) { + iter.next(); + node = new PlaceCategoryNode; + node->parentId = parent.categoryId(); + node->declCategory = QSharedPointer(new QDeclarativeCategory(iter.value(), m_plugin ,this)); + + if (m_hierarchical) + node->childIds = populateCategories(manager, iter.value()); + + m_categoriesTree.insert(node->declCategory->categoryId(), node); + childIds.append(iter.value().categoryId()); + + if (!m_hierarchical) { + childIds.append(populateCategories(manager,node->declCategory->category())); + } + } + return childIds; +} + +/*! + \internal +*/ +QModelIndex QDeclarativeSupportedCategoriesModel::index(const QString &categoryId) const +{ + if (categoryId.isEmpty()) + return QModelIndex(); + + if (!m_categoriesTree.contains(categoryId)) + return QModelIndex(); + + PlaceCategoryNode *categoryNode = m_categoriesTree.value(categoryId); + if (!categoryNode) + return QModelIndex(); + + QString parentCategoryId = categoryNode->parentId; + + PlaceCategoryNode *parentNode = m_categoriesTree.value(parentCategoryId); + + return createIndex(parentNode->childIds.indexOf(categoryId), 0, categoryNode); +} + +/*! + \internal +*/ +int QDeclarativeSupportedCategoriesModel::rowToAddChild(PlaceCategoryNode *node, const QPlaceCategory &category) +{ + Q_ASSERT(node); + for (int i = 0; i < node->childIds.count(); ++i) { + if (category.name() < m_categoriesTree.value(node->childIds.at(i))->declCategory->name()) + return i; + } + return node->childIds.count(); +} + +/*! + \qmlsignal CategoryModel::dataChanged() + + This signal is emitted when significant changes have been made to the underlying datastore. + + Applications should act on this signal at their own discretion. The data + provided by the model could be out of date and so the model should be reupdated + sometime, however an immediate reupdate may be disconcerting to users if the categories + change without any action on their part. + + The corresponding handler is \c onDataChanged. +*/ diff --git a/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h new file mode 100644 index 0000000..9816789 --- /dev/null +++ b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESUPPORTEDCATEGORIESMODEL_H +#define QDECLARATIVESUPPORTEDCATEGORIESMODEL_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "qdeclarativecategory_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoServiceProvider; +class QPlaceManager; +class QPlaceReply; + +class PlaceCategoryNode +{ +public: + QString parentId; + QStringList childIds; + QSharedPointer declCategory; +}; + +class QDeclarativeSupportedCategoriesModel : public QAbstractItemModel, public QQmlParserStatus +{ + Q_OBJECT + + Q_ENUMS(Status) + + Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) + Q_PROPERTY(bool hierarchical READ hierarchical WRITE setHierarchical NOTIFY hierarchicalChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + + Q_INTERFACES(QQmlParserStatus) + Q_ENUMS(Roles) //The Roles enum is for internal usage only. + +public: + explicit QDeclarativeSupportedCategoriesModel(QObject *parent = 0); + virtual ~QDeclarativeSupportedCategoriesModel(); + + // From QQmlParserStatus + virtual void classBegin() {} + virtual void componentComplete(); + + // From QAbstractItemModel + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + + QModelIndex index(int row, int column, const QModelIndex &parent) const; + QModelIndex parent(const QModelIndex &child) const; + + Q_INVOKABLE QVariant data(const QModelIndex &index, int role) const; + QHash roleNames() const; + + enum Roles { + CategoryRole = Qt::UserRole, + ParentCategoryRole + }; //for internal usage only + + enum Status {Null, Ready, Loading, Error}; + + void setPlugin(QDeclarativeGeoServiceProvider *plugin); + QDeclarativeGeoServiceProvider *plugin() const; + + void setHierarchical(bool hierarchical); + bool hierarchical() const; + + Q_INVOKABLE QString errorString() const; + + Status status() const; + void setStatus(Status status, const QString &errorString = QString()); + + using QAbstractItemModel::dataChanged; +Q_SIGNALS: + void pluginChanged(); + void hierarchicalChanged(); + void statusChanged(); + void dataChanged(); + +public Q_SLOTS: + void update(); + +private Q_SLOTS: + void replyFinished(); + void addedCategory(const QPlaceCategory &category, const QString &parentId); + void updatedCategory(const QPlaceCategory &category, const QString &parentId); + void removedCategory(const QString &categoryId, const QString &parentId); + void connectNotificationSignals(); + +private: + QStringList populateCategories(QPlaceManager *, const QPlaceCategory &parent); + QModelIndex index(const QString &categoryId) const; + int rowToAddChild(PlaceCategoryNode *, const QPlaceCategory &category); + void updateLayout(); + + QPlaceReply *m_response; + + QDeclarativeGeoServiceProvider *m_plugin; + bool m_hierarchical; + bool m_complete; + Status m_status; + QString m_errorString; + + QHash m_categoriesTree; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeSupportedCategoriesModel) + +#endif // QDECLARATIVESUPPORTEDCATEGORIESMODEL_H diff --git a/src/imports/location/error_messages.cpp b/src/imports/location/error_messages.cpp new file mode 100644 index 0000000..a2557f7 --- /dev/null +++ b/src/imports/location/error_messages.cpp @@ -0,0 +1,52 @@ +/*************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "error_messages.h" + +QT_BEGIN_NAMESPACE + +const char CONTEXT_NAME[] = "QtLocationQML"; + +//to-be-translated error string + +const char PLUGIN_PROPERTY_NOT_SET[] = QT_TRANSLATE_NOOP("QtLocationQML", "Plugin property is not set."); +const char PLUGIN_ERROR[] = QT_TRANSLATE_NOOP("QtLocationQML", "Plugin Error (%1): %2"); +const char PLUGIN_PROVIDER_ERROR[] = QT_TRANSLATE_NOOP("QtLocationQML", "Plugin Error (%1): Could not instantiate provider"); +const char PLUGIN_NOT_VALID[] = QT_TRANSLATE_NOOP("QtLocationQML", "Plugin is not valid"); +const char CATEGORIES_NOT_INITIALIZED[] = QT_TRANSLATE_NOOP("QtLocationQML", "Unable to initialize categories"); +const char UNABLE_TO_MAKE_REQUEST[] = QT_TRANSLATE_NOOP("QtLocationQML", "Unable to create request"); +const char INDEX_OUT_OF_RANGE[] = QT_TRANSLATE_NOOP("QtLocationQML", "Index '%1' out of range"); + +QT_END_NAMESPACE diff --git a/src/imports/location/error_messages.h b/src/imports/location/error_messages.h new file mode 100644 index 0000000..81c43b3 --- /dev/null +++ b/src/imports/location/error_messages.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ERROR_MESSAGES_H +#define ERROR_MESSAGES_H + +#include + +QT_BEGIN_NAMESPACE + +extern const char CONTEXT_NAME[]; +extern const char PLUGIN_PROPERTY_NOT_SET[]; +extern const char PLUGIN_ERROR[]; +extern const char PLUGIN_PROVIDER_ERROR[]; +extern const char PLUGIN_NOT_VALID[]; +extern const char CATEGORIES_NOT_INITIALIZED[]; +extern const char UNABLE_TO_MAKE_REQUEST[]; +extern const char INDEX_OUT_OF_RANGE[]; + +QT_END_NAMESPACE + +#endif // ERROR_MESSAGES_H diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp new file mode 100644 index 0000000..b42933f --- /dev/null +++ b/src/imports/location/location.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeoserviceprovider_p.h" +#include "qdeclarativegeomap_p.h" + +#include "qdeclarativegeoroute_p.h" +#include "qdeclarativegeoroutemodel_p.h" +#include "qdeclarativegeocodemodel_p.h" +#include "qdeclarativegeomaneuver_p.h" +#include "qdeclarativegeomapquickitem_p.h" +#include "qdeclarativegeomapitemview_p.h" +#include "qdeclarativegeomaptype_p.h" +#include "qdeclarativerectanglemapitem_p.h" +#include "qdeclarativecirclemapitem_p.h" +#include "qdeclarativeroutemapitem_p.h" +#include "qdeclarativepolylinemapitem_p.h" +#include "qdeclarativepolygonmapitem_p.h" + +//Place includes +#include "qdeclarativecategory_p.h" +#include "qdeclarativeplace_p.h" +#include "qdeclarativeplaceattribute_p.h" +#include "qdeclarativeplaceicon_p.h" +#include "qdeclarativeratings_p.h" +#include "qdeclarativesupplier_p.h" +#include "qdeclarativeplaceuser_p.h" +#include "qdeclarativecontactdetail_p.h" + +#include "qdeclarativesupportedcategoriesmodel_p.h" +#include "qdeclarativesearchresultmodel_p.h" +#include "qdeclarativesearchsuggestionmodel_p.h" +#include "error_messages.h" + +#include + +#include + +static void initResources() +{ +#ifdef QT_STATIC + Q_INIT_RESOURCE(qmake_QtLocation); +#endif +} + +QT_BEGIN_NAMESPACE + + +class QtLocationDeclarativeModule: public QQmlExtensionPlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0" + FILE "plugin.json") + +public: + QtLocationDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } + virtual void registerTypes(const char *uri) + { + if (QLatin1String(uri) == QLatin1String("QtLocation")) { + + // @uri QtLocation + int major = 5; + int minor = 0; + + // Register the 5.0 types + // 5.0 is siltent and not advertised + + qmlRegisterType(uri, major, minor, "Plugin"); + qmlRegisterType(uri, major, minor, "PluginParameter"); + qmlRegisterUncreatableType(uri, major, minor, "PluginRequirements", + QStringLiteral("PluginRequirements is not intended instantiable by developer.")); + qmlRegisterType(uri, major, minor, "Map"); + + qmlRegisterUncreatableType(uri, major, minor, "GeoMapItemBase", + QStringLiteral("GeoMapItemBase is not intended instantiable by developer.")); + qmlRegisterType(uri, major, minor, "MapQuickItem"); + qmlRegisterType(uri, major, minor, "MapItemView"); + + qmlRegisterType(uri, major, minor, "GeocodeModel"); // geocoding and reverse geocoding + qmlRegisterType(uri, major, minor, "RouteModel"); + qmlRegisterType(uri, major, minor, "RouteQuery"); + qmlRegisterType(uri, major, minor, "Route"); // data type + qmlRegisterType(uri, major, minor, "RouteSegment"); + qmlRegisterType(uri, major, minor, "RouteManeuver"); + qmlRegisterUncreatableType(uri, major, minor, "MapPinchEvent", + QStringLiteral("(Map)PinchEvent is not intended instantiable by developer.")); + qmlRegisterUncreatableType(uri, major, minor, "MapGestureArea", + QStringLiteral("(Map)GestureArea is not intended instantiable by developer.")); + qmlRegisterUncreatableType(uri, major, minor, "MapType", + QStringLiteral("MapType is not intended instantiable by developer.")); + qmlRegisterType(uri, major, minor, "Category"); + qmlRegisterType(uri, major, minor, "EditorialModel"); + qmlRegisterType(uri, major, minor, "ImageModel"); + qmlRegisterType(uri, major, minor, "Place"); + qmlRegisterType(uri, major, minor, "Icon"); + qmlRegisterType(uri, major, minor, "Ratings"); + qmlRegisterType(uri, major, minor, "ReviewModel"); + qmlRegisterType(uri, major, minor, "Supplier"); + qmlRegisterType(uri, major, minor, "User"); + qmlRegisterType(uri, major, minor, "MapRectangle"); + qmlRegisterType(uri, major, minor, "MapCircle"); + qmlRegisterType(); + qmlRegisterType(uri, major, minor, "MapPolyline"); + qmlRegisterType(uri, major, minor, "MapPolygon"); + qmlRegisterType(uri, major, minor, "MapRoute"); + + qmlRegisterType(uri, major, minor, "CategoryModel"); + qmlRegisterType(uri, major, minor, "PlaceSearchModel"); + qmlRegisterType(uri, major, minor, "PlaceSearchSuggestionModel"); + qmlRegisterType(uri, major, minor, "PlaceAttribute"); + qmlRegisterUncreatableType(uri, major, minor, "ExtendedAttributes", "ExtendedAttributes instances cannot be instantiated. " + "Only Place types have ExtendedAttributes and they cannot be re-assigned " + "(but can be modified)."); + qmlRegisterType(uri, major, minor, "ContactDetail"); + qmlRegisterUncreatableType(uri, major, minor, "ContactDetails", "ContactDetails instances cannot be instantiated. " + "Only Place types have ContactDetails and they cannot " + "be re-assigned (but can be modified)."); + + // Introduction of 5.3 version; existing 5.0 exports automatically become available under 5.3 as well + // 5.3 is committed QML API despite missing release of QtLocation 5.3 + + minor = 5; + //TODO: this is broken QTBUG-50990 + qmlRegisterUncreatableType(uri, major, minor, "MapType", + QStringLiteral("MapType is not intended instantiable by developer.")); + minor = 6; + //TODO: this is broken QTBUG-50990 + qmlRegisterUncreatableType(uri, major, minor, "MapGestureArea", + QStringLiteral("(Map)GestureArea is not intended instantiable by developer.")); + + // Register the 5.7 types + minor = 7; + qmlRegisterType(uri, major, minor, "RouteManeuver"); + + //registrations below are version independent + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + } else { + qDebug() << "Unsupported URI given to load location QML plugin: " << QLatin1String(uri); + } + } +}; + +#include "location.moc" + +QT_END_NAMESPACE diff --git a/src/imports/location/location.pro b/src/imports/location/location.pro new file mode 100644 index 0000000..57172ad --- /dev/null +++ b/src/imports/location/location.pro @@ -0,0 +1,69 @@ +QT += quick-private network positioning-private location-private qml-private core-private gui-private + +INCLUDEPATH += ../../location +INCLUDEPATH += ../../location/maps +INCLUDEPATH += ../../positioning +INCLUDEPATH += ../positioning +INCLUDEPATH *= $$PWD + +HEADERS += \ + qdeclarativegeomapitemview_p.h \ + qdeclarativegeoserviceprovider_p.h \ + qdeclarativegeocodemodel_p.h \ + qdeclarativegeoroutemodel_p.h \ + qdeclarativegeoroute_p.h \ + qdeclarativegeoroutesegment_p.h \ + qdeclarativegeomaneuver_p.h \ + qdeclarativegeomap_p.h \ + qdeclarativegeomaptype_p.h \ + qdeclarativegeomapitembase_p.h \ + qdeclarativegeomapquickitem_p.h \ + qdeclarativecirclemapitem_p.h \ + qdeclarativerectanglemapitem_p.h \ + qdeclarativepolygonmapitem_p.h \ + qdeclarativepolylinemapitem_p.h \ + qdeclarativeroutemapitem_p.h \ + qgeomapitemgeometry_p.h \ + qdeclarativegeomapcopyrightsnotice_p.h \ + error_messages.h \ + locationvaluetypehelper_p.h\ + qquickgeomapgesturearea_p.h\ + ../positioning/qquickgeocoordinateanimation_p.h \ + mapitemviewdelegateincubator.h \ + qdeclarativegeomapitemview_p_p.h + +SOURCES += \ + location.cpp \ + qdeclarativegeomapitemview.cpp \ + qdeclarativegeoserviceprovider.cpp \ + qdeclarativegeocodemodel.cpp \ + qdeclarativegeoroutemodel.cpp \ + qdeclarativegeoroute.cpp \ + qdeclarativegeoroutesegment.cpp \ + qdeclarativegeomaneuver.cpp \ + qdeclarativegeomap.cpp \ + qdeclarativegeomaptype.cpp \ + qdeclarativegeomapitembase.cpp \ + qdeclarativegeomapquickitem.cpp \ + qdeclarativecirclemapitem.cpp \ + qdeclarativerectanglemapitem.cpp \ + qdeclarativepolygonmapitem.cpp \ + qdeclarativepolylinemapitem.cpp \ + qdeclarativeroutemapitem.cpp \ + qgeomapitemgeometry.cpp \ + qdeclarativegeomapcopyrightsnotice.cpp \ + error_messages.cpp \ + locationvaluetypehelper.cpp \ + qquickgeomapgesturearea.cpp \ + ../positioning/qquickgeocoordinateanimation.cpp \ + mapitemviewdelegateincubator.cpp + +include(declarativeplaces/declarativeplaces.pri) + +load(qml_plugin) + +LIBS_PRIVATE += -L$$MODULE_BASE_OUTDIR/lib -lpoly2tri$$qtPlatformTargetSuffix() -lclip2tri$$qtPlatformTargetSuffix() + +OTHER_FILES += \ + plugin.json \ + qmldir diff --git a/src/imports/location/locationvaluetypehelper.cpp b/src/imports/location/locationvaluetypehelper.cpp new file mode 100644 index 0000000..4f39e0b --- /dev/null +++ b/src/imports/location/locationvaluetypehelper.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "locationvaluetypehelper_p.h" + + +QGeoCoordinate parseCoordinate(const QJSValue &value, bool *ok) +{ + QGeoCoordinate c; + + if (value.isObject()) { + if (value.hasProperty(QStringLiteral("latitude"))) + c.setLatitude(value.property(QStringLiteral("latitude")).toNumber()); + if (value.hasProperty(QStringLiteral("longitude"))) + c.setLongitude(value.property(QStringLiteral("longitude")).toNumber()); + if (value.hasProperty(QStringLiteral("altitude"))) + c.setAltitude(value.property(QStringLiteral("altitude")).toNumber()); + + if (ok) + *ok = true; + } + + return c; +} + +QGeoRectangle parseRectangle(const QJSValue &value, bool *ok) +{ + QGeoRectangle r; + + *ok = false; + + if (value.isObject()) { + if (value.hasProperty(QStringLiteral("bottomLeft"))) { + QGeoCoordinate c = parseCoordinate(value.property(QStringLiteral("bottomLeft")), ok); + if (*ok) + r.setBottomLeft(c); + } + if (value.hasProperty(QStringLiteral("bottomRight"))) { + QGeoCoordinate c = parseCoordinate(value.property(QStringLiteral("bottomRight")), ok); + if (*ok) + r.setBottomRight(c); + } + if (value.hasProperty(QStringLiteral("topLeft"))) { + QGeoCoordinate c = parseCoordinate(value.property(QStringLiteral("topLeft")), ok); + if (*ok) + r.setTopLeft(c); + } + if (value.hasProperty(QStringLiteral("topRight"))) { + QGeoCoordinate c = parseCoordinate(value.property(QStringLiteral("topRight")), ok); + if (*ok) + r.setTopRight(c); + } + if (value.hasProperty(QStringLiteral("center"))) { + QGeoCoordinate c = parseCoordinate(value.property(QStringLiteral("center")), ok); + if (*ok) + r.setCenter(c); + } + if (value.hasProperty(QStringLiteral("height"))) + r.setHeight(value.property(QStringLiteral("height")).toNumber()); + if (value.hasProperty(QStringLiteral("width"))) + r.setWidth(value.property(QStringLiteral("width")).toNumber()); + } + + return r; +} + +QGeoCircle parseCircle(const QJSValue &value, bool *ok) +{ + QGeoCircle c; + + *ok = false; + + if (value.isObject()) { + if (value.hasProperty(QStringLiteral("center"))) { + QGeoCoordinate coord = parseCoordinate(value.property(QStringLiteral("center")), ok); + if (*ok) + c.setCenter(coord); + } + if (value.hasProperty(QStringLiteral("radius"))) + c.setRadius(value.property(QStringLiteral("radius")).toNumber()); + } + + return c; +} diff --git a/src/imports/location/locationvaluetypehelper_p.h b/src/imports/location/locationvaluetypehelper_p.h new file mode 100644 index 0000000..50038e8 --- /dev/null +++ b/src/imports/location/locationvaluetypehelper_p.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LOCATION_VALUE_TYPE_HELPER +#define LOCATION_VALUE_TYPE_HELPER + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QGeoCoordinate parseCoordinate(const QJSValue &value, bool *ok); +QGeoRectangle parseRectangle(const QJSValue &value, bool *ok); +QGeoCircle parseCircle(const QJSValue &value, bool *ok); + +#endif diff --git a/src/imports/location/mapitemviewdelegateincubator.cpp b/src/imports/location/mapitemviewdelegateincubator.cpp new file mode 100644 index 0000000..06dee7b --- /dev/null +++ b/src/imports/location/mapitemviewdelegateincubator.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Jolla Ltd, author: Aaron McCarthy +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mapitemviewdelegateincubator.h" +#include "qdeclarativegeomapitemview_p.h" +#include "qdeclarativegeomapitemview_p_p.h" + +QT_BEGIN_NAMESPACE + +MapItemViewDelegateIncubator::MapItemViewDelegateIncubator(QDeclarativeGeoMapItemView *view, QDeclarativeGeoMapItemViewItemData *itemData, bool batched) +: m_view(view), m_itemData(itemData), m_batched(batched) +{ +} + +void MapItemViewDelegateIncubator::statusChanged(QQmlIncubator::Status status) +{ + m_view->incubatorStatusChanged(this, status, m_batched); +} + +QT_END_NAMESPACE diff --git a/src/imports/location/mapitemviewdelegateincubator.h b/src/imports/location/mapitemviewdelegateincubator.h new file mode 100644 index 0000000..94c7325 --- /dev/null +++ b/src/imports/location/mapitemviewdelegateincubator.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Jolla Ltd, author: Aaron McCarthy +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef MAPITEMVIEWDELEGATEINCUBATOR_H +#define MAPITEMVIEWDELEGATEINCUBATOR_H + +#include +#include "qdeclarativegeomapitemview_p_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoMapItemView; + +class MapItemViewDelegateIncubator : public QQmlIncubator +{ +public: + MapItemViewDelegateIncubator(QDeclarativeGeoMapItemView *view, QDeclarativeGeoMapItemViewItemData *itemData, bool batched = true); + +protected: + void statusChanged(Status status) Q_DECL_OVERRIDE; + +private: + QDeclarativeGeoMapItemView *m_view; + QDeclarativeGeoMapItemViewItemData *m_itemData; + bool m_batched; + + friend class QDeclarativeGeoMapItemView; +}; + +QT_END_NAMESPACE + +#endif // MAPITEMVIEWDELEGATEINCUBATOR_H diff --git a/src/imports/location/plugin.json b/src/imports/location/plugin.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/src/imports/location/plugin.json @@ -0,0 +1,2 @@ +{ +} diff --git a/src/imports/location/plugins.qmltypes b/src/imports/location/plugins.qmltypes new file mode 100644 index 0000000..4e8749d --- /dev/null +++ b/src/imports/location/plugins.qmltypes @@ -0,0 +1,1205 @@ +import QtQuick.tooling 1.2 + +// This file describes the plugin-supplied types contained in the library. +// It is used for QML tooling purposes only. +// +// This file was auto-generated by: +// 'qmlplugindump -nonrelocatable QtLocation 5.7' + +Module { + dependencies: ["QtQuick 2.0"] + Component { + name: "QDeclarativeCategory" + prototype: "QObject" + exports: ["QtLocation/Category 5.0"] + exportMetaObjectRevisions: [0] + Enum { + name: "Visibility" + values: { + "UnspecifiedVisibility": 0, + "DeviceVisibility": 1, + "PrivateVisibility": 2, + "PublicVisibility": 4 + } + } + Enum { + name: "Status" + values: { + "Ready": 0, + "Saving": 1, + "Removing": 2, + "Error": 3 + } + } + Property { name: "category"; type: "QPlaceCategory" } + Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + Property { name: "categoryId"; type: "string" } + Property { name: "name"; type: "string" } + Property { name: "visibility"; type: "Visibility" } + Property { name: "icon"; type: "QDeclarativePlaceIcon"; isPointer: true } + Property { name: "status"; type: "Status"; isReadonly: true } + Method { name: "errorString"; type: "string" } + Method { + name: "save" + Parameter { name: "parentId"; type: "string" } + } + Method { name: "save" } + Method { name: "remove" } + } + Component { + name: "QDeclarativeCircleMapItem" + defaultProperty: "data" + prototype: "QDeclarativeGeoMapItemBase" + exports: ["QtLocation/MapCircle 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "center"; type: "QGeoCoordinate" } + Property { name: "radius"; type: "double" } + Property { name: "color"; type: "QColor" } + Property { + name: "border" + type: "QDeclarativeMapLineProperties" + isReadonly: true + isPointer: true + } + Signal { + name: "centerChanged" + Parameter { name: "center"; type: "QGeoCoordinate" } + } + Signal { + name: "radiusChanged" + Parameter { name: "radius"; type: "double" } + } + Signal { + name: "colorChanged" + Parameter { name: "color"; type: "QColor" } + } + } + Component { + name: "QDeclarativeContactDetail" + prototype: "QObject" + exports: ["QtLocation/ContactDetail 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "contactDetail"; type: "QPlaceContactDetail" } + Property { name: "label"; type: "string" } + Property { name: "value"; type: "string" } + } + Component { + name: "QDeclarativeContactDetails" + prototype: "QQmlPropertyMap" + exports: ["QtLocation/ContactDetails 5.0"] + isCreatable: false + exportMetaObjectRevisions: [0] + } + Component { + name: "QDeclarativeGeoManeuver" + prototype: "QObject" + exports: [ + "QtLocation/RouteManeuver 5.0", + "QtLocation/RouteManeuver 5.7" + ] + exportMetaObjectRevisions: [0, 0] + Enum { + name: "Direction" + values: { + "NoDirection": 0, + "DirectionForward": 1, + "DirectionBearRight": 2, + "DirectionLightRight": 3, + "DirectionRight": 4, + "DirectionHardRight": 5, + "DirectionUTurnRight": 6, + "DirectionUTurnLeft": 7, + "DirectionHardLeft": 8, + "DirectionLeft": 9, + "DirectionLightLeft": 10, + "DirectionBearLeft": 11 + } + } + Property { name: "valid"; type: "bool"; isReadonly: true } + Property { name: "position"; type: "QGeoCoordinate"; isReadonly: true } + Property { name: "instructionText"; type: "string"; isReadonly: true } + Property { name: "direction"; type: "Direction"; isReadonly: true } + Property { name: "timeToNextInstruction"; type: "int"; isReadonly: true } + Property { name: "distanceToNextInstruction"; type: "double"; isReadonly: true } + Property { name: "waypoint"; type: "QGeoCoordinate"; isReadonly: true } + Property { name: "waypointValid"; type: "bool"; isReadonly: true } + } + Component { + name: "QDeclarativeGeoMap" + defaultProperty: "data" + prototype: "QQuickItem" + exports: ["QtLocation/Map 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "gesture"; type: "QQuickGeoMapGestureArea"; isReadonly: true; isPointer: true } + Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + Property { name: "minimumZoomLevel"; type: "double" } + Property { name: "maximumZoomLevel"; type: "double" } + Property { name: "zoomLevel"; type: "double" } + Property { name: "activeMapType"; type: "QDeclarativeGeoMapType"; isPointer: true } + Property { + name: "supportedMapTypes" + type: "QDeclarativeGeoMapType" + isList: true + isReadonly: true + } + Property { name: "center"; type: "QGeoCoordinate" } + Property { name: "mapItems"; type: "QList"; isReadonly: true } + Property { name: "error"; type: "QGeoServiceProvider::Error"; isReadonly: true } + Property { name: "errorString"; type: "string"; isReadonly: true } + Property { name: "visibleRegion"; type: "QGeoShape" } + Property { name: "copyrightsVisible"; type: "bool" } + Property { name: "color"; type: "QColor" } + Signal { + name: "pluginChanged" + Parameter { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + } + Signal { + name: "zoomLevelChanged" + Parameter { name: "zoomLevel"; type: "double" } + } + Signal { + name: "centerChanged" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + Signal { + name: "copyrightLinkActivated" + Parameter { name: "link"; type: "string" } + } + Signal { + name: "copyrightsVisibleChanged" + Parameter { name: "visible"; type: "bool" } + } + Signal { + name: "colorChanged" + Parameter { name: "color"; type: "QColor" } + } + Method { + name: "removeMapItem" + Parameter { name: "item"; type: "QDeclarativeGeoMapItemBase"; isPointer: true } + } + Method { + name: "addMapItem" + Parameter { name: "item"; type: "QDeclarativeGeoMapItemBase"; isPointer: true } + } + Method { name: "clearMapItems" } + Method { + name: "toCoordinate" + type: "QGeoCoordinate" + Parameter { name: "position"; type: "QPointF" } + Parameter { name: "clipToViewPort"; type: "bool" } + } + Method { + name: "toCoordinate" + type: "QGeoCoordinate" + Parameter { name: "position"; type: "QPointF" } + } + Method { + name: "fromCoordinate" + type: "QPointF" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + Parameter { name: "clipToViewPort"; type: "bool" } + } + Method { + name: "fromCoordinate" + type: "QPointF" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + Method { name: "fitViewportToMapItems" } + Method { + name: "pan" + Parameter { name: "dx"; type: "int" } + Parameter { name: "dy"; type: "int" } + } + Method { name: "prefetchData" } + Method { name: "clearData" } + } + Component { + name: "QDeclarativeGeoMapItemBase" + defaultProperty: "data" + prototype: "QQuickItem" + exports: ["QtLocation/GeoMapItemBase 5.0"] + isCreatable: false + exportMetaObjectRevisions: [0] + } + Component { + name: "QDeclarativeGeoMapItemView" + prototype: "QObject" + exports: ["QtLocation/MapItemView 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "model"; type: "QVariant" } + Property { name: "delegate"; type: "QQmlComponent"; isPointer: true } + Property { name: "autoFitViewport"; type: "bool" } + } + Component { + name: "QDeclarativeGeoMapQuickItem" + defaultProperty: "data" + prototype: "QDeclarativeGeoMapItemBase" + exports: ["QtLocation/MapQuickItem 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "coordinate"; type: "QGeoCoordinate" } + Property { name: "anchorPoint"; type: "QPointF" } + Property { name: "zoomLevel"; type: "double" } + Property { name: "sourceItem"; type: "QQuickItem"; isPointer: true } + } + Component { + name: "QDeclarativeGeoMapType" + prototype: "QObject" + exports: ["QtLocation/MapType 5.0", "QtLocation/MapType 5.5"] + isCreatable: false + exportMetaObjectRevisions: [0, 1] + Enum { + name: "MapStyle" + values: { + "NoMap": 0, + "StreetMap": 1, + "SatelliteMapDay": 2, + "SatelliteMapNight": 3, + "TerrainMap": 4, + "HybridMap": 5, + "TransitMap": 6, + "GrayStreetMap": 7, + "PedestrianMap": 8, + "CarNavigationMap": 9, + "CycleMap": 10, + "CustomMap": 100 + } + } + Property { name: "style"; type: "MapStyle"; isReadonly: true } + Property { name: "name"; type: "string"; isReadonly: true } + Property { name: "description"; type: "string"; isReadonly: true } + Property { name: "mobile"; type: "bool"; isReadonly: true } + Property { name: "night"; revision: 1; type: "bool"; isReadonly: true } + } + Component { + name: "QDeclarativeGeoRoute" + prototype: "QObject" + exports: ["QtLocation/Route 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "bounds"; type: "QGeoRectangle"; isReadonly: true } + Property { name: "travelTime"; type: "int"; isReadonly: true } + Property { name: "distance"; type: "double"; isReadonly: true } + Property { name: "path"; type: "QJSValue" } + Property { name: "segments"; type: "QDeclarativeGeoRouteSegment"; isList: true; isReadonly: true } + } + Component { + name: "QDeclarativeGeoRouteModel" + prototype: "QAbstractListModel" + exports: ["QtLocation/RouteModel 5.0"] + exportMetaObjectRevisions: [0] + Enum { + name: "Status" + values: { + "Null": 0, + "Ready": 1, + "Loading": 2, + "Error": 3 + } + } + Enum { + name: "RouteError" + values: { + "NoError": 0, + "EngineNotSetError": 1, + "CommunicationError": 2, + "ParseError": 3, + "UnsupportedOptionError": 4, + "UnknownError": 5, + "UnknownParameterError": 100, + "MissingRequiredParameterError": 101 + } + } + Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + Property { name: "query"; type: "QDeclarativeGeoRouteQuery"; isPointer: true } + Property { name: "count"; type: "int"; isReadonly: true } + Property { name: "autoUpdate"; type: "bool" } + Property { name: "status"; type: "Status"; isReadonly: true } + Property { name: "errorString"; type: "string"; isReadonly: true } + Property { name: "error"; type: "RouteError"; isReadonly: true } + Property { name: "measurementSystem"; type: "QLocale::MeasurementSystem" } + Signal { name: "routesChanged" } + Method { name: "update" } + Method { + name: "get" + type: "QDeclarativeGeoRoute*" + Parameter { name: "index"; type: "int" } + } + Method { name: "reset" } + Method { name: "cancel" } + } + Component { + name: "QDeclarativeGeoRouteQuery" + prototype: "QObject" + exports: ["QtLocation/RouteQuery 5.0"] + exportMetaObjectRevisions: [0] + Enum { + name: "TravelMode" + values: { + "CarTravel": 1, + "PedestrianTravel": 2, + "BicycleTravel": 4, + "PublicTransitTravel": 8, + "TruckTravel": 16 + } + } + Enum { + name: "TravelModes" + values: { + "CarTravel": 1, + "PedestrianTravel": 2, + "BicycleTravel": 4, + "PublicTransitTravel": 8, + "TruckTravel": 16 + } + } + Enum { + name: "FeatureType" + values: { + "NoFeature": 0, + "TollFeature": 1, + "HighwayFeature": 2, + "PublicTransitFeature": 4, + "FerryFeature": 8, + "TunnelFeature": 16, + "DirtRoadFeature": 32, + "ParksFeature": 64, + "MotorPoolLaneFeature": 128 + } + } + Enum { + name: "FeatureWeight" + values: { + "NeutralFeatureWeight": 0, + "PreferFeatureWeight": 1, + "RequireFeatureWeight": 2, + "AvoidFeatureWeight": 4, + "DisallowFeatureWeight": 8 + } + } + Enum { + name: "RouteOptimization" + values: { + "ShortestRoute": 1, + "FastestRoute": 2, + "MostEconomicRoute": 4, + "MostScenicRoute": 8 + } + } + Enum { + name: "RouteOptimizations" + values: { + "ShortestRoute": 1, + "FastestRoute": 2, + "MostEconomicRoute": 4, + "MostScenicRoute": 8 + } + } + Enum { + name: "SegmentDetail" + values: { + "NoSegmentData": 0, + "BasicSegmentData": 1 + } + } + Enum { + name: "SegmentDetails" + values: { + "NoSegmentData": 0, + "BasicSegmentData": 1 + } + } + Enum { + name: "ManeuverDetail" + values: { + "NoManeuvers": 0, + "BasicManeuvers": 1 + } + } + Enum { + name: "ManeuverDetails" + values: { + "NoManeuvers": 0, + "BasicManeuvers": 1 + } + } + Property { name: "numberAlternativeRoutes"; type: "int" } + Property { name: "travelModes"; type: "TravelModes" } + Property { name: "routeOptimizations"; type: "RouteOptimizations" } + Property { name: "segmentDetail"; type: "SegmentDetail" } + Property { name: "maneuverDetail"; type: "ManeuverDetail" } + Property { name: "waypoints"; type: "QJSValue" } + Property { name: "excludedAreas"; type: "QJSValue" } + Property { name: "featureTypes"; type: "QList"; isReadonly: true } + Signal { name: "queryDetailsChanged" } + Method { + name: "addWaypoint" + Parameter { name: "waypoint"; type: "QGeoCoordinate" } + } + Method { + name: "removeWaypoint" + Parameter { name: "waypoint"; type: "QGeoCoordinate" } + } + Method { name: "clearWaypoints" } + Method { + name: "addExcludedArea" + Parameter { name: "area"; type: "QGeoRectangle" } + } + Method { + name: "removeExcludedArea" + Parameter { name: "area"; type: "QGeoRectangle" } + } + Method { name: "clearExcludedAreas" } + Method { + name: "setFeatureWeight" + Parameter { name: "featureType"; type: "FeatureType" } + Parameter { name: "featureWeight"; type: "FeatureWeight" } + } + Method { + name: "featureWeight" + type: "int" + Parameter { name: "featureType"; type: "FeatureType" } + } + Method { name: "resetFeatureWeights" } + } + Component { + name: "QDeclarativeGeoRouteSegment" + prototype: "QObject" + exports: ["QtLocation/RouteSegment 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "travelTime"; type: "int"; isReadonly: true } + Property { name: "distance"; type: "double"; isReadonly: true } + Property { name: "path"; type: "QJSValue"; isReadonly: true } + Property { name: "maneuver"; type: "QDeclarativeGeoManeuver"; isReadonly: true; isPointer: true } + } + Component { + name: "QDeclarativeGeoServiceProvider" + defaultProperty: "parameters" + prototype: "QObject" + exports: ["QtLocation/Plugin 5.0"] + exportMetaObjectRevisions: [0] + Enum { + name: "RoutingFeature" + values: { + "NoRoutingFeatures": 0, + "OnlineRoutingFeature": 1, + "OfflineRoutingFeature": 2, + "LocalizedRoutingFeature": 4, + "RouteUpdatesFeature": 8, + "AlternativeRoutesFeature": 16, + "ExcludeAreasRoutingFeature": 32, + "AnyRoutingFeatures": -1 + } + } + Enum { + name: "RoutingFeatures" + values: { + "NoRoutingFeatures": 0, + "OnlineRoutingFeature": 1, + "OfflineRoutingFeature": 2, + "LocalizedRoutingFeature": 4, + "RouteUpdatesFeature": 8, + "AlternativeRoutesFeature": 16, + "ExcludeAreasRoutingFeature": 32, + "AnyRoutingFeatures": -1 + } + } + Enum { + name: "GeocodingFeature" + values: { + "NoGeocodingFeatures": 0, + "OnlineGeocodingFeature": 1, + "OfflineGeocodingFeature": 2, + "ReverseGeocodingFeature": 4, + "LocalizedGeocodingFeature": 8, + "AnyGeocodingFeatures": -1 + } + } + Enum { + name: "GeocodingFeatures" + values: { + "NoGeocodingFeatures": 0, + "OnlineGeocodingFeature": 1, + "OfflineGeocodingFeature": 2, + "ReverseGeocodingFeature": 4, + "LocalizedGeocodingFeature": 8, + "AnyGeocodingFeatures": -1 + } + } + Enum { + name: "MappingFeature" + values: { + "NoMappingFeatures": 0, + "OnlineMappingFeature": 1, + "OfflineMappingFeature": 2, + "LocalizedMappingFeature": 4, + "AnyMappingFeatures": -1 + } + } + Enum { + name: "MappingFeatures" + values: { + "NoMappingFeatures": 0, + "OnlineMappingFeature": 1, + "OfflineMappingFeature": 2, + "LocalizedMappingFeature": 4, + "AnyMappingFeatures": -1 + } + } + Enum { + name: "PlacesFeature" + values: { + "NoPlacesFeatures": 0, + "OnlinePlacesFeature": 1, + "OfflinePlacesFeature": 2, + "SavePlaceFeature": 4, + "RemovePlaceFeature": 8, + "SaveCategoryFeature": 16, + "RemoveCategoryFeature": 32, + "PlaceRecommendationsFeature": 64, + "SearchSuggestionsFeature": 128, + "LocalizedPlacesFeature": 256, + "NotificationsFeature": 512, + "PlaceMatchingFeature": 1024, + "AnyPlacesFeatures": -1 + } + } + Enum { + name: "PlacesFeatures" + values: { + "NoPlacesFeatures": 0, + "OnlinePlacesFeature": 1, + "OfflinePlacesFeature": 2, + "SavePlaceFeature": 4, + "RemovePlaceFeature": 8, + "SaveCategoryFeature": 16, + "RemoveCategoryFeature": 32, + "PlaceRecommendationsFeature": 64, + "SearchSuggestionsFeature": 128, + "LocalizedPlacesFeature": 256, + "NotificationsFeature": 512, + "PlaceMatchingFeature": 1024, + "AnyPlacesFeatures": -1 + } + } + Property { name: "name"; type: "string" } + Property { name: "availableServiceProviders"; type: "QStringList"; isReadonly: true } + Property { + name: "parameters" + type: "QDeclarativeGeoServiceProviderParameter" + isList: true + isReadonly: true + } + Property { + name: "required" + type: "QDeclarativeGeoServiceProviderRequirements" + isReadonly: true + isPointer: true + } + Property { name: "locales"; type: "QStringList" } + Property { name: "preferred"; type: "QStringList" } + Property { name: "allowExperimental"; type: "bool" } + Property { name: "isAttached"; type: "bool"; isReadonly: true } + Signal { + name: "nameChanged" + Parameter { name: "name"; type: "string" } + } + Signal { name: "attached" } + Signal { + name: "preferredChanged" + Parameter { name: "preferences"; type: "QStringList" } + } + Signal { + name: "allowExperimentalChanged" + Parameter { name: "allow"; type: "bool" } + } + Method { + name: "supportsRouting" + type: "bool" + Parameter { name: "feature"; type: "RoutingFeatures" } + } + Method { name: "supportsRouting"; type: "bool" } + Method { + name: "supportsGeocoding" + type: "bool" + Parameter { name: "feature"; type: "GeocodingFeatures" } + } + Method { name: "supportsGeocoding"; type: "bool" } + Method { + name: "supportsMapping" + type: "bool" + Parameter { name: "feature"; type: "MappingFeatures" } + } + Method { name: "supportsMapping"; type: "bool" } + Method { + name: "supportsPlaces" + type: "bool" + Parameter { name: "feature"; type: "PlacesFeatures" } + } + Method { name: "supportsPlaces"; type: "bool" } + } + Component { + name: "QDeclarativeGeoServiceProviderParameter" + prototype: "QObject" + exports: ["QtLocation/PluginParameter 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "name"; type: "string" } + Property { name: "value"; type: "QVariant" } + Signal { + name: "nameChanged" + Parameter { name: "name"; type: "string" } + } + Signal { + name: "valueChanged" + Parameter { name: "value"; type: "QVariant" } + } + } + Component { + name: "QDeclarativeGeoServiceProviderRequirements" + prototype: "QObject" + exports: ["QtLocation/PluginRequirements 5.0"] + isCreatable: false + exportMetaObjectRevisions: [0] + Property { name: "mapping"; type: "QDeclarativeGeoServiceProvider::MappingFeatures" } + Property { name: "routing"; type: "QDeclarativeGeoServiceProvider::RoutingFeatures" } + Property { name: "geocoding"; type: "QDeclarativeGeoServiceProvider::GeocodingFeatures" } + Property { name: "places"; type: "QDeclarativeGeoServiceProvider::PlacesFeatures" } + Signal { + name: "mappingRequirementsChanged" + Parameter { name: "features"; type: "QDeclarativeGeoServiceProvider::MappingFeatures" } + } + Signal { + name: "routingRequirementsChanged" + Parameter { name: "features"; type: "QDeclarativeGeoServiceProvider::RoutingFeatures" } + } + Signal { + name: "geocodingRequirementsChanged" + Parameter { name: "features"; type: "QDeclarativeGeoServiceProvider::GeocodingFeatures" } + } + Signal { + name: "placesRequirementsChanged" + Parameter { name: "features"; type: "QDeclarativeGeoServiceProvider::PlacesFeatures" } + } + Signal { name: "requirementsChanged" } + Method { + name: "matches" + type: "bool" + Parameter { name: "provider"; type: "const QGeoServiceProvider"; isPointer: true } + } + } + Component { + name: "QDeclarativeGeocodeModel" + prototype: "QAbstractListModel" + exports: ["QtLocation/GeocodeModel 5.0"] + exportMetaObjectRevisions: [0] + Enum { + name: "Status" + values: { + "Null": 0, + "Ready": 1, + "Loading": 2, + "Error": 3 + } + } + Enum { + name: "GeocodeError" + values: { + "NoError": 0, + "EngineNotSetError": 1, + "CommunicationError": 2, + "ParseError": 3, + "UnsupportedOptionError": 4, + "CombinationError": 5, + "UnknownError": 6, + "UnknownParameterError": 100, + "MissingRequiredParameterError": 101 + } + } + Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + Property { name: "autoUpdate"; type: "bool" } + Property { name: "status"; type: "Status"; isReadonly: true } + Property { name: "errorString"; type: "string"; isReadonly: true } + Property { name: "count"; type: "int"; isReadonly: true } + Property { name: "limit"; type: "int" } + Property { name: "offset"; type: "int" } + Property { name: "query"; type: "QVariant" } + Property { name: "bounds"; type: "QVariant" } + Property { name: "error"; type: "GeocodeError"; isReadonly: true } + Signal { name: "locationsChanged" } + Method { name: "update" } + Method { + name: "get" + type: "QDeclarativeGeoLocation*" + Parameter { name: "index"; type: "int" } + } + Method { name: "reset" } + Method { name: "cancel" } + } + Component { + name: "QDeclarativeMapLineProperties" + prototype: "QObject" + Property { name: "width"; type: "double" } + Property { name: "color"; type: "QColor" } + Signal { + name: "widthChanged" + Parameter { name: "width"; type: "double" } + } + Signal { + name: "colorChanged" + Parameter { name: "color"; type: "QColor" } + } + } + Component { + name: "QDeclarativePlace" + prototype: "QObject" + exports: ["QtLocation/Place 5.0"] + exportMetaObjectRevisions: [0] + Enum { + name: "Status" + values: { + "Ready": 0, + "Saving": 1, + "Fetching": 2, + "Removing": 3, + "Error": 4 + } + } + Enum { + name: "Visibility" + values: { + "UnspecifiedVisibility": 0, + "DeviceVisibility": 1, + "PrivateVisibility": 2, + "PublicVisibility": 4 + } + } + Property { name: "place"; type: "QPlace" } + Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + Property { name: "categories"; type: "QDeclarativeCategory"; isList: true; isReadonly: true } + Property { name: "location"; type: "QDeclarativeGeoLocation"; isPointer: true } + Property { name: "ratings"; type: "QDeclarativeRatings"; isPointer: true } + Property { name: "supplier"; type: "QDeclarativeSupplier"; isPointer: true } + Property { name: "icon"; type: "QDeclarativePlaceIcon"; isPointer: true } + Property { name: "name"; type: "string" } + Property { name: "placeId"; type: "string" } + Property { name: "attribution"; type: "string" } + Property { + name: "reviewModel" + type: "QDeclarativeReviewModel" + isReadonly: true + isPointer: true + } + Property { + name: "imageModel" + type: "QDeclarativePlaceImageModel" + isReadonly: true + isPointer: true + } + Property { + name: "editorialModel" + type: "QDeclarativePlaceEditorialModel" + isReadonly: true + isPointer: true + } + Property { name: "extendedAttributes"; type: "QObject"; isReadonly: true; isPointer: true } + Property { name: "contactDetails"; type: "QObject"; isReadonly: true; isPointer: true } + Property { name: "detailsFetched"; type: "bool"; isReadonly: true } + Property { name: "status"; type: "Status"; isReadonly: true } + Property { name: "primaryPhone"; type: "string"; isReadonly: true } + Property { name: "primaryFax"; type: "string"; isReadonly: true } + Property { name: "primaryEmail"; type: "string"; isReadonly: true } + Property { name: "primaryWebsite"; type: "QUrl"; isReadonly: true } + Property { name: "visibility"; type: "Visibility" } + Property { name: "favorite"; type: "QDeclarativePlace"; isPointer: true } + Method { name: "getDetails" } + Method { name: "save" } + Method { name: "remove" } + Method { name: "errorString"; type: "string" } + Method { + name: "copyFrom" + Parameter { name: "original"; type: "QDeclarativePlace"; isPointer: true } + } + Method { + name: "initializeFavorite" + Parameter { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + } + } + Component { + name: "QDeclarativePlaceAttribute" + prototype: "QObject" + exports: ["QtLocation/PlaceAttribute 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "attribute"; type: "QPlaceAttribute" } + Property { name: "label"; type: "string" } + Property { name: "text"; type: "string" } + } + Component { + name: "QDeclarativePlaceContentModel" + prototype: "QAbstractListModel" + Property { name: "place"; type: "QDeclarativePlace"; isPointer: true } + Property { name: "batchSize"; type: "int" } + Property { name: "totalCount"; type: "int"; isReadonly: true } + } + Component { + name: "QDeclarativePlaceEditorialModel" + prototype: "QDeclarativePlaceContentModel" + exports: ["QtLocation/EditorialModel 5.0"] + exportMetaObjectRevisions: [0] + } + Component { + name: "QDeclarativePlaceIcon" + prototype: "QObject" + exports: ["QtLocation/Icon 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "icon"; type: "QPlaceIcon" } + Property { name: "parameters"; type: "QObject"; isReadonly: true; isPointer: true } + Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + Method { + name: "url" + type: "QUrl" + Parameter { name: "size"; type: "QSize" } + } + Method { name: "url"; type: "QUrl" } + } + Component { + name: "QDeclarativePlaceImageModel" + prototype: "QDeclarativePlaceContentModel" + exports: ["QtLocation/ImageModel 5.0"] + exportMetaObjectRevisions: [0] + } + Component { + name: "QDeclarativePlaceUser" + prototype: "QObject" + exports: ["QtLocation/User 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "user"; type: "QPlaceUser" } + Property { name: "userId"; type: "string" } + Property { name: "name"; type: "string" } + } + Component { + name: "QDeclarativePolygonMapItem" + defaultProperty: "data" + prototype: "QDeclarativeGeoMapItemBase" + exports: ["QtLocation/MapPolygon 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "path"; type: "QJSValue" } + Property { name: "color"; type: "QColor" } + Property { + name: "border" + type: "QDeclarativeMapLineProperties" + isReadonly: true + isPointer: true + } + Signal { + name: "colorChanged" + Parameter { name: "color"; type: "QColor" } + } + Method { + name: "addCoordinate" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + Method { + name: "removeCoordinate" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + } + Component { + name: "QDeclarativePolylineMapItem" + defaultProperty: "data" + prototype: "QDeclarativeGeoMapItemBase" + exports: ["QtLocation/MapPolyline 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "path"; type: "QJSValue" } + Property { + name: "line" + type: "QDeclarativeMapLineProperties" + isReadonly: true + isPointer: true + } + Method { name: "pathLength"; type: "int" } + Method { + name: "addCoordinate" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + Method { + name: "insertCoordinate" + Parameter { name: "index"; type: "int" } + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + Method { + name: "replaceCoordinate" + Parameter { name: "index"; type: "int" } + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + Method { + name: "coordinateAt" + type: "QGeoCoordinate" + Parameter { name: "index"; type: "int" } + } + Method { + name: "containsCoordinate" + type: "bool" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + Method { + name: "removeCoordinate" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + Method { + name: "removeCoordinate" + Parameter { name: "index"; type: "int" } + } + } + Component { + name: "QDeclarativeRatings" + prototype: "QObject" + exports: ["QtLocation/Ratings 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "ratings"; type: "QPlaceRatings" } + Property { name: "average"; type: "double" } + Property { name: "maximum"; type: "double" } + Property { name: "count"; type: "int" } + } + Component { + name: "QDeclarativeRectangleMapItem" + defaultProperty: "data" + prototype: "QDeclarativeGeoMapItemBase" + exports: ["QtLocation/MapRectangle 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "topLeft"; type: "QGeoCoordinate" } + Property { name: "bottomRight"; type: "QGeoCoordinate" } + Property { name: "color"; type: "QColor" } + Property { + name: "border" + type: "QDeclarativeMapLineProperties" + isReadonly: true + isPointer: true + } + Signal { + name: "topLeftChanged" + Parameter { name: "topLeft"; type: "QGeoCoordinate" } + } + Signal { + name: "bottomRightChanged" + Parameter { name: "bottomRight"; type: "QGeoCoordinate" } + } + Signal { + name: "colorChanged" + Parameter { name: "color"; type: "QColor" } + } + } + Component { + name: "QDeclarativeReviewModel" + prototype: "QDeclarativePlaceContentModel" + exports: ["QtLocation/ReviewModel 5.0"] + exportMetaObjectRevisions: [0] + } + Component { + name: "QDeclarativeRouteMapItem" + defaultProperty: "data" + prototype: "QDeclarativePolylineMapItem" + exports: ["QtLocation/MapRoute 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "route"; type: "QDeclarativeGeoRoute"; isPointer: true } + Signal { + name: "routeChanged" + Parameter { name: "route"; type: "const QDeclarativeGeoRoute"; isPointer: true } + } + } + Component { + name: "QDeclarativeSearchModelBase" + prototype: "QAbstractListModel" + Enum { + name: "Status" + values: { + "Null": 0, + "Ready": 1, + "Loading": 2, + "Error": 3 + } + } + Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + Property { name: "searchArea"; type: "QVariant" } + Property { name: "limit"; type: "int" } + Property { name: "previousPagesAvailable"; type: "bool"; isReadonly: true } + Property { name: "nextPagesAvailable"; type: "bool"; isReadonly: true } + Property { name: "status"; type: "Status"; isReadonly: true } + Method { name: "update" } + Method { name: "cancel" } + Method { name: "reset" } + Method { name: "errorString"; type: "string" } + Method { name: "previousPage" } + Method { name: "nextPage" } + } + Component { + name: "QDeclarativeSearchResultModel" + prototype: "QDeclarativeSearchModelBase" + exports: ["QtLocation/PlaceSearchModel 5.0"] + exportMetaObjectRevisions: [0] + Enum { + name: "SearchResultType" + values: { + "UnknownSearchResult": 0, + "PlaceResult": 1, + "ProposedSearchResult": 2 + } + } + Enum { + name: "RelevanceHint" + values: { + "UnspecifiedHint": 0, + "DistanceHint": 1, + "LexicalPlaceNameHint": 2 + } + } + Property { name: "searchTerm"; type: "string" } + Property { name: "categories"; type: "QDeclarativeCategory"; isList: true; isReadonly: true } + Property { name: "recommendationId"; type: "string" } + Property { name: "relevanceHint"; type: "RelevanceHint" } + Property { name: "visibilityScope"; type: "QDeclarativePlace::Visibility" } + Property { name: "count"; type: "int"; isReadonly: true } + Property { name: "favoritesPlugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + Property { name: "favoritesMatchParameters"; type: "QVariantMap" } + Signal { name: "rowCountChanged" } + Signal { name: "dataChanged" } + Method { + name: "data" + type: "QVariant" + Parameter { name: "index"; type: "int" } + Parameter { name: "roleName"; type: "string" } + } + Method { + name: "updateWith" + Parameter { name: "proposedSearchIndex"; type: "int" } + } + } + Component { + name: "QDeclarativeSearchSuggestionModel" + prototype: "QDeclarativeSearchModelBase" + exports: ["QtLocation/PlaceSearchSuggestionModel 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "searchTerm"; type: "string" } + Property { name: "suggestions"; type: "QStringList"; isReadonly: true } + } + Component { + name: "QDeclarativeSupplier" + prototype: "QObject" + exports: ["QtLocation/Supplier 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "supplier"; type: "QPlaceSupplier" } + Property { name: "name"; type: "string" } + Property { name: "supplierId"; type: "string" } + Property { name: "url"; type: "QUrl" } + Property { name: "icon"; type: "QDeclarativePlaceIcon"; isPointer: true } + } + Component { + name: "QDeclarativeSupportedCategoriesModel" + prototype: "QAbstractItemModel" + exports: ["QtLocation/CategoryModel 5.0"] + exportMetaObjectRevisions: [0] + Enum { + name: "Roles" + values: { + "CategoryRole": 256, + "ParentCategoryRole": 257 + } + } + Enum { + name: "Status" + values: { + "Null": 0, + "Ready": 1, + "Loading": 2, + "Error": 3 + } + } + Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } + Property { name: "hierarchical"; type: "bool" } + Property { name: "status"; type: "Status"; isReadonly: true } + Signal { name: "dataChanged" } + Method { name: "update" } + Method { + name: "data" + type: "QVariant" + Parameter { name: "index"; type: "QModelIndex" } + Parameter { name: "role"; type: "int" } + } + Method { name: "errorString"; type: "string" } + } + Component { + name: "QGeoMapPinchEvent" + prototype: "QObject" + exports: ["QtLocation/MapPinchEvent 5.0"] + isCreatable: false + exportMetaObjectRevisions: [0] + Property { name: "center"; type: "QPointF"; isReadonly: true } + Property { name: "angle"; type: "double"; isReadonly: true } + Property { name: "point1"; type: "QPointF"; isReadonly: true } + Property { name: "point2"; type: "QPointF"; isReadonly: true } + Property { name: "pointCount"; type: "int"; isReadonly: true } + Property { name: "accepted"; type: "bool" } + } + Component { + name: "QQmlPropertyMap" + prototype: "QObject" + exports: ["QtLocation/ExtendedAttributes 5.0"] + isCreatable: false + exportMetaObjectRevisions: [0] + Signal { + name: "valueChanged" + Parameter { name: "key"; type: "string" } + Parameter { name: "value"; type: "QVariant" } + } + Method { name: "keys"; type: "QStringList" } + } + Component { + name: "QQuickGeoMapGestureArea" + defaultProperty: "data" + prototype: "QQuickItem" + exports: [ + "QtLocation/MapGestureArea 5.0", + "QtLocation/MapGestureArea 5.6" + ] + isCreatable: false + exportMetaObjectRevisions: [0, 1] + Enum { + name: "GeoMapGesture" + values: { + "NoGesture": 0, + "PinchGesture": 1, + "PanGesture": 2, + "FlickGesture": 4 + } + } + Enum { + name: "AcceptedGestures" + values: { + "NoGesture": 0, + "PinchGesture": 1, + "PanGesture": 2, + "FlickGesture": 4 + } + } + Property { name: "enabled"; type: "bool" } + Property { name: "pinchActive"; type: "bool"; isReadonly: true } + Property { name: "panActive"; type: "bool"; isReadonly: true } + Property { name: "acceptedGestures"; type: "AcceptedGestures" } + Property { name: "maximumZoomLevelChange"; type: "double" } + Property { name: "flickDeceleration"; type: "double" } + Property { name: "preventStealing"; revision: 1; type: "bool" } + Signal { + name: "pinchStarted" + Parameter { name: "pinch"; type: "QGeoMapPinchEvent"; isPointer: true } + } + Signal { + name: "pinchUpdated" + Parameter { name: "pinch"; type: "QGeoMapPinchEvent"; isPointer: true } + } + Signal { + name: "pinchFinished" + Parameter { name: "pinch"; type: "QGeoMapPinchEvent"; isPointer: true } + } + Signal { name: "panStarted" } + Signal { name: "panFinished" } + Signal { name: "flickStarted" } + Signal { name: "flickFinished" } + } +} diff --git a/src/imports/location/qdeclarativecirclemapitem.cpp b/src/imports/location/qdeclarativecirclemapitem.cpp new file mode 100644 index 0000000..f6b3c14 --- /dev/null +++ b/src/imports/location/qdeclarativecirclemapitem.cpp @@ -0,0 +1,657 @@ +/*************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativecirclemapitem_p.h" +#include "qdeclarativepolygonmapitem_p.h" +#include "qgeocameracapabilities_p.h" +#include "qgeoprojection_p.h" + +#include + +#include +#include +#include + +#include "qdoublevector2d_p.h" + +/* poly2tri triangulator includes */ +#include "../../3rdparty/poly2tri/common/shapes.h" +#include "../../3rdparty/poly2tri/sweep/cdt.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype MapCircle + \instantiates QDeclarativeCircleMapItem + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.5 + + \brief The MapCircle type displays a geographic circle on a Map. + + The MapCircle type displays a geographic circle on a Map, which + consists of all points that are within a set distance from one + central point. Depending on map projection, a geographic circle + may not always be a perfect circle on the screen: for instance, in + the Mercator projection, circles become ovoid in shape as they near + the poles. To display a perfect screen circle around a point, use a + MapQuickItem containing a relevant Qt Quick type instead. + + By default, the circle is displayed as a 1 pixel black border with + no fill. To change its appearance, use the color, border.color + and border.width properties. + + Internally, a MapCircle is implemented as a many-sided polygon. To + calculate the radius points it uses a spherical model of the Earth, + similar to the atDistanceAndAzimuth method of the \l {coordinate} + type. These two things can occasionally have implications for the + accuracy of the circle's shape, depending on position and map + projection. + + \note Dragging a MapCircle (through the use of \l MouseArea) + causes new points to be generated at the same distance (in meters) + from the center. This is in contrast to other map items which store + their dimensions in terms of latitude and longitude differences between + vertices. + + \section2 Performance + + MapCircle performance is almost equivalent to that of a MapPolygon with + the same number of vertices. There is a small amount of additional + overhead with respect to calculating the vertices first. + + Like the other map objects, MapCircle is normally drawn without a smooth + appearance. Setting the opacity property will force the object to be + blended, which decreases performance considerably depending on the graphics + hardware in use. + + \section2 Example Usage + + The following snippet shows a map containing a MapCircle, centered at + the coordinate (-27, 153) with a radius of 5km. The circle is + filled in green, with a 3 pixel black border. + + \code + Map { + MapCircle { + center { + latitude: -27.5 + longitude: 153.0 + } + radius: 5000.0 + color: 'green' + border.width: 3 + } + } + \endcode + + \image api-mapcircle.png +*/ + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +static const int CircleSamples = 128; + +struct Vertex +{ + QVector2D position; +}; + +QGeoMapCircleGeometry::QGeoMapCircleGeometry() +{ +} + +/*! + \internal +*/ +void QGeoMapCircleGeometry::updateScreenPointsInvert(const QGeoMap &map) +{ + if (!screenDirty_) + return; + + if (map.width() == 0 || map.height() == 0) { + clear(); + return; + } + + QPointF origin = map.coordinateToItemPosition(srcOrigin_, false).toPointF(); + + QPainterPath ppi = srcPath_; + + clear(); + + // a circle requires at least 3 points; + if (ppi.elementCount() < 3) + return; + + // translate the path into top-left-centric coordinates + QRectF bb = ppi.boundingRect(); + ppi.translate(-bb.left(), -bb.top()); + firstPointOffset_ = -1 * bb.topLeft(); + + ppi.closeSubpath(); + + // calculate actual width of map on screen in pixels + QGeoCoordinate mapCenter(0, map.cameraData().center().longitude()); + QDoubleVector2D midPoint = map.coordinateToItemPosition(mapCenter, false); + QDoubleVector2D midPointPlusOne = QDoubleVector2D(midPoint.x() + 1.0, midPoint.y()); + QGeoCoordinate coord1 = map.itemPositionToCoordinate(midPointPlusOne, false); + double geoDistance = coord1.longitude() - map.cameraData().center().longitude(); + if ( geoDistance < 0 ) + geoDistance += 360.0; + double mapWidth = 360.0 / geoDistance; + + qreal leftOffset = origin.x() - (map.width()/2.0 - mapWidth/2.0) - firstPointOffset_.x(); + qreal topOffset = origin.y() - (midPoint.y() - mapWidth/2.0) - firstPointOffset_.y(); + QPainterPath ppiBorder; + ppiBorder.moveTo(QPointF(-leftOffset, -topOffset)); + ppiBorder.lineTo(QPointF(mapWidth - leftOffset, -topOffset)); + ppiBorder.lineTo(QPointF(mapWidth - leftOffset, mapWidth - topOffset)); + ppiBorder.lineTo(QPointF(-leftOffset, mapWidth - topOffset)); + + screenOutline_ = ppiBorder; + + std::vector borderPts; + borderPts.reserve(4); + + std::vector curPts; + curPts.reserve(ppi.elementCount()); + for (int i = 0; i < ppi.elementCount(); ++i) { + const QPainterPath::Element e = ppi.elementAt(i); + if (e.isMoveTo() || i == ppi.elementCount() - 1 + || (qAbs(e.x - curPts.front()->x) < 0.1 + && qAbs(e.y - curPts.front()->y) < 0.1)) { + if (curPts.size() > 2) { + for (int j = 0; j < 4; ++j) { + const QPainterPath::Element e2 = ppiBorder.elementAt(j); + borderPts.push_back(new p2t::Point(e2.x, e2.y)); + } + p2t::CDT *cdt = new p2t::CDT(borderPts); + cdt->AddHole(curPts); + cdt->Triangulate(); + std::vector tris = cdt->GetTriangles(); + screenVertices_.reserve(screenVertices_.size() + int(tris.size())); + for (size_t i = 0; i < tris.size(); ++i) { + p2t::Triangle *t = tris.at(i); + for (int j = 0; j < 3; ++j) { + p2t::Point *p = t->GetPoint(j); + screenVertices_ << QPointF(p->x, p->y); + } + } + delete cdt; + } + curPts.clear(); + curPts.reserve(ppi.elementCount() - i); + curPts.push_back(new p2t::Point(e.x, e.y)); + } else if (e.isLineTo()) { + curPts.push_back(new p2t::Point(e.x, e.y)); + } else { + qWarning("Unhandled element type in circle painterpath"); + } + } + + if (curPts.size() > 0) { + qDeleteAll(curPts.begin(), curPts.end()); + curPts.clear(); + } + + if (borderPts.size() > 0) { + qDeleteAll(borderPts.begin(), borderPts.end()); + borderPts.clear(); + } + + screenBounds_ = ppiBorder.boundingRect(); + +} + +static const qreal qgeocoordinate_EARTH_MEAN_RADIUS = 6371.0072; + +inline static qreal qgeocoordinate_degToRad(qreal deg) +{ + return deg * M_PI / 180; +} +inline static qreal qgeocoordinate_radToDeg(qreal rad) +{ + return rad * 180 / M_PI; +} + +static bool crossEarthPole(const QGeoCoordinate ¢er, qreal distance) +{ + qreal poleLat = 90; + QGeoCoordinate northPole = QGeoCoordinate(poleLat, center.longitude()); + QGeoCoordinate southPole = QGeoCoordinate(-poleLat, center.longitude()); + // approximate using great circle distance + qreal distanceToNorthPole = center.distanceTo(northPole); + qreal distanceToSouthPole = center.distanceTo(southPole); + if (distanceToNorthPole < distance || distanceToSouthPole < distance) + return true; + return false; +} + +static void calculatePeripheralPoints(QList &path, + const QGeoCoordinate ¢er, + qreal distance, + int steps, + QGeoCoordinate &leftBound ) +{ + // Calculate points based on great-circle distance + // Calculation is the same as GeoCoordinate's atDistanceAndAzimuth function + // but tweaked here for computing multiple points + + // pre-calculations + steps = qMax(steps, 3); + qreal centerLon = center.longitude(); + qreal minLon = centerLon; + qreal latRad = qgeocoordinate_degToRad(center.latitude()); + qreal lonRad = qgeocoordinate_degToRad(centerLon); + qreal cosLatRad = std::cos(latRad); + qreal sinLatRad = std::sin(latRad); + qreal ratio = (distance / (qgeocoordinate_EARTH_MEAN_RADIUS * 1000.0)); + qreal cosRatio = std::cos(ratio); + qreal sinRatio = std::sin(ratio); + qreal sinLatRad_x_cosRatio = sinLatRad * cosRatio; + qreal cosLatRad_x_sinRatio = cosLatRad * sinRatio; + int idx = 0; + for (int i = 0; i < steps; ++i) { + qreal azimuthRad = 2 * M_PI * i / steps; + qreal resultLatRad = std::asin(sinLatRad_x_cosRatio + + cosLatRad_x_sinRatio * std::cos(azimuthRad)); + qreal resultLonRad = lonRad + std::atan2(std::sin(azimuthRad) * cosLatRad_x_sinRatio, + cosRatio - sinLatRad * std::sin(resultLatRad)); + qreal lat2 = qgeocoordinate_radToDeg(resultLatRad); + qreal lon2 = qgeocoordinate_radToDeg(resultLonRad); + if (lon2 < -180.0) { + lon2 += 360.0; + } else if (lon2 > 180.0) { + lon2 -= 360.0; + } + path << QGeoCoordinate(lat2, lon2, center.altitude()); + // Consider only points in the left half of the circle for the left bound. + if (azimuthRad > M_PI) { + if (lon2 > centerLon) // if point and center are on different hemispheres + lon2 -= 360; + if (lon2 < minLon) { + minLon = lon2; + idx = i; + } + } + } + leftBound = path.at(idx); +} + +QDeclarativeCircleMapItem::QDeclarativeCircleMapItem(QQuickItem *parent) +: QDeclarativeGeoMapItemBase(parent), color_(Qt::transparent), radius_(0), dirtyMaterial_(true), + updatingGeometry_(false) +{ + setFlag(ItemHasContents, true); + QObject::connect(&border_, SIGNAL(colorChanged(QColor)), + this, SLOT(markSourceDirtyAndUpdate())); + QObject::connect(&border_, SIGNAL(widthChanged(qreal)), + this, SLOT(markSourceDirtyAndUpdate())); + + // assume that circles are not self-intersecting + // to speed up processing + // FIXME: unfortunately they self-intersect at the poles due to current drawing method + // so the line is commented out until fixed + //geometry_.setAssumeSimple(true); + +} + +QDeclarativeCircleMapItem::~QDeclarativeCircleMapItem() +{ +} + +/*! + \qmlpropertygroup Location::MapCircle::border + \qmlproperty int MapCircle::border.width + \qmlproperty color MapCircle::border.color + + This property is part of the border group property. + The border property holds the width and color used to draw the border of the circle. + The width is in pixels and is independent of the zoom level of the map. + + The default values correspond to a black border with a width of 1 pixel. + For no line, use a width of 0 or a transparent color. +*/ +QDeclarativeMapLineProperties *QDeclarativeCircleMapItem::border() +{ + return &border_; +} + +void QDeclarativeCircleMapItem::markSourceDirtyAndUpdate() +{ + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + polishAndUpdate(); +} + +void QDeclarativeCircleMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) +{ + QDeclarativeGeoMapItemBase::setMap(quickMap,map); + if (map) + markSourceDirtyAndUpdate(); +} + +/*! + \qmlproperty coordinate MapCircle::center + + This property holds the central point about which the circle is defined. + + \sa radius +*/ +void QDeclarativeCircleMapItem::setCenter(const QGeoCoordinate ¢er) +{ + if (center_ == center) + return; + + center_ = center; + markSourceDirtyAndUpdate(); + emit centerChanged(center_); +} + +QGeoCoordinate QDeclarativeCircleMapItem::center() +{ + return center_; +} + +/*! + \qmlproperty color MapCircle::color + + This property holds the fill color of the circle when drawn. For no fill, + use a transparent color. +*/ +void QDeclarativeCircleMapItem::setColor(const QColor &color) +{ + if (color_ == color) + return; + color_ = color; + dirtyMaterial_ = true; + update(); + emit colorChanged(color_); +} + +QColor QDeclarativeCircleMapItem::color() const +{ + return color_; +} + +/*! + \qmlproperty real MapCircle::radius + + This property holds the radius of the circle, in meters on the ground. + + \sa center +*/ +void QDeclarativeCircleMapItem::setRadius(qreal radius) +{ + if (radius_ == radius) + return; + + radius_ = radius; + markSourceDirtyAndUpdate(); + emit radiusChanged(radius); +} + +qreal QDeclarativeCircleMapItem::radius() const +{ + return radius_; +} + +/*! + \qmlproperty real MapCircle::opacity + + This property holds the opacity of the item. Opacity is specified as a + number between 0 (fully transparent) and 1 (fully opaque). The default is 1. + + An item with 0 opacity will still receive mouse events. To stop mouse events, set the + visible property of the item to false. +*/ + +/*! + \internal +*/ +QSGNode *QDeclarativeCircleMapItem::updateMapItemPaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) +{ + Q_UNUSED(data); + + MapPolygonNode *node = static_cast(oldNode); + + if (!node) + node = new MapPolygonNode(); + + //TODO: update only material + if (geometry_.isScreenDirty() || borderGeometry_.isScreenDirty() || dirtyMaterial_) { + node->update(color_, border_.color(), &geometry_, &borderGeometry_); + geometry_.setPreserveGeometry(false); + borderGeometry_.setPreserveGeometry(false); + geometry_.markClean(); + borderGeometry_.markClean(); + dirtyMaterial_ = false; + } + return node; +} + +/*! + \internal +*/ +void QDeclarativeCircleMapItem::updatePolish() +{ + if (!map() || !center().isValid() || qIsNaN(radius_) || radius_ <= 0.0) + return; + + QScopedValueRollback rollback(updatingGeometry_); + updatingGeometry_ = true; + + if (geometry_.isSourceDirty()) { + circlePath_.clear(); + calculatePeripheralPoints(circlePath_, center_, radius_, CircleSamples, geoLeftBound_); + } + + int pathCount = circlePath_.size(); + bool preserve = preserveCircleGeometry(circlePath_, center_, radius_); + geometry_.setPreserveGeometry(preserve, geoLeftBound_); + geometry_.updateSourcePoints(*map(), circlePath_); + if (crossEarthPole(center_, radius_) && circlePath_.size() == pathCount) + geometry_.updateScreenPointsInvert(*map()); // invert fill area for really huge circles + else geometry_.updateScreenPoints(*map()); + + if (border_.color() != Qt::transparent && border_.width() > 0) { + QList closedPath = circlePath_; + closedPath << closedPath.first(); + borderGeometry_.setPreserveGeometry(preserve, geoLeftBound_); + borderGeometry_.updateSourcePoints(*map(), closedPath, geoLeftBound_); + borderGeometry_.updateScreenPoints(*map(), border_.width()); + + QList geoms; + geoms << &geometry_ << &borderGeometry_; + QRectF combined = QGeoMapItemGeometry::translateToCommonOrigin(geoms); + + setWidth(combined.width()); + setHeight(combined.height()); + } else { + borderGeometry_.clear(); + setWidth(geometry_.screenBoundingBox().width()); + setHeight(geometry_.screenBoundingBox().height()); + } + + setPositionOnMap(circlePath_.at(0), geometry_.firstPointOffset()); +} + +/*! + \internal +*/ +void QDeclarativeCircleMapItem::afterViewportChanged(const QGeoMapViewportChangeEvent &event) +{ + if (event.mapSize.width() <= 0 || event.mapSize.height() <= 0) + return; + + // if the scene is tilted, we must regenerate our geometry every frame + if (map()->cameraCapabilities().supportsTilting() + && (event.cameraData.tilt() > 0.1 + || event.cameraData.tilt() < -0.1)) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + + // if the scene is rolled, we must regen too + if (map()->cameraCapabilities().supportsRolling() + && (event.cameraData.roll() > 0.1 + || event.cameraData.roll() < -0.1)) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + + // otherwise, only regen on rotate, resize and zoom + if (event.bearingChanged || event.mapSizeChanged || event.zoomLevelChanged) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + + if (event.centerChanged && crossEarthPole(center_, radius_)) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + + geometry_.markScreenDirty(); + borderGeometry_.markScreenDirty(); + polishAndUpdate(); +} + +/*! + \internal +*/ +bool QDeclarativeCircleMapItem::contains(const QPointF &point) const +{ + return (geometry_.contains(point) || borderGeometry_.contains(point)); +} + +/*! + \internal +*/ +void QDeclarativeCircleMapItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + if (updatingGeometry_ || newGeometry == oldGeometry) { + QDeclarativeGeoMapItemBase::geometryChanged(newGeometry, oldGeometry); + return; + } + + QDoubleVector2D newPoint = QDoubleVector2D(x(),y()) + QDoubleVector2D(width(), height()) / 2; + QGeoCoordinate newCoordinate = map()->itemPositionToCoordinate(newPoint, false); + if (newCoordinate.isValid()) + setCenter(newCoordinate); + + // Not calling QDeclarativeGeoMapItemBase::geometryChanged() as it will be called from a nested + // call to this function. +} + +bool QDeclarativeCircleMapItem::preserveCircleGeometry (QList &path, + const QGeoCoordinate ¢er, qreal distance) +{ + // if circle crosses north/south pole, then don't preserve circular shape, + if ( crossEarthPole(center, distance)) { + updateCirclePathForRendering(path, center, distance); + return false; + } + return true; + +} + + +// A workaround for circle path to be drawn correctly using a polygon geometry +void QDeclarativeCircleMapItem::updateCirclePathForRendering(QList &path, + const QGeoCoordinate ¢er, + qreal distance) +{ + qreal poleLat = 90; + qreal distanceToNorthPole = center.distanceTo(QGeoCoordinate(poleLat, 0)); + qreal distanceToSouthPole = center.distanceTo(QGeoCoordinate(-poleLat, 0)); + bool crossNorthPole = distanceToNorthPole < distance; + bool crossSouthPole = distanceToSouthPole < distance; + if (!crossNorthPole && !crossSouthPole) + return; + QList wrapPathIndex; + // calculate actual width of map on screen in pixels + QDoubleVector2D midPoint = map()->coordinateToItemPosition(map()->cameraData().center(), false); + QDoubleVector2D midPointPlusOne(midPoint.x() + 1.0, midPoint.y()); + QGeoCoordinate coord1 = map()->itemPositionToCoordinate(midPointPlusOne, false); + qreal geoDistance = coord1.longitude() - map()->cameraData().center().longitude(); + if ( geoDistance < 0 ) + geoDistance += 360; + qreal mapWidth = 360.0 / geoDistance; + mapWidth = qMin(static_cast(mapWidth), map()->width()); + QDoubleVector2D prev = map()->coordinateToItemPosition(path.at(0), false); + // find the points in path where wrapping occurs + for (int i = 1; i <= path.count(); ++i) { + int index = i % path.count(); + QDoubleVector2D point = map()->coordinateToItemPosition(path.at(index), false); + if ( (qAbs(point.x() - prev.x())) >= mapWidth/2.0 ) { + wrapPathIndex << index; + if (wrapPathIndex.size() == 2 || !(crossNorthPole && crossSouthPole)) + break; + } + prev = point; + } + // insert two additional coords at top/bottom map corners of the map for shape + // to be drawn correctly + if (wrapPathIndex.size() > 0) { + qreal newPoleLat = 90; + QGeoCoordinate wrapCoord = path.at(wrapPathIndex[0]); + if (wrapPathIndex.size() == 2) { + QGeoCoordinate wrapCoord2 = path.at(wrapPathIndex[1]); + if (wrapCoord2.latitude() > wrapCoord.latitude()) + newPoleLat = -90; + } else if (center.latitude() < 0) { + newPoleLat = -90; + } + for (int i = 0; i < wrapPathIndex.size(); ++i) { + int index = wrapPathIndex[i] == 0 ? 0 : wrapPathIndex[i] + i*2; + int prevIndex = (index - 1) < 0 ? (path.count() - 1): index - 1; + QGeoCoordinate coord0 = path.at(prevIndex); + QGeoCoordinate coord1 = path.at(index); + coord0.setLatitude(newPoleLat); + coord1.setLatitude(newPoleLat); + path.insert(index ,coord1); + path.insert(index, coord0); + newPoleLat = -newPoleLat; + } + } +} + +////////////////////////////////////////////////////////////////////// + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativecirclemapitem_p.h b/src/imports/location/qdeclarativecirclemapitem_p.h new file mode 100644 index 0000000..c91d160 --- /dev/null +++ b/src/imports/location/qdeclarativecirclemapitem_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVECIRCLEMAPITEM_H +#define QDECLARATIVECIRCLEMAPITEM_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeomapitembase_p.h" +#include "qdeclarativepolylinemapitem_p.h" +#include "qdeclarativepolygonmapitem_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMapCircleGeometry : public QGeoMapPolygonGeometry +{ +public: + QGeoMapCircleGeometry(); + + void updateScreenPointsInvert(const QGeoMap &map); +}; + +class QDeclarativeCircleMapItem : public QDeclarativeGeoMapItemBase +{ + Q_OBJECT + Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter NOTIFY centerChanged) + Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + Q_PROPERTY(QDeclarativeMapLineProperties *border READ border CONSTANT) + +public: + explicit QDeclarativeCircleMapItem(QQuickItem *parent = 0); + ~QDeclarativeCircleMapItem(); + + virtual void setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) Q_DECL_OVERRIDE; + virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; + + QGeoCoordinate center(); + void setCenter(const QGeoCoordinate ¢er); + + qreal radius() const; + void setRadius(qreal radius); + + QColor color() const; + void setColor(const QColor &color); + + QDeclarativeMapLineProperties *border(); + + bool contains(const QPointF &point) const Q_DECL_OVERRIDE; + +Q_SIGNALS: + void centerChanged(const QGeoCoordinate ¢er); + void radiusChanged(qreal radius); + void colorChanged(const QColor &color); + +protected: + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void updatePolish() Q_DECL_OVERRIDE; + +protected Q_SLOTS: + void markSourceDirtyAndUpdate(); + virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; + +private: + bool preserveCircleGeometry(QList &path, const QGeoCoordinate ¢er, + qreal distance); + void updateCirclePathForRendering(QList &path, const QGeoCoordinate ¢er, + qreal distance); + +private: + QGeoCoordinate center_; + QDeclarativeMapLineProperties border_; + QColor color_; + qreal radius_; + QGeoCoordinate geoLeftBound_; + QList circlePath_; + bool dirtyMaterial_; + QGeoMapCircleGeometry geometry_; + QGeoMapPolylineGeometry borderGeometry_; + bool updatingGeometry_; +}; + +////////////////////////////////////////////////////////////////////// + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeCircleMapItem) + +#endif /* QDECLARATIVECIRCLEMAPITEM_H */ diff --git a/src/imports/location/qdeclarativegeocodemodel.cpp b/src/imports/location/qdeclarativegeocodemodel.cpp new file mode 100644 index 0000000..d8ff4e8 --- /dev/null +++ b/src/imports/location/qdeclarativegeocodemodel.cpp @@ -0,0 +1,727 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeocodemodel_p.h" +#include "error_messages.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype GeocodeModel + \instantiates QDeclarativeGeocodeModel + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-geocoding + \since Qt Location 5.5 + + \brief The GeocodeModel type provides support for searching operations + related to geographic information. + + The GeocodeModel type is used as part of a model/view grouping to + match addresses or search strings with geographic locations. How the + geographic locations generated are used or displayed is decided by any + Views attached to the GeocodeModel (for example a \l MapItemView or \l{ListView}). + + Like \l Map and \l RouteModel, all the data for a GeocodeModel to work + comes from a services plugin. This is contained in the \l{plugin} property, + and this must be set before the GeocodeModel can do any useful work. + + Once the plugin is set, the \l{query} property can be used to specify the + address or search string to match. If \l{autoUpdate} is enabled, the Model + will update its output automatically. Otherwise, the \l{update} method may + be used. By default, autoUpdate is disabled. + + The data stored and returned in the GeocodeModel consists of \l{Location} + objects, as a list with the role name "locationData". See the documentation + for \l{Location} for further details on its structure and contents. + + \section2 Example Usage + + The following snippet is two-part, showing firstly the declaration of + objects, and secondly a short piece of procedural code using it. We set + the geocodeModel's \l{autoUpdate} property to false, and call \l{update} once + the query is set up. In this case, as we use a string value in \l{query}, + only one update would occur, even with autoUpdate enabled. However, if we + provided an \l{Address} object we may inadvertently trigger multiple + requests whilst setting its properties. + + \code + Plugin { + id: aPlugin + } + + GeocodeModel { + id: geocodeModel + plugin: aPlugin + autoUpdate: false + } + \endcode + + \code + { + geocodeModel.query = "53 Brandl St, Eight Mile Plains, Australia" + geocodeModel.update() + } + \endcode +*/ + +/*! + \qmlsignal QtLocation::GeocodeModel::locationsChanged() + + This signal is emitted when locations in the model have changed. + + \sa count +*/ + + +QDeclarativeGeocodeModel::QDeclarativeGeocodeModel(QObject *parent) +: QAbstractListModel(parent), autoUpdate_(false), complete_(false), reply_(0), plugin_(0), + status_(QDeclarativeGeocodeModel::Null), error_(QDeclarativeGeocodeModel::NoError), + address_(0), limit_(-1), offset_(0) +{ +} + +QDeclarativeGeocodeModel::~QDeclarativeGeocodeModel() +{ + qDeleteAll(declarativeLocations_); + declarativeLocations_.clear(); + delete reply_; +} + +/*! + \internal + From QQmlParserStatus +*/ +void QDeclarativeGeocodeModel::componentComplete() +{ + complete_ = true; + if (autoUpdate_) + update(); +} + +/*! + \qmlmethod void QtLocation::GeocodeModel::update() + + Instructs the GeocodeModel to update its data. This is most useful + when \l autoUpdate is disabled, to force a refresh when the query + has been changed. +*/ +void QDeclarativeGeocodeModel::update() +{ + if (!complete_) + return; + + if (!plugin_) { + setError(EngineNotSetError, tr("Cannot geocode, plugin not set.")); + return; + } + + QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); + if (!serviceProvider) + return; + + QGeoCodingManager *geocodingManager = serviceProvider->geocodingManager(); + if (!geocodingManager) { + setError(EngineNotSetError, tr("Cannot geocode, geocode manager not set.")); + return; + } + if (!coordinate_.isValid() && (!address_ || address_->address().isEmpty()) && + (searchString_.isEmpty())) { + setError(ParseError, tr("Cannot geocode, valid query not set.")); + return; + } + abortRequest(); // abort possible previous requests + setError(NoError, QString()); + + if (coordinate_.isValid()) { + setStatus(QDeclarativeGeocodeModel::Loading); + reply_ = geocodingManager->reverseGeocode(coordinate_, boundingArea_); + if (reply_->isFinished()) { + if (reply_->error() == QGeoCodeReply::NoError) { + geocodeFinished(reply_); + } else { + geocodeError(reply_, reply_->error(), reply_->errorString()); + } + } + } else if (address_) { + setStatus(QDeclarativeGeocodeModel::Loading); + reply_ = geocodingManager->geocode(address_->address(), boundingArea_); + if (reply_->isFinished()) { + if (reply_->error() == QGeoCodeReply::NoError) { + geocodeFinished(reply_); + } else { + geocodeError(reply_, reply_->error(), reply_->errorString()); + } + } + } else if (!searchString_.isEmpty()) { + setStatus(QDeclarativeGeocodeModel::Loading); + reply_ = geocodingManager->geocode(searchString_, limit_, offset_, boundingArea_); + if (reply_->isFinished()) { + if (reply_->error() == QGeoCodeReply::NoError) { + geocodeFinished(reply_); + } else { + geocodeError(reply_, reply_->error(), reply_->errorString()); + } + } + } +} + +/*! + \internal +*/ +void QDeclarativeGeocodeModel::abortRequest() +{ + if (reply_) { + reply_->abort(); + reply_->deleteLater(); + reply_ = 0; + } +} + +/*! + \internal +*/ +void QDeclarativeGeocodeModel::queryContentChanged() +{ + if (autoUpdate_) + update(); +} + +/*! + \internal + From QAbstractListModel +*/ +int QDeclarativeGeocodeModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return declarativeLocations_.count(); +} + +/*! + \internal +*/ +QVariant QDeclarativeGeocodeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + if (index.row() >= declarativeLocations_.count()) + return QVariant(); + if (role == QDeclarativeGeocodeModel::LocationRole) { + QObject *locationObject = declarativeLocations_.at(index.row()); + Q_ASSERT(locationObject); + return QVariant::fromValue(locationObject); + } + return QVariant(); +} + +QHash QDeclarativeGeocodeModel::roleNames() const +{ + QHash roleNames = QAbstractItemModel::roleNames(); + roleNames.insert(LocationRole, "locationData"); + return roleNames; +} + +/*! + \internal +*/ +void QDeclarativeGeocodeModel::setPlugin(QDeclarativeGeoServiceProvider *plugin) +{ + if (plugin_ == plugin) + return; + + reset(); // reset the model + plugin_ = plugin; + if (complete_) + emit pluginChanged(); + + if (!plugin) + return; + + if (plugin_->isAttached()) { + pluginReady(); + } else { + connect(plugin_, SIGNAL(attached()), + this, SLOT(pluginReady())); + } +} + +/*! + \internal +*/ +void QDeclarativeGeocodeModel::pluginReady() +{ + QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); + QGeoCodingManager *geocodingManager = serviceProvider->geocodingManager(); + + if (serviceProvider->error() != QGeoServiceProvider::NoError) { + QDeclarativeGeocodeModel::GeocodeError newError = UnknownError; + switch (serviceProvider->error()) { + case QGeoServiceProvider::NotSupportedError: + newError = EngineNotSetError; break; + case QGeoServiceProvider::UnknownParameterError: + newError = UnknownParameterError; break; + case QGeoServiceProvider::MissingRequiredParameterError: + newError = MissingRequiredParameterError; break; + case QGeoServiceProvider::ConnectionError: + newError = CommunicationError; break; + default: + break; + } + + setError(newError, serviceProvider->errorString()); + return; + } + + if (!geocodingManager) { + setError(EngineNotSetError,tr("Plugin does not support (reverse) geocoding.")); + return; + } + + connect(geocodingManager, SIGNAL(finished(QGeoCodeReply*)), + this, SLOT(geocodeFinished(QGeoCodeReply*))); + connect(geocodingManager, SIGNAL(error(QGeoCodeReply*,QGeoCodeReply::Error,QString)), + this, SLOT(geocodeError(QGeoCodeReply*,QGeoCodeReply::Error,QString))); +} + +/*! + \qmlproperty Plugin QtLocation::GeocodeModel::plugin + + This property holds the plugin that provides the actual geocoding service. + Note that all plugins do not necessarily provide geocoding (could for example provide + only routing or maps). + + \sa Plugin +*/ + +QDeclarativeGeoServiceProvider *QDeclarativeGeocodeModel::plugin() const +{ + return plugin_; +} + +void QDeclarativeGeocodeModel::setBounds(const QVariant &boundingArea) +{ + QGeoShape s; + + if (boundingArea.userType() == qMetaTypeId()) + s = boundingArea.value(); + else if (boundingArea.userType() == qMetaTypeId()) + s = boundingArea.value(); + else if (boundingArea.userType() == qMetaTypeId()) + s = boundingArea.value(); + + + if (boundingArea_ == s) + return; + + boundingArea_ = s; + emit boundsChanged(); +} + +/*! + \qmlproperty geoshape QtLocation::GeocodeModel::bounds + + This property holds the bounding area used to limit the results to those + within the area. This is particularly useful if query is only partially filled out, + as the service will attempt to (reverse) geocode all matches for the specified data. + + Accepted types are \l {georectangle} and + \l {geocircle}. +*/ +QVariant QDeclarativeGeocodeModel::bounds() const +{ + if (boundingArea_.type() == QGeoShape::RectangleType) + return QVariant::fromValue(QGeoRectangle(boundingArea_)); + else if (boundingArea_.type() == QGeoShape::CircleType) + return QVariant::fromValue(QGeoCircle(boundingArea_)); + else + return QVariant::fromValue(boundingArea_); +} + +void QDeclarativeGeocodeModel::geocodeFinished(QGeoCodeReply *reply) +{ + if (reply != reply_ || reply->error() != QGeoCodeReply::NoError) + return; + int oldCount = declarativeLocations_.count(); + setLocations(reply->locations()); + setError(NoError, QString()); + setStatus(QDeclarativeGeocodeModel::Ready); + reply->deleteLater(); + reply_ = 0; + emit locationsChanged(); + if (oldCount != declarativeLocations_.count()) + emit countChanged(); +} + +/*! + \internal +*/ +void QDeclarativeGeocodeModel::geocodeError(QGeoCodeReply *reply, + QGeoCodeReply::Error error, + const QString &errorString) +{ + if (reply != reply_) + return; + Q_UNUSED(error); + int oldCount = declarativeLocations_.count(); + if (oldCount > 0) { + // Reset the model + setLocations(reply->locations()); + emit locationsChanged(); + emit countChanged(); + } + setError(static_cast(error), errorString); + setStatus(QDeclarativeGeocodeModel::Error); + reply->deleteLater(); + reply_ = 0; +} + +/*! + \qmlproperty enumeration QtLocation::GeocodeModel::status + + This read-only property holds the current status of the model. + + \list + \li GeocodeModel.Null - No geocode requests have been issued or \l reset has been called. + \li GeocodeModel.Ready - Geocode request(s) have finished successfully. + \li GeocodeModel.Loading - Geocode request has been issued but not yet finished + \li GeocodeModel.Error - Geocoding error has occurred, details are in \l error and \l errorString + \endlist +*/ + +QDeclarativeGeocodeModel::Status QDeclarativeGeocodeModel::status() const +{ + return status_; +} + +void QDeclarativeGeocodeModel::setStatus(QDeclarativeGeocodeModel::Status status) +{ + if (status_ == status) + return; + status_ = status; + emit statusChanged(); +} + +/*! + \qmlproperty enumeration QtLocation::GeocodeModel::error + + This read-only property holds the latest error value of the geocoding request. + + \list + \li GeocodeModel.NoError - No error has occurred. + \li GeocodeModel.CombinationError - An error occurred while results where being combined from multiple sources. + \li GeocodeModel.CommunicationError - An error occurred while communicating with the service provider. + \li GeocodeModel.EngineNotSetError - The model's plugin property was not set or there is no geocoding manager associated with the plugin. + \li GeocodeModel.MissingRequiredParameterError - A required parameter was not specified. + \li GeocodeModel.ParseError - The response from the service provider was in an unrecognizable format. + \li GeocodeModel.UnknownError - An error occurred which does not fit into any of the other categories. + \li GeocodeModel.UnknownParameterError - The plugin did not recognize one of the parameters it was given. + \li GeocodeModel.UnsupportedOptionError - The requested operation is not supported by the geocoding provider. + This may happen when the loaded engine does not support a particular geocoding request + such as reverse geocoding. + \endlist +*/ + +QDeclarativeGeocodeModel::GeocodeError QDeclarativeGeocodeModel::error() const +{ + return error_; +} + +void QDeclarativeGeocodeModel::setError(GeocodeError error, const QString &errorString) +{ + if (error_ == error && errorString_ == errorString) + return; + error_ = error; + errorString_ = errorString; + emit errorChanged(); +} + +/*! + \qmlproperty string QtLocation::GeocodeModel::errorString + + This read-only property holds the textual presentation of the latest geocoding error. + If no error has occurred or the model has been reset, an empty string is returned. + + An empty string may also be returned if an error occurred which has no associated + textual representation. +*/ + +QString QDeclarativeGeocodeModel::errorString() const +{ + return errorString_; +} + +/*! + \internal +*/ +void QDeclarativeGeocodeModel::setLocations(const QList &locations) +{ + beginResetModel(); + qDeleteAll(declarativeLocations_); + declarativeLocations_.clear(); + for (int i = 0; i < locations.count(); ++i) { + QDeclarativeGeoLocation *location = new QDeclarativeGeoLocation(locations.at(i), this); + declarativeLocations_.append(location); + } + endResetModel(); +} + +/*! + \qmlproperty int QtLocation::GeocodeModel::count + + This property holds how many locations the model currently has. + Amongst other uses, you can use this value when accessing locations + via the GeocodeModel::get -method. +*/ + +int QDeclarativeGeocodeModel::count() const +{ + return declarativeLocations_.count(); +} + +/*! + \qmlmethod Location QtLocation::GeocodeModel::get(int) + + Returns the Location at given index. Use \l count property to check the + amount of locations available. The locations are indexed from zero, so the accessible range + is 0...(count - 1). + + If you access out of bounds, a zero (null object) is returned and a warning is issued. +*/ + +QDeclarativeGeoLocation *QDeclarativeGeocodeModel::get(int index) +{ + if (index < 0 || index >= declarativeLocations_.count()) { + qmlInfo(this) << QStringLiteral("Index '%1' out of range").arg(index); + return 0; + } + return declarativeLocations_.at(index); +} + +/*! + \qmlproperty int QtLocation::GeocodeModel::limit + + This property holds the maximum number of results. The limit and \l offset values are only + applicable with free string geocoding (that is they are not considered when using addresses + or coordinates in the search query). + + If limit is -1 the entire result set will be returned, otherwise at most limit results will be + returned. The limit and \l offset results can be used together to implement paging. +*/ + +int QDeclarativeGeocodeModel::limit() const +{ + return limit_; +} + +void QDeclarativeGeocodeModel::setLimit(int limit) +{ + if (limit == limit_) + return; + limit_ = limit; + if (autoUpdate_) { + update(); + } + emit limitChanged(); +} + +/*! + \qmlproperty int QtLocation::GeocodeModel::offset + + This property tells not to return the first 'offset' number of the results. The \l limit and + offset values are only applicable with free string geocoding (that is they are not considered + when using addresses or coordinates in the search query). + + The \l limit and offset results can be used together to implement paging. +*/ + +int QDeclarativeGeocodeModel::offset() const +{ + return offset_; +} + +void QDeclarativeGeocodeModel::setOffset(int offset) +{ + if (offset == offset_) + return; + offset_ = offset; + if (autoUpdate_) { + update(); + } + emit offsetChanged(); +} + +/*! + \qmlmethod void QtLocation::GeocodeModel::reset() + + Resets the model. All location data is cleared, any outstanding requests + are aborted and possible errors are cleared. Model status will be set + to GeocodeModel.Null +*/ + +void QDeclarativeGeocodeModel::reset() +{ + beginResetModel(); + if (!declarativeLocations_.isEmpty()) { + setLocations(QList()); + emit countChanged(); + } + endResetModel(); + + abortRequest(); + setError(NoError, QString()); + setStatus(QDeclarativeGeocodeModel::Null); +} + +/*! + \qmlmethod void QtLocation::GeocodeModel::cancel() + + Cancels any outstanding requests and clears errors. Model status will be set to either + GeocodeModel.Null or GeocodeModel.Ready. +*/ +void QDeclarativeGeocodeModel::cancel() +{ + abortRequest(); + setError(NoError, QString()); + setStatus(declarativeLocations_.isEmpty() ? Null : Ready); +} + +/*! + \qmlproperty QVariant QtLocation::GeocodeModel::query + + This property holds the data of the geocoding request. + The property accepts three types of queries which determine both the data and + the type of action to be performed: + + \list + \li Address - Geocoding (address to coordinate) + \li \l {coordinate} - Reverse geocoding (coordinate to address) + \li string - Geocoding (address to coordinate) + \endlist +*/ + +QVariant QDeclarativeGeocodeModel::query() const +{ + return queryVariant_; +} + +void QDeclarativeGeocodeModel::setQuery(const QVariant &query) +{ + if (query == queryVariant_) + return; + + if (query.userType() == qMetaTypeId()) { + if (address_) { + address_->disconnect(this); + address_ = 0; + } + searchString_.clear(); + + coordinate_ = query.value(); + } else if (query.type() == QVariant::String) { + searchString_ = query.toString(); + if (address_) { + address_->disconnect(this); + address_ = 0; + } + coordinate_ = QGeoCoordinate(); + } else if (QObject *object = query.value()) { + if (QDeclarativeGeoAddress *address = qobject_cast(object)) { + if (address_) + address_->disconnect(this); + coordinate_ = QGeoCoordinate(); + searchString_.clear(); + + address_ = address; + connect(address_, SIGNAL(countryChanged()), this, SLOT(queryContentChanged())); + connect(address_, SIGNAL(countryCodeChanged()), this, SLOT(queryContentChanged())); + connect(address_, SIGNAL(stateChanged()), this, SLOT(queryContentChanged())); + connect(address_, SIGNAL(countyChanged()), this, SLOT(queryContentChanged())); + connect(address_, SIGNAL(cityChanged()), this, SLOT(queryContentChanged())); + connect(address_, SIGNAL(districtChanged()), this, SLOT(queryContentChanged())); + connect(address_, SIGNAL(streetChanged()), this, SLOT(queryContentChanged())); + connect(address_, SIGNAL(postalCodeChanged()), this, SLOT(queryContentChanged())); + } else { + qmlInfo(this) << QStringLiteral("Unsupported query type for geocode model ") + << QStringLiteral("(coordinate, string and Address supported)."); + return; + } + } else { + qmlInfo(this) << QStringLiteral("Unsupported query type for geocode model ") + << QStringLiteral("(coordinate, string and Address supported)."); + return; + } + + queryVariant_ = query; + emit queryChanged(); + if (autoUpdate_) + update(); +} + +/*! + \qmlproperty bool QtLocation::GeocodeModel::autoUpdate + + This property controls whether the Model automatically updates in response + to changes in its attached query. The default value of this property + is false. + + If setting this value to 'true' and using an Address or + \l {coordinate} as the query, note that any change at all in the + object's properties will trigger a new request to be sent. If you are adjusting many + properties of the object whilst autoUpdate is enabled, this can generate large numbers of + useless (and later discarded) requests. +*/ + +bool QDeclarativeGeocodeModel::autoUpdate() const +{ + return autoUpdate_; +} + +void QDeclarativeGeocodeModel::setAutoUpdate(bool update) +{ + if (autoUpdate_ == update) + return; + autoUpdate_ = update; + emit autoUpdateChanged(); +} + +#include "moc_qdeclarativegeocodemodel_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeocodemodel_p.h b/src/imports/location/qdeclarativegeocodemodel_p.h new file mode 100644 index 0000000..2fbe993 --- /dev/null +++ b/src/imports/location/qdeclarativegeocodemodel_p.h @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOCODEMODEL_H +#define QDECLARATIVEGEOCODEMODEL_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeoserviceprovider_p.h" + +#include +#include +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoServiceProvider; +class QGeoCodingManager; +class QDeclarativeGeoLocation; + +class QDeclarativeGeocodeModel : public QAbstractListModel, public QQmlParserStatus +{ + Q_OBJECT + Q_ENUMS(Status) + Q_ENUMS(GeocodeError) + + Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) + Q_PROPERTY(bool autoUpdate READ autoUpdate WRITE setAutoUpdate NOTIFY autoUpdateChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) + Q_PROPERTY(int count READ count NOTIFY countChanged) + Q_PROPERTY(int limit READ limit WRITE setLimit NOTIFY limitChanged) + Q_PROPERTY(int offset READ offset WRITE setOffset NOTIFY offsetChanged) + Q_PROPERTY(QVariant query READ query WRITE setQuery NOTIFY queryChanged) + Q_PROPERTY(QVariant bounds READ bounds WRITE setBounds NOTIFY boundsChanged) + Q_PROPERTY(GeocodeError error READ error NOTIFY errorChanged) + Q_INTERFACES(QQmlParserStatus) + +public: + enum Status { + Null, + Ready, + Loading, + Error + }; + + enum GeocodeError { + NoError = QGeoCodeReply::NoError, + EngineNotSetError = QGeoCodeReply::EngineNotSetError, //TODO Qt6 consider merge with NotSupportedError + CommunicationError = QGeoCodeReply::CommunicationError, //TODO Qt6 merge with Map's ConnectionError + ParseError = QGeoCodeReply::ParseError, + UnsupportedOptionError = QGeoCodeReply::UnsupportedOptionError, //TODO Qt6 consider rename UnsupportedOperationError + CombinationError = QGeoCodeReply::CombinationError, + UnknownError = QGeoCodeReply::UnknownError, + //we leave gap for future QGeoCodeReply errors + + //QGeoServiceProvider related errors start here + UnknownParameterError = 100, + MissingRequiredParameterError + }; + + enum Roles { + LocationRole = Qt::UserRole + 1 + }; + + explicit QDeclarativeGeocodeModel(QObject *parent = 0); + virtual ~QDeclarativeGeocodeModel(); + + // From QQmlParserStatus + virtual void classBegin() {} + virtual void componentComplete(); + + // From QAbstractListModel + virtual int rowCount(const QModelIndex &parent) const; + virtual QVariant data(const QModelIndex &index, int role) const; + virtual QHash roleNames() const; + + void setPlugin(QDeclarativeGeoServiceProvider *plugin); + QDeclarativeGeoServiceProvider *plugin() const; + + void setBounds(const QVariant &boundingArea); + QVariant bounds() const; + + Status status() const; + QString errorString() const; + GeocodeError error() const; + + bool autoUpdate() const; + void setAutoUpdate(bool update); + + int count() const; + Q_INVOKABLE QDeclarativeGeoLocation *get(int index); + + int limit() const; + void setLimit(int limit); + int offset() const; + void setOffset(int offset); + + QVariant query() const; + void setQuery(const QVariant &query); + Q_INVOKABLE void reset(); + Q_INVOKABLE void cancel(); + +Q_SIGNALS: + void countChanged(); + void pluginChanged(); + void statusChanged(); + void errorChanged(); //emitted also for errorString notification + void locationsChanged(); + void autoUpdateChanged(); + void boundsChanged(); + void queryChanged(); + void limitChanged(); + void offsetChanged(); + +public Q_SLOTS: + void update(); + +protected Q_SLOTS: + void queryContentChanged(); + void geocodeFinished(QGeoCodeReply *reply); + void geocodeError(QGeoCodeReply *reply, + QGeoCodeReply::Error error, + const QString &errorString); + void pluginReady(); + +protected: + QGeoCodingManager *searchManager(); + void setStatus(Status status); + void setError(GeocodeError error, const QString &errorString); + bool autoUpdate_; + bool complete_; + +private: + void setLocations(const QList &locations); + void abortRequest(); + QGeoCodeReply *reply_; + + QDeclarativeGeoServiceProvider *plugin_; + QGeoShape boundingArea_; + + QList declarativeLocations_; + + Status status_; + QString errorString_; + GeocodeError error_; + QVariant queryVariant_; + QGeoCoordinate coordinate_; + QDeclarativeGeoAddress *address_; + QString searchString_; + + int limit_; + int offset_; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/qdeclarativegeomaneuver.cpp b/src/imports/location/qdeclarativegeomaneuver.cpp new file mode 100644 index 0000000..72c3886 --- /dev/null +++ b/src/imports/location/qdeclarativegeomaneuver.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeomaneuver_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype RouteManeuver + \instantiates QDeclarativeGeoManeuver + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-routing + \since Qt Location 5.5 + + \brief The RouteManeuver type represents the information relevant to the + point at which two RouteSegments meet. + + RouteSegment instances can be thought of as edges on a routing + graph, with RouteManeuver instances as optional labels attached to the + vertices of the graph. + + The most interesting information held in a RouteManeuver instance is + normally the textual navigation to provide and the position at which to + provide it, accessible by \l instructionText and \l position respectively. + + \section1 Example + + The following QML snippet demonstrates how to print information about a + route maneuver: + + \snippet declarative/routing.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/routing.qml RouteManeuver +*/ + +QDeclarativeGeoManeuver::QDeclarativeGeoManeuver(QObject *parent) + : QObject(parent) +{ +} + +QDeclarativeGeoManeuver::QDeclarativeGeoManeuver(const QGeoManeuver &maneuver, QObject *parent) + : QObject(parent), + maneuver_(maneuver) +{ +} + +QDeclarativeGeoManeuver::~QDeclarativeGeoManeuver() {} + +/*! + \qmlproperty bool RouteManeuver::valid + + This read-only property holds whether this maneuver is valid or not. + + Invalid maneuvers are used when there is no information + that needs to be attached to the endpoint of a QGeoRouteSegment instance. +*/ + +bool QDeclarativeGeoManeuver::valid() const +{ + return maneuver_.isValid(); +} + +/*! + \qmlproperty coordinate RouteManeuver::position + + This read-only property holds where the \l instructionText should be displayed. + +*/ + +QGeoCoordinate QDeclarativeGeoManeuver::position() const +{ + return maneuver_.position(); +} + +/*! + \qmlproperty string RouteManeuver::instructionText + + This read-only property holds textual navigation instruction. +*/ + +QString QDeclarativeGeoManeuver::instructionText() const +{ + return maneuver_.instructionText(); +} + +/*! + \qmlproperty enumeration RouteManeuver::direction + + Describes the change in direction associated with the instruction text + that is associated with a RouteManeuver. + + \list + \li RouteManeuver.NoDirection - There is no direction associated with the instruction text + \li RouteManeuver.DirectionForward - The instruction indicates that the direction of travel does not need to change + \li RouteManeuver.DirectionBearRight - The instruction indicates that the direction of travel should bear to the right + \li RouteManeuver.DirectionLightRight - The instruction indicates that a light turn to the right is required + \li RouteManeuver.DirectionRight - The instruction indicates that a turn to the right is required + \li RouteManeuver.DirectionHardRight - The instruction indicates that a hard turn to the right is required + \li RouteManeuver.DirectionUTurnRight - The instruction indicates that a u-turn to the right is required + \li RouteManeuver.DirectionUTurnLeft - The instruction indicates that a u-turn to the left is required + \li RouteManeuver.DirectionHardLeft - The instruction indicates that a hard turn to the left is required + \li RouteManeuver.DirectionLeft - The instruction indicates that a turn to the left is required + \li RouteManeuver.DirectionLightLeft - The instruction indicates that a light turn to the left is required + \li RouteManeuver.DirectionBearLeft - The instruction indicates that the direction of travel should bear to the left + \endlist +*/ + +QDeclarativeGeoManeuver::Direction QDeclarativeGeoManeuver::direction() const +{ + return QDeclarativeGeoManeuver::Direction(maneuver_.direction()); +} + +/*! + \qmlproperty int RouteManeuver::timeToNextInstruction + + This read-only property holds the estimated time it will take to travel + from the point at which the associated instruction was issued and the + point that the next instruction should be issued, in seconds. +*/ + +int QDeclarativeGeoManeuver::timeToNextInstruction() const +{ + return maneuver_.timeToNextInstruction(); +} + +/*! + \qmlproperty real RouteManeuver::distanceToNextInstruction + + This read-only property holds the distance, in meters, between the point at which + the associated instruction was issued and the point that the next instruction should + be issued. +*/ + +qreal QDeclarativeGeoManeuver::distanceToNextInstruction() const +{ + return maneuver_.distanceToNextInstruction(); +} + +/*! + \qmlproperty coordinate RouteManeuver::waypoint + + This property holds the waypoint associated with this maneuver. + All maneuvers do not have a waypoint associated with them, this + can be checked with \l waypointValid. + +*/ + +QGeoCoordinate QDeclarativeGeoManeuver::waypoint() const +{ + return maneuver_.waypoint(); +} + +/*! + \qmlproperty bool RouteManeuver::waypointValid + + This read-only property holds whether this \l waypoint, associated with this + maneuver, is valid or not. +*/ + +bool QDeclarativeGeoManeuver::waypointValid() const +{ + return maneuver_.waypoint().isValid(); +} + +#include "moc_qdeclarativegeomaneuver_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomaneuver_p.h b/src/imports/location/qdeclarativegeomaneuver_p.h new file mode 100644 index 0000000..b189d83 --- /dev/null +++ b/src/imports/location/qdeclarativegeomaneuver_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOMANEUVER_H +#define QDECLARATIVEGEOMANEUVER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoManeuver : public QObject +{ + Q_OBJECT + Q_ENUMS(Direction) + + Q_PROPERTY(bool valid READ valid CONSTANT) + Q_PROPERTY(QGeoCoordinate position READ position CONSTANT) + Q_PROPERTY(QString instructionText READ instructionText CONSTANT) + Q_PROPERTY(Direction direction READ direction CONSTANT) + Q_PROPERTY(int timeToNextInstruction READ timeToNextInstruction CONSTANT) + Q_PROPERTY(qreal distanceToNextInstruction READ distanceToNextInstruction CONSTANT) + Q_PROPERTY(QGeoCoordinate waypoint READ waypoint CONSTANT) + Q_PROPERTY(bool waypointValid READ waypointValid CONSTANT) + +public: + enum Direction { + NoDirection = QGeoManeuver::NoDirection, + DirectionForward = QGeoManeuver::DirectionForward, + DirectionBearRight = QGeoManeuver::DirectionBearRight, + DirectionLightRight = QGeoManeuver::DirectionLightRight, + DirectionRight = QGeoManeuver::DirectionRight, + DirectionHardRight = QGeoManeuver::DirectionHardRight, + DirectionUTurnRight = QGeoManeuver::DirectionUTurnRight, + DirectionUTurnLeft = QGeoManeuver::DirectionUTurnLeft, + DirectionHardLeft = QGeoManeuver::DirectionHardLeft, + DirectionLeft = QGeoManeuver::DirectionLeft, + DirectionLightLeft = QGeoManeuver::DirectionLightLeft, + DirectionBearLeft = QGeoManeuver::DirectionBearLeft + }; + + explicit QDeclarativeGeoManeuver(QObject *parent = 0); + QDeclarativeGeoManeuver(const QGeoManeuver &maneuver, QObject *parent = 0); + ~QDeclarativeGeoManeuver(); + + bool valid() const; + bool waypointValid() const; + + QGeoCoordinate position() const; + QString instructionText() const; + Direction direction() const; + int timeToNextInstruction() const; + qreal distanceToNextInstruction() const; + QGeoCoordinate waypoint() const; + +private: + QGeoManeuver maneuver_; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp new file mode 100644 index 0000000..fd98b2c --- /dev/null +++ b/src/imports/location/qdeclarativegeomap.cpp @@ -0,0 +1,1551 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeomap_p.h" +#include "qdeclarativegeomapquickitem_p.h" +#include "qdeclarativegeomapcopyrightsnotice_p.h" +#include "qdeclarativegeoserviceprovider_p.h" +#include "qdeclarativegeomaptype_p.h" +#include "qgeomappingmanager_p.h" +#include "qgeocameracapabilities_p.h" +#include "qgeomap_p.h" +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Map + \instantiates QDeclarativeGeoMap + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.0 + + \brief The Map type displays a map. + + The Map type is used to display a map or image of the Earth, with + the capability to also display interactive objects tied to the map's + surface. + + There are a variety of different ways to visualize the Earth's surface + in a 2-dimensional manner, but all of them involve some kind of projection: + a mathematical relationship between the 3D coordinates (latitude, longitude + and altitude) and 2D coordinates (X and Y in pixels) on the screen. + + Different sources of map data can use different projections, and from the + point of view of the Map type, we treat these as one replaceable unit: + the Map plugin. A Map plugin consists of a data source, as well as all other + details needed to display its data on-screen. + + The current Map plugin in use is contained in the \l plugin property of + the Map item. In order to display any image in a Map item, you will need + to set this property. See the \l Plugin type for a description of how + to retrieve an appropriate plugin for use. + + The geographic region displayed in the Map item is referred to as its + viewport, and this is defined by the properties \l center, and + \l zoomLevel. The \l center property contains a \l {coordinate} + specifying the center of the viewport, while \l zoomLevel controls the scale of the + map. See each of these properties for further details about their values. + + When the map is displayed, each possible geographic coordinate that is + visible will map to some pixel X and Y coordinate on the screen. To perform + conversions between these two, Map provides the \l toCoordinate and + \l fromCoordinate functions, which are of general utility. + + \section2 Map Objects + + Map related objects can be declared within the body of a Map object in Qt Quick and will + automatically appear on the Map. To add objects programmatically, first be + sure they are created with the Map as their parent (for example in an argument to + Component::createObject), and then call the \l addMapItem method on the Map. + A corresponding \l removeMapItem method also exists to do the opposite and + remove an object from the Map. + + Moving Map objects around, resizing them or changing their shape normally + does not involve any special interaction with Map itself -- changing these + details about a map object will automatically update the display. + + \section2 Interaction + + The Map type includes support for pinch and flick gestures to control + zooming and panning. These are enabled by default, and available at any + time by using the \l gesture object. The actual GestureArea is constructed + specially at startup and cannot be replaced or destroyed. Its properties + can be altered, however, to control its behavior. + + \section2 Performance + + Maps are rendered using OpenGL (ES) and the Qt Scene Graph stack, and as + a result perform quite well where GL accelerated hardware is available. + + For "online" Map plugins, network bandwidth and latency can be major + contributors to the user's perception of performance. Extensive caching is + performed to mitigate this, but such mitigation is not always perfect. For + "offline" plugins, the time spent retrieving the stored geographic data + and rendering the basic map features can often play a dominant role. Some + offline plugins may use hardware acceleration themselves to (partially) + avert this. + + In general, large and complex Map items such as polygons and polylines with + large numbers of vertices can have an adverse effect on UI performance. + Further, more detailed notes on this are in the documentation for each + map item type. + + \section2 Example Usage + + The following snippet shows a simple Map and the necessary Plugin type + to use it. The map is centered over Oslo, Norway, with zoom level 10. + + \quotefromfile minimal_map/main.qml + \skipto import + \printuntil } + \printline } + \skipto Map + \printuntil } + \printline } + + \image minimal_map.png +*/ + +/*! + \qmlsignal QtLocation::Map::copyrightLinkActivated(string link) + + This signal is emitted when the user clicks on a \a link in the copyright notice. The + application should open the link in a browser or display its contents to the user. +*/ + +static const qreal EARTH_MEAN_RADIUS = 6371007.2; + +QDeclarativeGeoMap::QDeclarativeGeoMap(QQuickItem *parent) + : QQuickItem(parent), + m_plugin(0), + m_serviceProvider(0), + m_mappingManager(0), + m_activeMapType(0), + m_gestureArea(new QQuickGeoMapGestureArea(this)), + m_map(0), + m_error(QGeoServiceProvider::NoError), + m_color(QColor::fromRgbF(0.9, 0.9, 0.9)), + m_componentCompleted(false), + m_pendingFitViewport(false), + m_copyrightsVisible(true), + m_maximumViewportLatitude(0.0), + m_initialized(false), + m_validRegion(false) +{ + setAcceptHoverEvents(false); + setAcceptedMouseButtons(Qt::LeftButton); + setFlags(QQuickItem::ItemHasContents | QQuickItem::ItemClipsChildrenToShape); + setFiltersChildMouseEvents(true); + + connect(this, SIGNAL(childrenChanged()), this, SLOT(onMapChildrenChanged()), Qt::QueuedConnection); + + m_activeMapType = new QDeclarativeGeoMapType(QGeoMapType(QGeoMapType::NoMap, + tr("No Map"), + tr("No Map"), false, false, 0), this); + m_cameraData.setCenter(QGeoCoordinate(51.5073,-0.1277)); //London city center + m_cameraData.setZoomLevel(8.0); +} + +QDeclarativeGeoMap::~QDeclarativeGeoMap() +{ + if (!m_mapViews.isEmpty()) + qDeleteAll(m_mapViews); + // remove any map items associations + for (int i = 0; i < m_mapItems.count(); ++i) { + if (m_mapItems.at(i)) + m_mapItems.at(i).data()->setMap(0,0); + } + m_mapItems.clear(); + + delete m_copyrights.data(); + m_copyrights.clear(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::onMapChildrenChanged() +{ + if (!m_componentCompleted || !m_map) + return; + + int maxChildZ = 0; + QObjectList kids = children(); + bool foundCopyrights = false; + + for (int i = 0; i < kids.size(); ++i) { + QDeclarativeGeoMapCopyrightNotice *copyrights = qobject_cast(kids.at(i)); + if (copyrights) { + foundCopyrights = true; + } else { + QDeclarativeGeoMapItemBase *mapItem = qobject_cast(kids.at(i)); + if (mapItem) { + if (mapItem->z() > maxChildZ) + maxChildZ = mapItem->z(); + } + } + } + + QDeclarativeGeoMapCopyrightNotice *copyrights = m_copyrights.data(); + // if copyrights object not found within the map's children + if (!foundCopyrights) { + // if copyrights object was deleted! + if (!copyrights) { + // create a new one and set its parent, re-assign it to the weak pointer, then connect the copyrights-change signal + m_copyrights = new QDeclarativeGeoMapCopyrightNotice(this); + copyrights = m_copyrights.data(); + connect(m_map, SIGNAL(copyrightsChanged(QImage)), + copyrights, SLOT(copyrightsChanged(QImage))); + connect(m_map, SIGNAL(copyrightsChanged(QString)), + copyrights, SLOT(copyrightsChanged(QString))); + connect(copyrights, SIGNAL(linkActivated(QString)), + this, SIGNAL(copyrightLinkActivated(QString))); + + // set visibility of copyright notice + copyrights->setCopyrightsVisible(m_copyrightsVisible); + + } else { + // just re-set its parent. + copyrights->setParent(this); + } + } + + // put the copyrights notice object at the highest z order + copyrights->setCopyrightsZ(maxChildZ + 1); +} + +static QDeclarativeGeoMapType *findMapType(const QList &types, const QGeoMapType &type) +{ + for (int i = 0; i < types.size(); ++i) + if (types[i]->mapType() == type) + return types[i]; + return Q_NULLPTR; +} + +void QDeclarativeGeoMap::onSupportedMapTypesChanged() +{ + QList supportedMapTypes; + QList types = m_mappingManager->supportedMapTypes(); + for (int i = 0; i < types.size(); ++i) { + // types that are present and get removed will be deleted at QObject destruction + QDeclarativeGeoMapType *type = findMapType(m_supportedMapTypes, types[i]); + if (!type) + type = new QDeclarativeGeoMapType(types[i], this); + supportedMapTypes.append(type); + } + m_supportedMapTypes.swap(supportedMapTypes); + if (m_supportedMapTypes.isEmpty()) { + m_map->setActiveMapType(QGeoMapType()); // no supported map types: setting an invalid one + } else { + bool hasMapType = false; + foreach (QDeclarativeGeoMapType *declarativeType, m_supportedMapTypes) { + if (declarativeType->mapType() == m_map->activeMapType()) + hasMapType = true; + } + if (!hasMapType) { + QDeclarativeGeoMapType *type = m_supportedMapTypes.at(0); + m_activeMapType = type; + m_map->setActiveMapType(type->mapType()); + } + } + + emit supportedMapTypesChanged(); +} + +void QDeclarativeGeoMap::setError(QGeoServiceProvider::Error error, const QString &errorString) +{ + if (m_error == error && m_errorString == errorString) + return; + m_error = error; + m_errorString = errorString; + emit errorChanged(); +} + +void QDeclarativeGeoMap::initialize() +{ + // try to keep center change signal in the end + bool centerHasChanged = false; + + setMinimumZoomLevel(m_map->minimumZoomForMapSize(width(), height())); + + // set latitude bundary check + m_maximumViewportLatitude = m_map->maximumLatitudeForZoom(m_cameraData.zoomLevel()); + QGeoCoordinate center = m_cameraData.center(); + center.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude)); + + if (center != m_cameraData.center()) { + centerHasChanged = true; + m_cameraData.setCenter(center); + } + + m_map->setCameraData(m_cameraData); + + m_initialized = true; + + if (centerHasChanged) + emit centerChanged(m_cameraData.center()); +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::pluginReady() +{ + m_serviceProvider = m_plugin->sharedGeoServiceProvider(); + m_mappingManager = m_serviceProvider->mappingManager(); + + if (m_serviceProvider->error() != QGeoServiceProvider::NoError) { + setError(m_serviceProvider->error(), m_serviceProvider->errorString()); + return; + } + + if (!m_mappingManager) { + //TODO Should really be EngineNotSetError (see QML GeoCodeModel) + setError(QGeoServiceProvider::NotSupportedError, tr("Plugin does not support mapping.")); + return; + } + + if (!m_mappingManager->isInitialized()) + connect(m_mappingManager, SIGNAL(initialized()), this, SLOT(mappingManagerInitialized())); + else + mappingManagerInitialized(); + + // make sure this is only called once + disconnect(this, SLOT(pluginReady())); +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::componentComplete() +{ + m_componentCompleted = true; + populateMap(); + QQuickItem::componentComplete(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::mousePressEvent(QMouseEvent *event) +{ + if (isInteractive()) + m_gestureArea->handleMousePressEvent(event); + else + QQuickItem::mousePressEvent(event); +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::mouseMoveEvent(QMouseEvent *event) +{ + if (isInteractive()) + m_gestureArea->handleMouseMoveEvent(event); + else + QQuickItem::mouseMoveEvent(event); +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::mouseReleaseEvent(QMouseEvent *event) +{ + if (isInteractive()) { + m_gestureArea->handleMouseReleaseEvent(event); + ungrabMouse(); + } else { + QQuickItem::mouseReleaseEvent(event); + } +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::mouseUngrabEvent() +{ + if (isInteractive()) + m_gestureArea->handleMouseUngrabEvent(); + else + QQuickItem::mouseUngrabEvent(); +} + +void QDeclarativeGeoMap::touchUngrabEvent() +{ + if (isInteractive()) + m_gestureArea->handleTouchUngrabEvent(); + else + QQuickItem::touchUngrabEvent(); +} + +/*! + \qmlproperty MapGestureArea QtLocation::Map::gesture + + Contains the MapGestureArea created with the Map. This covers pan, flick and pinch gestures. + Use \c{gesture.enabled: true} to enable basic gestures, or see \l{MapGestureArea} for + further details. +*/ + +QQuickGeoMapGestureArea *QDeclarativeGeoMap::gesture() +{ + return m_gestureArea; +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::populateMap() +{ + QObjectList kids = children(); + QList quickKids = childItems(); + for (int i=0; i < quickKids.count(); ++i) + kids.append(quickKids.at(i)); + + for (int i = 0; i < kids.size(); ++i) { + // dispatch items appropriately + QDeclarativeGeoMapItemView *mapView = qobject_cast(kids.at(i)); + if (mapView) { + m_mapViews.append(mapView); + setupMapView(mapView); + continue; + } + QDeclarativeGeoMapItemBase *mapItem = qobject_cast(kids.at(i)); + if (mapItem) { + addMapItem(mapItem); + } + } +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::setupMapView(QDeclarativeGeoMapItemView *view) +{ + Q_UNUSED(view) + view->setMap(this); + view->repopulate(); +} + +/*! + * \internal + */ +QSGNode *QDeclarativeGeoMap::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + if (!m_map) { + delete oldNode; + return 0; + } + + QSGSimpleRectNode *root = static_cast(oldNode); + if (!root) + root = new QSGSimpleRectNode(boundingRect(), m_color); + else { + root->setRect(boundingRect()); + root->setColor(m_color); + } + + QSGNode *content = root->childCount() ? root->firstChild() : 0; + content = m_map->updateSceneGraph(content, window()); + if (content && root->childCount() == 0) + root->appendChildNode(content); + + return root; +} + +/*! + \qmlproperty Plugin QtLocation::Map::plugin + + This property holds the plugin which provides the mapping functionality. + + This is a write-once property. Once the map has a plugin associated with + it, any attempted modifications of the plugin will be ignored. +*/ + +void QDeclarativeGeoMap::setPlugin(QDeclarativeGeoServiceProvider *plugin) +{ + if (m_plugin) { + qmlInfo(this) << QStringLiteral("Plugin is a write-once property, and cannot be set again."); + return; + } + m_plugin = plugin; + emit pluginChanged(m_plugin); + + if (m_plugin->isAttached()) { + pluginReady(); + } else { + connect(m_plugin, SIGNAL(attached()), + this, SLOT(pluginReady())); + } +} + +/*! + \internal + this function will only be ever called once +*/ +void QDeclarativeGeoMap::mappingManagerInitialized() +{ + m_map = m_mappingManager->createMap(this); + + if (!m_map) + return; + + m_gestureArea->setMap(m_map); + + QList types = m_mappingManager->supportedMapTypes(); + for (int i = 0; i < types.size(); ++i) { + QDeclarativeGeoMapType *type = new QDeclarativeGeoMapType(types[i], this); + m_supportedMapTypes.append(type); + } + + if (!m_supportedMapTypes.isEmpty()) { + QDeclarativeGeoMapType *type = m_supportedMapTypes.at(0); + m_activeMapType = type; + m_map->setActiveMapType(type->mapType()); + } else { + m_map->setActiveMapType(m_activeMapType->mapType()); + } + + //The zoom level limits are only restricted by the plugins values, if the user has set a more + //strict zoom level limit before initialization nothing is done here. + //minimum zoom level might be changed to limit gray bundaries + + if (m_gestureArea->maximumZoomLevel() < 0 + || m_mappingManager->cameraCapabilities().maximumZoomLevel() < m_gestureArea->maximumZoomLevel()) + setMaximumZoomLevel(m_mappingManager->cameraCapabilities().maximumZoomLevel()); + + if (m_mappingManager->cameraCapabilities().minimumZoomLevel() > m_gestureArea->minimumZoomLevel()) + setMinimumZoomLevel(m_mappingManager->cameraCapabilities().minimumZoomLevel()); + + + // Map tiles are built in this call. m_map->minimumZoom() becomes operational + // after this has been called at least once, after creation. + + if (!m_initialized && width() > 0 && height() > 0) { + m_map->setSize(QSize(width(), height())); + initialize(); + } + + m_copyrights = new QDeclarativeGeoMapCopyrightNotice(this); + connect(m_map, SIGNAL(copyrightsChanged(QImage)), + m_copyrights.data(), SLOT(copyrightsChanged(QImage))); + connect(m_map, SIGNAL(copyrightsChanged(QString)), + m_copyrights.data(), SLOT(copyrightsChanged(QString))); + connect(m_copyrights.data(), SIGNAL(linkActivated(QString)), + this, SIGNAL(copyrightLinkActivated(QString))); + connect(m_map, &QGeoMap::sgNodeChanged, this, &QQuickItem::update); + + // set visibility of copyright notice + m_copyrights->setCopyrightsVisible(m_copyrightsVisible); + + // This prefetches a buffer around the map + m_map->prefetchData(); + + connect(m_mappingManager, SIGNAL(supportedMapTypesChanged()), this, SLOT(onSupportedMapTypesChanged())); + emit minimumZoomLevelChanged(); + emit maximumZoomLevelChanged(); + emit supportedMapTypesChanged(); + emit activeMapTypeChanged(); + + // Any map items that were added before the plugin was ready + // need to have setMap called again + foreach (const QPointer &item, m_mapItems) { + if (item) + item.data()->setMap(this, m_map); + } +} + +/*! + \internal +*/ +QDeclarativeGeoServiceProvider *QDeclarativeGeoMap::plugin() const +{ + return m_plugin; +} + +/*! + \internal + Sets the gesture areas minimum zoom level. If the camera capabilities + has been set this method honors the boundaries set by it. + The minimum zoom level will also have a lower bound dependent on the size + of the canvas, effectively preventing to display out of bounds areas. +*/ +void QDeclarativeGeoMap::setMinimumZoomLevel(qreal minimumZoomLevel) +{ + + if (minimumZoomLevel >= 0) { + qreal oldMinimumZoomLevel = this->minimumZoomLevel(); + + if (m_map) { + minimumZoomLevel = qBound(qreal(m_map->cameraCapabilities().minimumZoomLevel()), minimumZoomLevel, maximumZoomLevel()); + double minimumViewportZoomLevel = m_map->minimumZoomForMapSize(width(),height()); + if (minimumZoomLevel < minimumViewportZoomLevel) + minimumZoomLevel = minimumViewportZoomLevel; + } + + m_gestureArea->setMinimumZoomLevel(minimumZoomLevel); + + if (zoomLevel() < minimumZoomLevel) + setZoomLevel(minimumZoomLevel); + + if (oldMinimumZoomLevel != minimumZoomLevel) + emit minimumZoomLevelChanged(); + } +} + +/*! + \qmlproperty real QtLocation::Map::minimumZoomLevel + + This property holds the minimum valid zoom level for the map. + + The minimum zoom level defined by the \l plugin used is a lower bound for + this property. However, the returned value is also canvas-size-dependent, and + can be higher than the user-specified value, or than the minimum zoom level + defined by the plugin used, to prevent the map from being smaller than the + viewport in either dimension. + + If a plugin supporting mapping is not set, -1.0 is returned. +*/ + +qreal QDeclarativeGeoMap::minimumZoomLevel() const +{ + if (m_gestureArea->minimumZoomLevel() != -1) + return m_gestureArea->minimumZoomLevel(); + else if (m_map) + return m_map->cameraCapabilities().minimumZoomLevel(); + else + return -1.0; +} + +/*! + \internal + Sets the gesture areas maximum zoom level. If the camera capabilities + has been set this method honors the boundaries set by it. +*/ +void QDeclarativeGeoMap::setMaximumZoomLevel(qreal maximumZoomLevel) +{ + if (maximumZoomLevel >= 0) { + qreal oldMaximumZoomLevel = this->maximumZoomLevel(); + + if (m_map) + maximumZoomLevel = qBound(minimumZoomLevel(), maximumZoomLevel, qreal(m_map->cameraCapabilities().maximumZoomLevel())); + + m_gestureArea->setMaximumZoomLevel(maximumZoomLevel); + + if (zoomLevel() > maximumZoomLevel) + setZoomLevel(maximumZoomLevel); + + if (oldMaximumZoomLevel != maximumZoomLevel) + emit maximumZoomLevelChanged(); + } +} + +/*! + \qmlproperty real QtLocation::Map::maximumZoomLevel + + This property holds the maximum valid zoom level for the map. + + The maximum zoom level is defined by the \l plugin used. + If a plugin supporting mapping is not set, -1.0 is returned. +*/ + +qreal QDeclarativeGeoMap::maximumZoomLevel() const +{ + if (m_gestureArea->maximumZoomLevel() != -1) + return m_gestureArea->maximumZoomLevel(); + else if (m_map) + return m_map->cameraCapabilities().maximumZoomLevel(); + else + return -1.0; +} + +/*! + \qmlproperty real QtLocation::Map::zoomLevel + + This property holds the zoom level for the map. + + Larger values for the zoom level provide more detail. Zoom levels + are always non-negative. The default value is 8.0. +*/ +void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel) +{ + if (m_cameraData.zoomLevel() == zoomLevel || zoomLevel < 0) + return; + + //small optiomatization to avoid double setCameraData + bool centerHasChanged = false; + + if (m_initialized) { + m_cameraData.setZoomLevel(qBound(minimumZoomLevel(), zoomLevel, maximumZoomLevel())); + m_maximumViewportLatitude = m_map->maximumLatitudeForZoom(m_cameraData.zoomLevel()); + QGeoCoordinate coord = m_cameraData.center(); + coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude)); + if (coord != m_cameraData.center()) { + centerHasChanged = true; + m_cameraData.setCenter(coord); + } + m_map->setCameraData(m_cameraData); + } else { + m_cameraData.setZoomLevel(zoomLevel); + } + + m_validRegion = false; + + if (centerHasChanged) + emit centerChanged(m_cameraData.center()); + emit zoomLevelChanged(m_cameraData.zoomLevel()); +} + +qreal QDeclarativeGeoMap::zoomLevel() const +{ + return m_cameraData.zoomLevel(); +} + +/*! + \qmlproperty coordinate QtLocation::Map::center + + This property holds the coordinate which occupies the center of the + mapping viewport. Invalid center coordinates are ignored. + + The default value is an arbitrary valid coordinate. +*/ +void QDeclarativeGeoMap::setCenter(const QGeoCoordinate ¢er) +{ + if (center == m_cameraData.center()) + return; + + if (!center.isValid()) + return; + + if (m_initialized) { + QGeoCoordinate coord(center); + coord.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude)); + m_cameraData.setCenter(coord); + m_map->setCameraData(m_cameraData); + } else { + m_cameraData.setCenter(center); + } + + m_validRegion = false; + emit centerChanged(m_cameraData.center()); +} + +QGeoCoordinate QDeclarativeGeoMap::center() const +{ + return m_cameraData.center(); +} + + +/*! + \qmlproperty geoshape QtLocation::Map::visibleRegion + + This property holds the region which occupies the viewport of + the map. The camera is positioned in the center of the shape, and + at the largest integral zoom level possible which allows the + whole shape to be visible on the screen. This implies that + reading this property back shortly after having been set the + returned area is equal or larger than the set area. + + Setting this property implicitly changes the \l center and + \l zoomLevel of the map. Any previously set value to those + properties will be overridden. + + This property does not provide any change notifications. + + \since 5.6 +*/ +void QDeclarativeGeoMap::setVisibleRegion(const QGeoShape &shape) +{ + if (shape == m_region && m_validRegion) + return; + + m_region = shape; + if (!shape.isValid()) { + // shape invalidated -> nothing to fit anymore + m_pendingFitViewport = false; + return; + } + + if (!width() || !height()) { + m_pendingFitViewport = true; + return; + } + + fitViewportToGeoShape(); +} + +QGeoShape QDeclarativeGeoMap::visibleRegion() const +{ + if (!m_map || !width() || !height()) + return m_region; + + QGeoCoordinate tl = m_map->itemPositionToCoordinate(QDoubleVector2D(0, 0)); + QGeoCoordinate br = m_map->itemPositionToCoordinate(QDoubleVector2D(width(), height())); + + return QGeoRectangle(tl, br); +} + +/*! + \qmlproperty bool QtLocation::Map::copyrightsVisible + + This property holds the visibility of the copyrights notice. The notice is usually + displayed in the bottom left corner. By default, this property is set to \c true. + + \note Many map providers require the notice to be visible as part of the terms and conditions. + Please consult the relevant provider documentation before turning this notice off. + + \since 5.7 +*/ +void QDeclarativeGeoMap::setCopyrightsVisible(bool visible) +{ + if (m_copyrightsVisible == visible) + return; + + if (!m_copyrights.isNull()) + m_copyrights->setCopyrightsVisible(visible); + + m_copyrightsVisible = visible; + emit copyrightsVisibleChanged(visible); +} + +bool QDeclarativeGeoMap::copyrightsVisible() const +{ + return m_copyrightsVisible; +} + + + +/*! + \qmlproperty color QtLocation::Map::color + + This property holds the background color of the map element. + + \since 5.6 +*/ +void QDeclarativeGeoMap::setColor(const QColor &color) +{ + if (color != m_color) { + m_color = color; + update(); + emit colorChanged(m_color); + } +} + +QColor QDeclarativeGeoMap::color() const +{ + return m_color; +} + +void QDeclarativeGeoMap::fitViewportToGeoShape() +{ + int margins = 10; + if (!m_map || width() <= margins || height() <= margins) + return; + + QGeoCoordinate topLeft; + QGeoCoordinate bottomRight; + + switch (m_region.type()) { + case QGeoShape::RectangleType: + { + QGeoRectangle rect = m_region; + topLeft = rect.topLeft(); + bottomRight = rect.bottomRight(); + break; + } + case QGeoShape::CircleType: + { + const double pi = M_PI; + QGeoCircle circle = m_region; + QGeoCoordinate centerCoordinate = circle.center(); + + // calculate geo bounding box of the circle + // circle tangential points with meridians and the north pole create + // spherical triangle, we use spherical law of sines + // sin(lon_delta_in_rad)/sin(r_in_rad) = + // sin(alpha_in_rad)/sin(pi/2 - lat_in_rad), where: + // * lon_delta_in_rad - delta of longitudes of circle center + // and tangential points + // * r_in_rad - angular radius of the circle + // * lat_in_rad - latitude of circle center + // * alpha_in_rad - angle between meridian and radius to the circle => + // this is tangential point => sin(alpha) = 1 + // * lat_delta_in_rad - delta of latitudes of circle center and + // latitude of points where great circle (going through circle + // center) crosses circle and the pole + + double r_in_rad = circle.radius() / EARTH_MEAN_RADIUS; // angular r + double lat_delta_in_deg = r_in_rad * 180 / pi; + double lon_delta_in_deg = std::asin(std::sin(r_in_rad) / + std::cos(centerCoordinate.latitude() * pi / 180)) * 180 / pi; + + topLeft.setLatitude(centerCoordinate.latitude() + lat_delta_in_deg); + topLeft.setLongitude(centerCoordinate.longitude() - lon_delta_in_deg); + bottomRight.setLatitude(centerCoordinate.latitude() + - lat_delta_in_deg); + bottomRight.setLongitude(centerCoordinate.longitude() + + lon_delta_in_deg); + + // adjust if circle reaches poles => cross all meridians and + // fit into Mercator projection bounds + if (topLeft.latitude() > 90 || bottomRight.latitude() < -90) { + topLeft.setLatitude(qMin(topLeft.latitude(), 85.05113)); + topLeft.setLongitude(-180.0); + bottomRight.setLatitude(qMax(bottomRight.latitude(), + -85.05113)); + bottomRight.setLongitude(180.0); + } + break; + } + case QGeoShape::UnknownType: + //Fallthrough to default + default: + return; + } + + // adjust zoom, use reference world to keep things simple + // otherwise we would need to do the error prone longitudes + // wrapping + QDoubleVector2D topLeftPoint = + m_map->referenceCoordinateToItemPosition(topLeft); + QDoubleVector2D bottomRightPoint = + m_map->referenceCoordinateToItemPosition(bottomRight); + + double bboxWidth = bottomRightPoint.x() - topLeftPoint.x(); + double bboxHeight = bottomRightPoint.y() - topLeftPoint.y(); + + // find center of the bounding box + QGeoCoordinate centerCoordinate = + m_map->referenceItemPositionToCoordinate( + (topLeftPoint + bottomRightPoint)/2); + + // position camera to the center of bounding box + setCenter(centerCoordinate); + + // if the shape is empty we just change center position, not zoom + if (bboxHeight == 0 && bboxWidth == 0) + return; + + double zoomRatio = qMax(bboxWidth / (width() - margins), + bboxHeight / (height() - margins)); + // fixme: use log2 with c++11 + zoomRatio = std::log(zoomRatio) / std::log(2.0); + double newZoom = qMax(minimumZoomLevel(), zoomLevel() + - zoomRatio); + setZoomLevel(newZoom); + m_validRegion = true; +} + + +/*! + \qmlproperty list QtLocation::Map::supportedMapTypes + + This read-only property holds the set of \l{MapType}{map types} supported by this map. + + \sa activeMapType +*/ +QQmlListProperty QDeclarativeGeoMap::supportedMapTypes() +{ + return QQmlListProperty(this, m_supportedMapTypes); +} + +/*! + \qmlmethod coordinate QtLocation::Map::toCoordinate(QPointF position, bool clipToViewPort) + + Returns the coordinate which corresponds to the \a position relative to the map item. + + If \a cliptoViewPort is \c true, or not supplied then returns an invalid coordinate if + \a position is not within the current viewport. +*/ +QGeoCoordinate QDeclarativeGeoMap::toCoordinate(const QPointF &position, bool clipToViewPort) const +{ + if (m_map) + return m_map->itemPositionToCoordinate(QDoubleVector2D(position), clipToViewPort); + else + return QGeoCoordinate(); +} + +/*! + \qmlmethod point QtLocation::Map::fromCoordinate(coordinate coordinate, bool clipToViewPort) + + Returns the position relative to the map item which corresponds to the \a coordinate. + + If \a cliptoViewPort is \c true, or not supplied then returns an invalid QPointF if + \a coordinate is not within the current viewport. +*/ +QPointF QDeclarativeGeoMap::fromCoordinate(const QGeoCoordinate &coordinate, bool clipToViewPort) const +{ + if (m_map) + return m_map->coordinateToItemPosition(coordinate, clipToViewPort).toPointF(); + else + return QPointF(qQNaN(), qQNaN()); +} + +/*! + \qmlmethod void QtLocation::Map::pan(int dx, int dy) + + Starts panning the map by \a dx pixels along the x-axis and + by \a dy pixels along the y-axis. + + Positive values for \a dx move the map right, negative values left. + Positive values for \a dy move the map down, negative values up. + + During panning the \l center, and \l zoomLevel may change. +*/ +void QDeclarativeGeoMap::pan(int dx, int dy) +{ + if (!m_map) + return; + if (dx == 0 && dy == 0) + return; + QGeoCoordinate coord = m_map->itemPositionToCoordinate( + QDoubleVector2D(m_map->width() / 2 + dx, + m_map->height() / 2 + dy)); + setCenter(coord); +} + + +/*! + \qmlmethod void QtLocation::Map::prefetchData() + + Optional hint that allows the map to prefetch during this idle period +*/ +void QDeclarativeGeoMap::prefetchData() +{ + if (!m_map) + return; + m_map->prefetchData(); +} + +/*! + \qmlmethod void QtLocation::Map::clearData() + + Clears map data collected by the currently selected plugin. + \note This method will delete cached files. + \sa plugin +*/ +void QDeclarativeGeoMap::clearData() +{ + m_map->clearData(); +} + +/*! + \qmlproperty string QtLocation::Map::errorString + + This read-only property holds the textual presentation of the latest mapping provider error. + If no error has occurred, an empty string is returned. + + An empty string may also be returned if an error occurred which has no associated + textual representation. + + \sa QGeoServiceProvider::errorString() +*/ + +QString QDeclarativeGeoMap::errorString() const +{ + return m_errorString; +} + +/*! + \qmlproperty enumeration QtLocation::Map::error + + This read-only property holds the last occurred mapping service provider error. + + \list + \li Map.NoError - No error has occurred. + \li Map.NotSupportedError -The maps plugin property was not set or there is no mapping manager associated with the plugin. + \li Map.UnknownParameterError -The plugin did not recognize one of the parameters it was given. + \li Map.MissingRequiredParameterError - The plugin did not find one of the parameters it was expecting. + \li Map.ConnectionError - The plugin could not connect to its backend service or database. + \endlist + + \sa QGeoServiceProvider::Error +*/ + +QGeoServiceProvider::Error QDeclarativeGeoMap::error() const +{ + return m_error; +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::touchEvent(QTouchEvent *event) +{ + if (isInteractive()) { + m_gestureArea->handleTouchEvent(event); + if ( event->type() == QEvent::TouchEnd || + event->type() == QEvent::TouchCancel) { + ungrabTouchPoints(); + } + } else { + //ignore event so sythesized event is generated; + QQuickItem::touchEvent(event); + } +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::wheelEvent(QWheelEvent *event) +{ + if (isInteractive()) + m_gestureArea->handleWheelEvent(event); + else + QQuickItem::wheelEvent(event); + +} + +bool QDeclarativeGeoMap::isInteractive() +{ + return (m_gestureArea->enabled() && m_gestureArea->acceptedGestures()) || m_gestureArea->isActive(); +} + +/*! + \internal +*/ +bool QDeclarativeGeoMap::childMouseEventFilter(QQuickItem *item, QEvent *event) +{ + Q_UNUSED(item) + if (!isVisible() || !isEnabled() || !isInteractive()) + return QQuickItem::childMouseEventFilter(item, event); + + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + return sendMouseEvent(static_cast(event)); + case QEvent::UngrabMouse: { + QQuickWindow *win = window(); + if (!win) break; + if (!win->mouseGrabberItem() || + (win->mouseGrabberItem() && + win->mouseGrabberItem() != this)) { + // child lost grab, we could even lost + // some events if grab already belongs for example + // in item in diffrent window , clear up states + mouseUngrabEvent(); + } + break; + } + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + case QEvent::TouchCancel: + if (static_cast(event)->touchPoints().count() >= 2) { + // 1 touch point = handle with MouseEvent (event is always synthesized) + // let the synthesized mouse event grab the mouse, + // note there is no mouse grabber at this point since + // touch event comes first (see Qt::AA_SynthesizeMouseForUnhandledTouchEvents) + return sendTouchEvent(static_cast(event)); + } + default: + break; + } + return QQuickItem::childMouseEventFilter(item, event); +} + +/*! + \qmlmethod void QtLocation::Map::addMapItem(MapItem item) + + Adds the given \a item to the Map (for example MapQuickItem, MapCircle). If the object + already is on the Map, it will not be added again. + + As an example, consider the case where you have a MapCircle representing your current position: + + \snippet declarative/maps.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/maps.qml Map addMapItem MapCircle at current position + + \note MapItemViews cannot be added with this method. + + \sa mapItems, removeMapItem, clearMapItems +*/ + +void QDeclarativeGeoMap::addMapItem(QDeclarativeGeoMapItemBase *item) +{ + if (!item || item->quickMap()) + return; + m_updateMutex.lock(); + item->setParentItem(this); + if (m_map) + item->setMap(this, m_map); + m_mapItems.append(item); + emit mapItemsChanged(); + m_updateMutex.unlock(); +} + +/*! + \qmlproperty list QtLocation::Map::mapItems + + Returns the list of all map items in no particular order. + These items include items that were declared statically as part of + the type declaration, as well as dynamical items (\l addMapItem, + \l MapItemView). + + \sa addMapItem, removeMapItem, clearMapItems +*/ + +QList QDeclarativeGeoMap::mapItems() +{ + QList ret; + foreach (const QPointer &ptr, m_mapItems) { + if (ptr) + ret << ptr.data(); + } + return ret; +} + +/*! + \qmlmethod void QtLocation::Map::removeMapItem(MapItem item) + + Removes the given \a item from the Map (for example MapQuickItem, MapCircle). If + the MapItem does not exist or was not previously added to the map, the + method does nothing. + + \sa mapItems, addMapItem, clearMapItems +*/ +void QDeclarativeGeoMap::removeMapItem(QDeclarativeGeoMapItemBase *ptr) +{ + if (!ptr || !m_map) + return; + QPointer item(ptr); + if (!m_mapItems.contains(item)) + return; + m_updateMutex.lock(); + item.data()->setParentItem(0); + item.data()->setMap(0, 0); + // these can be optimized for perf, as we already check the 'contains' above + m_mapItems.removeOne(item); + emit mapItemsChanged(); + m_updateMutex.unlock(); +} + +/*! + \qmlmethod void QtLocation::Map::clearMapItems() + + Removes all items from the map. + + \sa mapItems, addMapItem, removeMapItem +*/ +void QDeclarativeGeoMap::clearMapItems() +{ + if (m_mapItems.isEmpty()) + return; + m_updateMutex.lock(); + for (int i = 0; i < m_mapItems.count(); ++i) { + if (m_mapItems.at(i)) { + m_mapItems.at(i).data()->setParentItem(0); + m_mapItems.at(i).data()->setMap(0, 0); + } + } + m_mapItems.clear(); + emit mapItemsChanged(); + m_updateMutex.unlock(); +} + +/*! + \qmlproperty MapType QtLocation::Map::activeMapType + + \brief Access to the currently active \l{MapType}{map type}. + + This property can be set to change the active \l{MapType}{map type}. + See the \l{Map::supportedMapTypes}{supportedMapTypes} property for possible values. + + \sa MapType +*/ +void QDeclarativeGeoMap::setActiveMapType(QDeclarativeGeoMapType *mapType) +{ + if (m_activeMapType->mapType() != mapType->mapType()) { + m_activeMapType = mapType; + if (m_map) + m_map->setActiveMapType(mapType->mapType()); + emit activeMapTypeChanged(); + } +} + +QDeclarativeGeoMapType * QDeclarativeGeoMap::activeMapType() const +{ + return m_activeMapType; +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + m_gestureArea->setSize(newGeometry.size()); + QQuickItem::geometryChanged(newGeometry, oldGeometry); + + if (!m_map || !newGeometry.size().isValid()) + return; + + m_map->setSize(newGeometry.size().toSize()); + + if (!m_initialized) + initialize(); + else + setMinimumZoomLevel(m_map->minimumZoomForMapSize(newGeometry.width(), newGeometry.height())); + + /*! + The fitViewportTo*() functions depend on a valid map geometry. + If they were called prior to the first resize they cause + the zoomlevel to jump to 0 (showing the world). Therefore the + calls were queued up until now. + + Multiple fitViewportTo*() calls replace each other. + */ + if (m_pendingFitViewport && width() && height()) { + fitViewportToGeoShape(); + m_pendingFitViewport = false; + } + +} + +/*! + \qmlmethod void QtLocation::Map::fitViewportToMapItems() + + Fits the current viewport to the boundary of all map items. The camera is positioned + in the center of the map items, and at the largest integral zoom level possible which + allows all map items to be visible on screen + +*/ +void QDeclarativeGeoMap::fitViewportToMapItems() +{ + fitViewportToMapItemsRefine(true); +} + +/*! + \internal +*/ +void QDeclarativeGeoMap::fitViewportToMapItemsRefine(bool refine) +{ + if (!m_map) + return; + + if (m_mapItems.size() == 0) + return; + + double minX = 0; + double maxX = 0; + double minY = 0; + double maxY = 0; + double topLeftX = 0; + double topLeftY = 0; + double bottomRightX = 0; + double bottomRightY = 0; + bool haveQuickItem = false; + + // find bounds of all map items + int itemCount = 0; + for (int i = 0; i < m_mapItems.count(); ++i) { + if (!m_mapItems.at(i)) + continue; + QDeclarativeGeoMapItemBase *item = m_mapItems.at(i).data(); + if (!item) + continue; + + // skip quick items in the first pass and refine the fit later + if (refine) { + QDeclarativeGeoMapQuickItem *quickItem = + qobject_cast(item); + if (quickItem) { + haveQuickItem = true; + continue; + } + } + // Force map items to update immediately. Needed to ensure correct item size and positions + // when recursively calling this function. + if (item->isPolishScheduled()) + item->updatePolish(); + + topLeftX = item->position().x(); + topLeftY = item->position().y(); + bottomRightX = topLeftX + item->width(); + bottomRightY = topLeftY + item->height(); + + if (itemCount == 0) { + minX = topLeftX; + maxX = bottomRightX; + minY = topLeftY; + maxY = bottomRightY; + } else { + minX = qMin(minX, topLeftX); + maxX = qMax(maxX, bottomRightX); + minY = qMin(minY, topLeftY); + maxY = qMax(maxY, bottomRightY); + } + ++itemCount; + } + + if (itemCount == 0) { + if (haveQuickItem) + fitViewportToMapItemsRefine(false); + return; + } + double bboxWidth = maxX - minX; + double bboxHeight = maxY - minY; + double bboxCenterX = minX + (bboxWidth / 2.0); + double bboxCenterY = minY + (bboxHeight / 2.0); + + // position camera to the center of bounding box + QGeoCoordinate coordinate; + coordinate = m_map->itemPositionToCoordinate(QDoubleVector2D(bboxCenterX, bboxCenterY), false); + setProperty("center", QVariant::fromValue(coordinate)); + + // adjust zoom + double bboxWidthRatio = bboxWidth / (bboxWidth + bboxHeight); + double mapWidthRatio = width() / (width() + height()); + double zoomRatio; + + if (bboxWidthRatio > mapWidthRatio) + zoomRatio = bboxWidth / width(); + else + zoomRatio = bboxHeight / height(); + + qreal newZoom = std::log10(zoomRatio) / std::log10(0.5); + newZoom = std::floor(qMax(minimumZoomLevel(), (zoomLevel() + newZoom))); + setProperty("zoomLevel", QVariant::fromValue(newZoom)); + + // as map quick items retain the same screen size after the camera zooms in/out + // we refine the viewport again to achieve better results + if (refine) + fitViewportToMapItemsRefine(false); +} + +bool QDeclarativeGeoMap::sendMouseEvent(QMouseEvent *event) +{ + QPointF localPos = mapFromScene(event->windowPos()); + QQuickWindow *win = window(); + QQuickItem *grabber = win ? win->mouseGrabberItem() : 0; + bool stealEvent = m_gestureArea->isActive(); + + if ((stealEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) { + QScopedPointer mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos)); + mouseEvent->setAccepted(false); + + switch (mouseEvent->type()) { + case QEvent::MouseMove: + m_gestureArea->handleMouseMoveEvent(mouseEvent.data()); + break; + case QEvent::MouseButtonPress: + m_gestureArea->handleMousePressEvent(mouseEvent.data()); + break; + case QEvent::MouseButtonRelease: + m_gestureArea->handleMouseReleaseEvent(mouseEvent.data()); + break; + default: + break; + } + + stealEvent = m_gestureArea->isActive(); + grabber = win ? win->mouseGrabberItem() : 0; + + if (grabber && stealEvent && !grabber->keepMouseGrab() && grabber != this) + grabMouse(); + + if (stealEvent) { + //do not deliver + event->setAccepted(true); + return true; + } else { + return false; + } + } + + if (event->type() == QEvent::MouseButtonRelease) { + if (win && win->mouseGrabberItem() == this) + ungrabMouse(); + } + + return false; +} + +bool QDeclarativeGeoMap::sendTouchEvent(QTouchEvent *event) +{ + QQuickWindowPrivate *win = window() ? QQuickWindowPrivate::get(window()) : 0; + const QTouchEvent::TouchPoint &point = event->touchPoints().first(); + QQuickItem *grabber = win ? win->itemForTouchPointId.value(point.id()) : 0; + + bool stealEvent = m_gestureArea->isActive(); + bool containsPoint = contains(mapFromScene(point.scenePos())); + + if ((stealEvent || containsPoint) && (!grabber || !grabber->keepTouchGrab())) { + QScopedPointer touchEvent(new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints())); + touchEvent->setTimestamp(event->timestamp()); + touchEvent->setAccepted(false); + + m_gestureArea->handleTouchEvent(touchEvent.data()); + stealEvent = m_gestureArea->isActive(); + grabber = win ? win->itemForTouchPointId.value(point.id()) : 0; + + if (grabber && stealEvent && !grabber->keepTouchGrab() && grabber != this) { + QVector ids; + foreach (const QTouchEvent::TouchPoint &tp, event->touchPoints()) { + if (!(tp.state() & Qt::TouchPointReleased)) { + ids.append(tp.id()); + } + } + grabTouchPoints(ids); + } + + if (stealEvent) { + //do not deliver + event->setAccepted(true); + return true; + } else { + return false; + } + } + + if (event->type() == QEvent::TouchEnd) { + if (win && win->itemForTouchPointId.value(point.id()) == this) { + ungrabTouchPoints(); + } + } + return false; +} + +#include "moc_qdeclarativegeomap_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h new file mode 100644 index 0000000..d1d6965 --- /dev/null +++ b/src/imports/location/qdeclarativegeomap_p.h @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOMAP_H +#define QDECLARATIVEGEOMAP_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeoserviceprovider.h" +#include "qdeclarativegeomapitemview_p.h" +#include "qquickgeomapgesturearea_p.h" +#include "qgeocameradata_p.h" +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoServiceProvider; +class QDeclarativeGeoMapType; +class QDeclarativeGeoMapCopyrightNotice; + +class QDeclarativeGeoMap : public QQuickItem +{ + Q_OBJECT + Q_ENUMS(QGeoServiceProvider::Error) + Q_PROPERTY(QQuickGeoMapGestureArea *gesture READ gesture CONSTANT) + Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) + Q_PROPERTY(qreal minimumZoomLevel READ minimumZoomLevel WRITE setMinimumZoomLevel NOTIFY minimumZoomLevelChanged) + Q_PROPERTY(qreal maximumZoomLevel READ maximumZoomLevel WRITE setMaximumZoomLevel NOTIFY maximumZoomLevelChanged) + Q_PROPERTY(qreal zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged) + Q_PROPERTY(QDeclarativeGeoMapType *activeMapType READ activeMapType WRITE setActiveMapType NOTIFY activeMapTypeChanged) + Q_PROPERTY(QQmlListProperty supportedMapTypes READ supportedMapTypes NOTIFY supportedMapTypesChanged) + Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter NOTIFY centerChanged) + Q_PROPERTY(QList mapItems READ mapItems NOTIFY mapItemsChanged) + Q_PROPERTY(QGeoServiceProvider::Error error READ error NOTIFY errorChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) + Q_PROPERTY(QGeoShape visibleRegion READ visibleRegion WRITE setVisibleRegion) + Q_PROPERTY(bool copyrightsVisible READ copyrightsVisible WRITE setCopyrightsVisible NOTIFY copyrightsVisibleChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + Q_INTERFACES(QQmlParserStatus) + +public: + + explicit QDeclarativeGeoMap(QQuickItem *parent = 0); + ~QDeclarativeGeoMap(); + + void setPlugin(QDeclarativeGeoServiceProvider *plugin); + QDeclarativeGeoServiceProvider *plugin() const; + + void setActiveMapType(QDeclarativeGeoMapType *mapType); + QDeclarativeGeoMapType *activeMapType() const; + + void setMinimumZoomLevel(qreal minimumZoomLevel); + qreal minimumZoomLevel() const; + + void setMaximumZoomLevel(qreal maximumZoomLevel); + qreal maximumZoomLevel() const; + + void setZoomLevel(qreal zoomLevel); + qreal zoomLevel() const; + + void setCenter(const QGeoCoordinate ¢er); + QGeoCoordinate center() const; + + void setVisibleRegion(const QGeoShape &shape); + QGeoShape visibleRegion() const; + + void setCopyrightsVisible(bool visible); + bool copyrightsVisible() const; + + void setColor(const QColor &color); + QColor color() const; + + QQmlListProperty supportedMapTypes(); + + Q_INVOKABLE void removeMapItem(QDeclarativeGeoMapItemBase *item); + Q_INVOKABLE void addMapItem(QDeclarativeGeoMapItemBase *item); + Q_INVOKABLE void clearMapItems(); + QList mapItems(); + + Q_INVOKABLE QGeoCoordinate toCoordinate(const QPointF &position, bool clipToViewPort = true) const; + Q_INVOKABLE QPointF fromCoordinate(const QGeoCoordinate &coordinate, bool clipToViewPort = true) const; + + QQuickGeoMapGestureArea *gesture(); + + Q_INVOKABLE void fitViewportToMapItems(); + Q_INVOKABLE void pan(int dx, int dy); + Q_INVOKABLE void prefetchData(); // optional hint for prefetch + Q_INVOKABLE void clearData(); + + QString errorString() const; + QGeoServiceProvider::Error error() const; + +Q_SIGNALS: + void pluginChanged(QDeclarativeGeoServiceProvider *plugin); + void zoomLevelChanged(qreal zoomLevel); + void centerChanged(const QGeoCoordinate &coordinate); + void activeMapTypeChanged(); + void supportedMapTypesChanged(); + void minimumZoomLevelChanged(); + void maximumZoomLevelChanged(); + void mapItemsChanged(); + void errorChanged(); + void copyrightLinkActivated(const QString &link); + void copyrightsVisibleChanged(bool visible); + void colorChanged(const QColor &color); + +protected: + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE ; + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE ; + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE ; + void mouseUngrabEvent() Q_DECL_OVERRIDE ; + void touchUngrabEvent() Q_DECL_OVERRIDE; + void touchEvent(QTouchEvent *event) Q_DECL_OVERRIDE ; + void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE ; + + bool childMouseEventFilter(QQuickItem *item, QEvent *event) Q_DECL_OVERRIDE; + bool sendMouseEvent(QMouseEvent *event); + bool sendTouchEvent(QTouchEvent *event); + + void componentComplete() Q_DECL_OVERRIDE; + QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + + void setError(QGeoServiceProvider::Error error, const QString &errorString); + void initialize(); +private Q_SLOTS: + void mappingManagerInitialized(); + void pluginReady(); + void onMapChildrenChanged(); + void onSupportedMapTypesChanged(); + +private: + void setupMapView(QDeclarativeGeoMapItemView *view); + void populateMap(); + void fitViewportToMapItemsRefine(bool refine); + void fitViewportToGeoShape(); + bool isInteractive(); + +private: + QDeclarativeGeoServiceProvider *m_plugin; + QGeoServiceProvider *m_serviceProvider; + QGeoMappingManager *m_mappingManager; + QDeclarativeGeoMapType *m_activeMapType; + QList m_supportedMapTypes; + QList m_mapViews; + QQuickGeoMapGestureArea *m_gestureArea; + QGeoMap *m_map; + QPointer m_copyrights; + QList > m_mapItems; + QMutex m_updateMutex; + QString m_errorString; + QGeoServiceProvider::Error m_error; + QGeoShape m_region; + QColor m_color; + QGeoCameraData m_cameraData; + bool m_componentCompleted; + bool m_pendingFitViewport; + bool m_copyrightsVisible; + double m_maximumViewportLatitude; + bool m_initialized; + bool m_validRegion; + + friend class QDeclarativeGeoMapItem; + friend class QDeclarativeGeoMapItemView; + friend class QQuickGeoMapGestureArea; + Q_DISABLE_COPY(QDeclarativeGeoMap) +}; + + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeGeoMap) + +#endif diff --git a/src/imports/location/qdeclarativegeomapcopyrightsnotice.cpp b/src/imports/location/qdeclarativegeomapcopyrightsnotice.cpp new file mode 100644 index 0000000..7b5a576 --- /dev/null +++ b/src/imports/location/qdeclarativegeomapcopyrightsnotice.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Aaron McCarthy +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeomapcopyrightsnotice_p.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QDeclarativeGeoMapCopyrightNotice::QDeclarativeGeoMapCopyrightNotice(QQuickItem *parent) +: QQuickPaintedItem(parent), m_copyrightsHtml(0), m_copyrightsVisible(true) +{ + QQuickAnchors *anchors = property("anchors").value(); + if (anchors) { + anchors->setLeft(QQuickAnchorLine(parent, QQuickAnchors::LeftAnchor)); + anchors->setBottom(QQuickAnchorLine(parent, QQuickAnchors::BottomAnchor)); + } +} + +QDeclarativeGeoMapCopyrightNotice::~QDeclarativeGeoMapCopyrightNotice() +{ +} + +/*! + \internal +*/ +void QDeclarativeGeoMapCopyrightNotice::paint(QPainter *painter) +{ + painter->drawImage(0, 0, m_copyrightsImage); +} + +void QDeclarativeGeoMapCopyrightNotice::mousePressEvent(QMouseEvent *event) +{ + if (m_copyrightsHtml) { + m_activeAnchor = m_copyrightsHtml->documentLayout()->anchorAt(event->pos()); + if (!m_activeAnchor.isEmpty()) + return; + } + + QQuickPaintedItem::mousePressEvent(event); +} + +void QDeclarativeGeoMapCopyrightNotice::mouseReleaseEvent(QMouseEvent *event) +{ + if (m_copyrightsHtml) { + QString anchor = m_copyrightsHtml->documentLayout()->anchorAt(event->pos()); + if (anchor == m_activeAnchor && !anchor.isEmpty()) { + emit linkActivated(anchor); + m_activeAnchor.clear(); + } + } +} + +/*! + \internal +*/ +void QDeclarativeGeoMapCopyrightNotice::setCopyrightsVisible(bool visible) +{ + m_copyrightsVisible = visible; + + setVisible(!m_copyrightsImage.isNull() && visible); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapCopyrightNotice::setCopyrightsZ(int copyrightsZ) +{ + setZ(copyrightsZ); + update(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapCopyrightNotice::copyrightsChanged(const QImage ©rightsImage) +{ + delete m_copyrightsHtml; + m_copyrightsHtml = 0; + + m_copyrightsImage = copyrightsImage; + + setWidth(m_copyrightsImage.width()); + setHeight(m_copyrightsImage.height()); + + setKeepMouseGrab(false); + setAcceptedMouseButtons(Qt::NoButton); + setVisible(m_copyrightsVisible); + + update(); +} + +void QDeclarativeGeoMapCopyrightNotice::copyrightsChanged(const QString ©rightsHtml) +{ + if (copyrightsHtml.isEmpty() || !m_copyrightsVisible) { + m_copyrightsImage = QImage(); + setVisible(false); + return; + } else { + setVisible(true); + } + + if (!m_copyrightsHtml) + m_copyrightsHtml = new QTextDocument(this); + + m_copyrightsHtml->setHtml(copyrightsHtml); + + m_copyrightsImage = QImage(m_copyrightsHtml->size().toSize(), + QImage::Format_ARGB32_Premultiplied); + m_copyrightsImage.fill(qPremultiply(qRgba(255, 255, 255, 128))); + + QPainter painter(&m_copyrightsImage); + //m_copyrightsHtml->drawContents(&painter); // <- this uses the default application palette, that might have, f.ex., white text + QAbstractTextDocumentLayout::PaintContext ctx; + ctx.palette.setColor(QPalette::Text, QColor(QStringLiteral("black"))); + ctx.palette.setColor(QPalette::Link, QColor(QStringLiteral("blue"))); + m_copyrightsHtml->documentLayout()->draw(&painter, ctx); + + setWidth(m_copyrightsImage.width()); + setHeight(m_copyrightsImage.height()); + + setContentsSize(m_copyrightsImage.size()); + + setKeepMouseGrab(true); + setAcceptedMouseButtons(Qt::LeftButton); + + update(); +} + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomapcopyrightsnotice_p.h b/src/imports/location/qdeclarativegeomapcopyrightsnotice_p.h new file mode 100644 index 0000000..771ced6 --- /dev/null +++ b/src/imports/location/qdeclarativegeomapcopyrightsnotice_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Aaron McCarthy +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOMAPCOPYRIGHTSNOTICE_H +#define QDECLARATIVEGEOMAPCOPYRIGHTSNOTICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QTextDocument; + +class QDeclarativeGeoMapCopyrightNotice : public QQuickPaintedItem +{ + Q_OBJECT + +public: + explicit QDeclarativeGeoMapCopyrightNotice(QQuickItem *parent); + ~QDeclarativeGeoMapCopyrightNotice(); + + void setCopyrightsZ(int copyrightsZ); + + void setCopyrightsVisible(bool visible); + +public Q_SLOTS: + void copyrightsChanged(const QImage ©rightsImage); + void copyrightsChanged(const QString ©rightsHtml); + +signals: + void linkActivated(const QString &link); + +protected: + void paint(QPainter *painter) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + +private: + QTextDocument *m_copyrightsHtml; + QImage m_copyrightsImage; + QString m_activeAnchor; + bool m_copyrightsVisible; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/qdeclarativegeomapitembase.cpp b/src/imports/location/qdeclarativegeomapitembase.cpp new file mode 100644 index 0000000..8e825f5 --- /dev/null +++ b/src/imports/location/qdeclarativegeomapitembase.cpp @@ -0,0 +1,267 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeomapitembase_p.h" +#include "qgeocameradata_p.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoMapViewportChangeEvent::QGeoMapViewportChangeEvent() + : zoomLevelChanged(false), + centerChanged(false), + mapSizeChanged(false), + tiltChanged(false), + bearingChanged(false), + rollChanged(false) +{ +} + +QGeoMapViewportChangeEvent::QGeoMapViewportChangeEvent(const QGeoMapViewportChangeEvent &other) +{ + this->operator=(other); +} + +QGeoMapViewportChangeEvent &QGeoMapViewportChangeEvent::operator=(const QGeoMapViewportChangeEvent &other) +{ + if (this == &other) + return (*this); + + cameraData = other.cameraData; + mapSize = other.mapSize; + zoomLevelChanged = other.zoomLevelChanged; + centerChanged = other.centerChanged; + mapSizeChanged = other.mapSizeChanged; + tiltChanged = other.tiltChanged; + bearingChanged = other.bearingChanged; + rollChanged = other.rollChanged; + + return (*this); +} + +QDeclarativeGeoMapItemBase::QDeclarativeGeoMapItemBase(QQuickItem *parent) +: QQuickItem(parent), map_(0), quickMap_(0) +{ + setFiltersChildMouseEvents(true); + connect(this, SIGNAL(childrenChanged()), + this, SLOT(afterChildrenChanged())); +} + +QDeclarativeGeoMapItemBase::~QDeclarativeGeoMapItemBase() +{ + disconnect(this, SLOT(afterChildrenChanged())); + if (quickMap_) + quickMap_->removeMapItem(this); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemBase::afterChildrenChanged() +{ + QList kids = childItems(); + if (kids.size() > 0) { + bool printedWarning = false; + foreach (QQuickItem *i, kids) { + if (i->flags() & QQuickItem::ItemHasContents + && !qobject_cast(i)) { + if (!printedWarning) { + qmlInfo(this) << "Geographic map items do not support child items"; + printedWarning = true; + } + + qmlInfo(i) << "deleting this child"; + i->deleteLater(); + } + } + } +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemBase::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) +{ + if (quickMap == quickMap_) + return; + if (quickMap && quickMap_) + return; // don't allow association to more than one map + if (quickMap_) + quickMap_->disconnect(this); + if (map_) + map_->disconnect(this); + + quickMap_ = quickMap; + map_ = map; + + if (map_ && quickMap_) { + connect(map_, SIGNAL(cameraDataChanged(QGeoCameraData)), + this, SLOT(baseCameraDataChanged(QGeoCameraData))); + connect(quickMap, SIGNAL(heightChanged()), this, SLOT(polishAndUpdate())); + connect(quickMap, SIGNAL(widthChanged()), this, SLOT(polishAndUpdate())); + lastSize_ = QSizeF(quickMap_->width(), quickMap_->height()); + lastCameraData_ = map_->cameraData(); + } +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemBase::baseCameraDataChanged(const QGeoCameraData &cameraData) +{ + QGeoMapViewportChangeEvent evt; + evt.cameraData = cameraData; + evt.mapSize = QSizeF(quickMap_->width(), quickMap_->height()); + + if (evt.mapSize != lastSize_) + evt.mapSizeChanged = true; + + if (cameraData.bearing() != lastCameraData_.bearing()) + evt.bearingChanged = true; + if (cameraData.center() != lastCameraData_.center()) + evt.centerChanged = true; + if (cameraData.roll() != lastCameraData_.roll()) + evt.rollChanged = true; + if (cameraData.tilt() != lastCameraData_.tilt()) + evt.tiltChanged = true; + if (cameraData.zoomLevel() != lastCameraData_.zoomLevel()) + evt.zoomLevelChanged = true; + + lastSize_ = evt.mapSize; + lastCameraData_ = cameraData; + + afterViewportChanged(evt); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemBase::setPositionOnMap(const QGeoCoordinate &coordinate, const QPointF &offset) +{ + if (!map_ || !quickMap_) + return; + + QPointF topLeft = map_->coordinateToItemPosition(coordinate, false).toPointF() - offset; + + setPosition(topLeft); +} + +/*! + \internal +*/ +float QDeclarativeGeoMapItemBase::zoomLevelOpacity() const +{ + if (quickMap_->zoomLevel() > 3.0) + return 1.0; + else if (quickMap_->zoomLevel() > 2.0) + return quickMap_->zoomLevel() - 2.0; + else + return 0.0; +} + +bool QDeclarativeGeoMapItemBase::childMouseEventFilter(QQuickItem *item, QEvent *event) +{ + Q_UNUSED(item) + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + if (contains(static_cast(event)->pos())) { + return false; + } else { + event->setAccepted(false); + return true; + } + default: + return false; + } +} + +/*! + \internal +*/ +QSGNode *QDeclarativeGeoMapItemBase::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *pd) +{ + if (!map_ || !quickMap_) { + delete oldNode; + return 0; + } + + QSGOpacityNode *opn = static_cast(oldNode); + if (!opn) + opn = new QSGOpacityNode(); + + opn->setOpacity(zoomLevelOpacity()); + + QSGNode *oldN = opn->childCount() ? opn->firstChild() : 0; + opn->removeAllChildNodes(); + if (opn->opacity() > 0.0) { + QSGNode *n = this->updateMapItemPaintNode(oldN, pd); + if (n) + opn->appendChildNode(n); + } else { + delete oldN; + } + + return opn; +} + +/*! + \internal +*/ +QSGNode *QDeclarativeGeoMapItemBase::updateMapItemPaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + delete oldNode; + return 0; +} + +bool QDeclarativeGeoMapItemBase::isPolishScheduled() const +{ + return QQuickItemPrivate::get(this)->polishScheduled; +} + +void QDeclarativeGeoMapItemBase::polishAndUpdate() +{ + polish(); + update(); +} + + +#include "moc_qdeclarativegeomapitembase_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomapitembase_p.h b/src/imports/location/qdeclarativegeomapitembase_p.h new file mode 100644 index 0000000..c7793fb --- /dev/null +++ b/src/imports/location/qdeclarativegeomapitembase_p.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOMAPITEMBASE_H +#define QDECLARATIVEGEOMAPITEMBASE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include "qdeclarativegeomap_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoMapViewportChangeEvent +{ +public: + explicit QGeoMapViewportChangeEvent(); + QGeoMapViewportChangeEvent(const QGeoMapViewportChangeEvent &other); + QGeoMapViewportChangeEvent &operator=(const QGeoMapViewportChangeEvent &other); + + QGeoCameraData cameraData; + QSizeF mapSize; + + bool zoomLevelChanged; + bool centerChanged; + bool mapSizeChanged; + bool tiltChanged; + bool bearingChanged; + bool rollChanged; +}; + +class QDeclarativeGeoMapItemBase : public QQuickItem +{ + Q_OBJECT +public: + explicit QDeclarativeGeoMapItemBase(QQuickItem *parent = 0); + virtual ~QDeclarativeGeoMapItemBase(); + + virtual void setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map); + virtual void setPositionOnMap(const QGeoCoordinate &coordinate, const QPointF &offset); + + QDeclarativeGeoMap *quickMap() { return quickMap_; } + QGeoMap *map() { return map_; } + + QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); + virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *); + +protected Q_SLOTS: + virtual void afterChildrenChanged(); + virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) = 0; + void polishAndUpdate(); + +protected: + float zoomLevelOpacity() const; + bool childMouseEventFilter(QQuickItem *item, QEvent *event); + bool isPolishScheduled() const; + +private Q_SLOTS: + void baseCameraDataChanged(const QGeoCameraData &camera); + +private: + QGeoMap *map_; + QDeclarativeGeoMap *quickMap_; + + QSizeF lastSize_; + QGeoCameraData lastCameraData_; + + friend class QDeclarativeGeoMap; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/qdeclarativegeomapitemview.cpp b/src/imports/location/qdeclarativegeomapitemview.cpp new file mode 100644 index 0000000..0a9128f --- /dev/null +++ b/src/imports/location/qdeclarativegeomapitemview.cpp @@ -0,0 +1,540 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeomapitemview_p.h" +#include "qdeclarativegeomap_p.h" +#include "qdeclarativegeomapitembase_p.h" +#include "mapitemviewdelegateincubator.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype MapItemView + \instantiates QDeclarativeGeoMapItemView + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.5 + \inherits QObject + + \brief The MapItemView is used to populate Map from a model. + + The MapItemView is used to populate Map with MapItems from a model. + The MapItemView type only makes sense when contained in a Map, + meaning that it has no standalone presentation. + + \section2 Example Usage + + This example demonstrates how to use the MapViewItem object to display + a \l{Route}{route} on a \l{Map}{map}: + + \snippet declarative/maps.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/maps.qml MapRoute +*/ + +QDeclarativeGeoMapItemView::QDeclarativeGeoMapItemView(QQuickItem *parent) + : QObject(parent), componentCompleted_(false), delegate_(0), + itemModel_(0), map_(0), fitViewport_(false), m_metaObjectType(0), + m_readyIncubators(0), m_repopulating(false) +{ +} + +QDeclarativeGeoMapItemView::~QDeclarativeGeoMapItemView() +{ + removeInstantiatedItems(); + if (m_metaObjectType) + m_metaObjectType->release(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemView::componentComplete() +{ + componentCompleted_ = true; +} + +void QDeclarativeGeoMapItemView::incubatorStatusChanged(MapItemViewDelegateIncubator *incubator, + QQmlIncubator::Status status, + bool batched) +{ + if (status == QQmlIncubator::Loading) + return; + + QDeclarativeGeoMapItemViewItemData *itemData = incubator->m_itemData; + if (!itemData) { + // Should never get here + qWarning() << "MapItemViewDelegateIncubator incubating invalid itemData"; + return; + } + + switch (status) { + case QQmlIncubator::Ready: + { + QDeclarativeGeoMapItemBase *item = qobject_cast(incubator->object()); + if (!item) + break; + itemData->item = item; + if (!itemData->item) { + qWarning() << "QDeclarativeGeoMapItemView map item delegate is of unsupported type."; + delete incubator->object(); + } else { + if (!batched) { + map_->addMapItem(itemData->item); + fitViewport(); + } else { + ++m_readyIncubators; // QSemaphore not needed as multiple threads not involved + + if (m_readyIncubators == m_itemDataBatched.size()) { + + // Clearing stuff older than the reset + foreach (QDeclarativeGeoMapItemViewItemData *i, m_itemData) + removeItemData(i); + m_itemData.clear(); + + // Adding everthing created after reset was issued + foreach (QDeclarativeGeoMapItemViewItemData *i, m_itemDataBatched) { + map_->addMapItem(i->item); + } + m_itemData = m_itemDataBatched; + m_itemDataBatched.clear(); + + m_readyIncubators = 0; + m_repopulating = false; + + fitViewport(); + } + } + } + delete itemData->incubator; + itemData->incubator = 0; + break; + } + case QQmlIncubator::Null: + // Should never get here + delete itemData->incubator; + itemData->incubator = 0; + break; + case QQmlIncubator::Error: + qWarning() << "QDeclarativeGeoMapItemView map item creation failed."; + delete itemData->incubator; + itemData->incubator = 0; + break; + default: + ; + } +} + +/*! + \qmlproperty model QtLocation::MapItemView::model + + This property holds the model that provides data used for creating the map items defined by the + delegate. Only QAbstractItemModel based models are supported. +*/ +QVariant QDeclarativeGeoMapItemView::model() const +{ + return QVariant::fromValue(itemModel_); +} + +void QDeclarativeGeoMapItemView::setModel(const QVariant &model) +{ + QAbstractItemModel *itemModel = model.value(); + if (itemModel == itemModel_) + return; + + if (itemModel_) { + disconnect(itemModel_, SIGNAL(modelReset()), this, SLOT(itemModelReset())); + disconnect(itemModel_, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(itemModelRowsRemoved(QModelIndex,int,int))); + disconnect(itemModel_, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(itemModelRowsInserted(QModelIndex,int,int))); + disconnect(itemModel_, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), + this, SLOT(itemModelRowsMoved(QModelIndex,int,int,QModelIndex,int))); + disconnect(itemModel_, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), + this, SLOT(itemModelDataChanged(QModelIndex,QModelIndex,QVector))); + + removeInstantiatedItems(); // this also terminates ongong repopulations. + m_metaObjectType->release(); + m_metaObjectType = 0; + + itemModel_ = 0; + } + + if (itemModel) { + itemModel_ = itemModel; + connect(itemModel_, SIGNAL(modelReset()), this, SLOT(itemModelReset())); + connect(itemModel_, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(itemModelRowsRemoved(QModelIndex,int,int))); + connect(itemModel_, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(itemModelRowsInserted(QModelIndex,int,int))); + connect(itemModel_, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), + this, SLOT(itemModelRowsMoved(QModelIndex,int,int,QModelIndex,int))); + connect(itemModel_, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), + this, SLOT(itemModelDataChanged(QModelIndex,QModelIndex,QVector))); + + m_metaObjectType = new QQmlOpenMetaObjectType(&QObject::staticMetaObject, 0); + foreach (const QByteArray &name, itemModel_->roleNames()) + m_metaObjectType->createProperty(name); + + instantiateAllItems(); + } + + emit modelChanged(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemView::itemModelReset() +{ + repopulate(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemView::itemModelRowsInserted(const QModelIndex &index, int start, int end) +{ + Q_UNUSED(index) + + if (!componentCompleted_ || !map_ || !delegate_ || !itemModel_) + return; + + for (int i = start; i <= end; ++i) { + const QModelIndex insertedIndex = itemModel_->index(i, 0, index); + // If ran inside a qquickwidget which forces incubators to be synchronous, this call won't happen + // with m_repopulating == true while incubators from a model reset are still incubating. + // Note that having the model in a different thread is not supported in general. + createItemForIndex(insertedIndex, m_repopulating); + } + + fitViewport(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemView::itemModelRowsRemoved(const QModelIndex &index, int start, int end) +{ + Q_UNUSED(index) + + if (!componentCompleted_ || !map_ || !delegate_ || !itemModel_) + return; + + for (int i = end; i >= start; --i) { + if (m_repopulating) { + QDeclarativeGeoMapItemViewItemData *itemData = m_itemDataBatched.takeAt(i); + if (!itemData) + continue; + if (itemData->incubator) { + if (itemData->incubator->isReady()) { + --m_readyIncubators; + delete itemData->incubator->object(); + } + itemData->incubator->clear(); + } + delete itemData; + } else { + QDeclarativeGeoMapItemViewItemData *itemData = m_itemData.takeAt(i); + removeItemData(itemData); + } + } + + fitViewport(); +} + +void QDeclarativeGeoMapItemView::itemModelRowsMoved(const QModelIndex &parent, int start, int end, + const QModelIndex &destination, int row) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + Q_UNUSED(destination) + Q_UNUSED(row) + + qWarning() << "QDeclarativeGeoMapItemView does not support models that move rows."; +} + +void QDeclarativeGeoMapItemView::itemModelDataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight, + const QVector &roles) +{ + Q_UNUSED(roles) + + if (!m_itemData.count() || (m_repopulating && !m_itemDataBatched.count()) ) + return; + + for (int i = topLeft.row(); i <= bottomRight.row(); ++i) { + const QModelIndex index = itemModel_->index(i, 0); + QDeclarativeGeoMapItemViewItemData *itemData; + if (m_repopulating) + itemData= m_itemDataBatched.at(i); + else + itemData= m_itemData.at(i); + + QHashIterator iterator(itemModel_->roleNames()); + while (iterator.hasNext()) { + iterator.next(); + + QVariant modelData = itemModel_->data(index, iterator.key()); + if (!modelData.isValid()) + continue; + + itemData->context->setContextProperty(QString::fromLatin1(iterator.value().constData()), + modelData); + itemData->modelDataMeta->setValue(iterator.value(), modelData); + } + } +} + +/*! + \qmlproperty Component QtLocation::MapItemView::delegate + + This property holds the delegate which defines how each item in the + model should be displayed. The Component must contain exactly one + MapItem -derived object as the root object. +*/ +QQmlComponent *QDeclarativeGeoMapItemView::delegate() const +{ + return delegate_; +} + +void QDeclarativeGeoMapItemView::setDelegate(QQmlComponent *delegate) +{ + if (delegate_ == delegate) + return; + + delegate_ = delegate; + + repopulate(); + emit delegateChanged(); +} + +/*! + \qmlproperty Component QtLocation::MapItemView::autoFitViewport + + This property controls whether to automatically pan and zoom the viewport + to display all map items when items are added or removed. + + Defaults to false. +*/ +bool QDeclarativeGeoMapItemView::autoFitViewport() const +{ + return fitViewport_; +} + +void QDeclarativeGeoMapItemView::setAutoFitViewport(const bool &fitViewport) +{ + if (fitViewport == fitViewport_) + return; + fitViewport_ = fitViewport; + emit autoFitViewportChanged(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemView::fitViewport() +{ + if (!map_ || !fitViewport_ || m_repopulating) + return; + + if (map_->mapItems().size() > 0) + map_->fitViewportToMapItems(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemView::setMap(QDeclarativeGeoMap *map) +{ + if (!map || map_) // changing map on the fly not supported + return; + map_ = map; +} + +/*! + \internal +*/ +void QDeclarativeGeoMapItemView::removeInstantiatedItems() +{ + if (!map_) + return; + + terminateOngoingRepopulation(); + foreach (QDeclarativeGeoMapItemViewItemData *itemData, m_itemData) + removeItemData(itemData); + m_itemData.clear(); +} + +/*! + \internal + + Instantiates all items. +*/ +void QDeclarativeGeoMapItemView::instantiateAllItems() +{ + if (!componentCompleted_ || !map_ || !delegate_ || !itemModel_) + return; + Q_ASSERT(!m_itemDataBatched.size()); + m_repopulating = true; + + // QQuickWidget forces incubators to synchronous mode. Thus itemDataChanged gets called during the for loop below. + m_itemDataBatched.resize(itemModel_->rowCount()); + for (int i = 0; i < itemModel_->rowCount(); ++i) { + const QModelIndex index = itemModel_->index(i, 0); + createItemForIndex(index, true); + } + + fitViewport(); +} + +void QDeclarativeGeoMapItemView::removeItemData(QDeclarativeGeoMapItemViewItemData *itemData) +{ + if (!itemData) + return; + if (itemData->incubator) { + if (itemData->incubator->isReady()) { + if (itemData->incubator->object() == itemData->item) { + map_->removeMapItem(itemData->item); // removeMapItem checks whether the item is in the map, so it's safe to call. + itemData->item = 0; + } + delete itemData->incubator->object(); + } + itemData->incubator->clear(); // stops ongoing incubation + } + if (itemData->item) + map_->removeMapItem(itemData->item); + delete itemData; // destroys the ->item too. +} + +void QDeclarativeGeoMapItemView::terminateOngoingRepopulation() +{ + if (m_repopulating) { + // Terminate the previous resetting task. Not all incubators finished, but + // QQmlIncubatorController operates in the same thread, so it is safe + // to check, here, whether incubators are ready or not, without having + // to race with them. + + foreach (QDeclarativeGeoMapItemViewItemData *itemData, m_itemDataBatched) + removeItemData(itemData); + + m_itemDataBatched.clear(); + m_readyIncubators = 0; + m_repopulating = false; + } +} + +/*! + \internal + Removes and repopulates all items. +*/ +void QDeclarativeGeoMapItemView::repopulate() +{ + if (!itemModel_ || !itemModel_->rowCount()) { + removeInstantiatedItems(); + } else { + terminateOngoingRepopulation(); + instantiateAllItems(); // removal of instantiated item done at incubation completion + } +} + +/*! + \internal + + Note: this call is async. that is returns to the event loop before returning to the caller. + May also trigger incubatorStatusChanged() before returning to the caller if the incubator is fast enough. +*/ +void QDeclarativeGeoMapItemView::createItemForIndex(const QModelIndex &index, bool batched) +{ + // Expected to be already tested by caller. + Q_ASSERT(delegate_); + Q_ASSERT(itemModel_); + + QDeclarativeGeoMapItemViewItemData *itemData = new QDeclarativeGeoMapItemViewItemData; + + itemData->modelData = new QObject; + itemData->modelDataMeta = new QQmlOpenMetaObject(itemData->modelData, m_metaObjectType, false); + itemData->context = new QQmlContext(qmlContext(this)); + + QHashIterator iterator(itemModel_->roleNames()); + while (iterator.hasNext()) { + iterator.next(); + + QVariant modelData = itemModel_->data(index, iterator.key()); + if (!modelData.isValid()) + continue; + + itemData->context->setContextProperty(QString::fromLatin1(iterator.value().constData()), + modelData); + + itemData->modelDataMeta->setValue(iterator.value(), modelData); + } + + itemData->context->setContextProperty(QLatin1String("model"), itemData->modelData); + itemData->context->setContextProperty(QLatin1String("index"), index.row()); + + if (batched || m_repopulating) { + if (index.row() < m_itemDataBatched.size()) + m_itemDataBatched.replace(index.row(), itemData); + else + m_itemDataBatched.insert(index.row(), itemData); + } else + m_itemData.insert(index.row(), itemData); + itemData->incubator = new MapItemViewDelegateIncubator(this, itemData, batched || m_repopulating); + + delegate_->create(*itemData->incubator, itemData->context); +} + +QDeclarativeGeoMapItemViewItemData::~QDeclarativeGeoMapItemViewItemData() +{ + delete incubator; + delete item; + delete context; + delete modelData; +} + +#include "moc_qdeclarativegeomapitemview_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomapitemview_p.h b/src/imports/location/qdeclarativegeomapitemview_p.h new file mode 100644 index 0000000..6a4a292 --- /dev/null +++ b/src/imports/location/qdeclarativegeomapitemview_p.h @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOMAPITEMVIEW_H +#define QDECLARATIVEGEOMAPITEMVIEW_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include "qdeclarativegeomapitemview_p_p.h" + +QT_BEGIN_NAMESPACE + +class QAbstractItemModel; +class QQmlComponent; +class QQuickItem; +class QDeclarativeGeoMap; +class QDeclarativeGeoMapItemBase; +class QQmlOpenMetaObject; +class QQmlOpenMetaObjectType; +class MapItemViewDelegateIncubator; + +class QDeclarativeGeoMapItemView : public QObject, public QQmlParserStatus +{ + Q_OBJECT + + Q_INTERFACES(QQmlParserStatus) + + Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged) + Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) + Q_PROPERTY(bool autoFitViewport READ autoFitViewport WRITE setAutoFitViewport NOTIFY autoFitViewportChanged) + +public: + explicit QDeclarativeGeoMapItemView(QQuickItem *parent = 0); + ~QDeclarativeGeoMapItemView(); + + QVariant model() const; + void setModel(const QVariant &); + + QQmlComponent *delegate() const; + void setDelegate(QQmlComponent *); + + bool autoFitViewport() const; + void setAutoFitViewport(const bool &); + + void setMap(QDeclarativeGeoMap *); + void repopulate(); + void removeInstantiatedItems(); + void instantiateAllItems(); + + qreal zValue(); + void setZValue(qreal zValue); + + // From QQmlParserStatus + virtual void componentComplete(); + void classBegin() {} + +Q_SIGNALS: + void modelChanged(); + void delegateChanged(); + void autoFitViewportChanged(); + +protected: + void incubatorStatusChanged(MapItemViewDelegateIncubator *incubator, + QQmlIncubator::Status status, + bool batched); + +private Q_SLOTS: + void itemModelReset(); + void itemModelRowsInserted(const QModelIndex &index, int start, int end); + void itemModelRowsRemoved(const QModelIndex &index, int start, int end); + void itemModelRowsMoved(const QModelIndex &parent, int start, int end, + const QModelIndex &destination, int row); + void itemModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QVector &roles); + +private: + void createItemForIndex(const QModelIndex &index, bool batched = false); + void fitViewport(); + void terminateOngoingRepopulation(); + void removeItemData(QDeclarativeGeoMapItemViewItemData *itemData); + + bool componentCompleted_; + QQmlComponent *delegate_; + QAbstractItemModel *itemModel_; + QDeclarativeGeoMap *map_; + QVector m_itemData; + QVector m_itemDataBatched; + bool fitViewport_; + + QQmlOpenMetaObjectType *m_metaObjectType; + int m_readyIncubators; + bool m_repopulating; + + friend class QDeclarativeGeoMapItemViewItemData; + friend class MapItemViewDelegateIncubator; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeGeoMapItemView) + +#endif diff --git a/src/imports/location/qdeclarativegeomapitemview_p_p.h b/src/imports/location/qdeclarativegeomapitemview_p_p.h new file mode 100644 index 0000000..5a4e3b2 --- /dev/null +++ b/src/imports/location/qdeclarativegeomapitemview_p_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOMAPITEMVIEW_P_P_H +#define QDECLARATIVEGEOMAPITEMVIEW_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class MapItemViewDelegateIncubator; +class QDeclarativeGeoMapItemView; +class QDeclarativeGeoMapItemBase; + +struct QDeclarativeGeoMapItemViewItemData { + QDeclarativeGeoMapItemViewItemData() + : incubator(0), item(0), context(0), modelData(0), modelDataMeta(0) + { + } + + ~QDeclarativeGeoMapItemViewItemData(); + + MapItemViewDelegateIncubator *incubator; + QDeclarativeGeoMapItemBase *item; + QQmlContext *context; + QObject *modelData; + QQmlOpenMetaObject *modelDataMeta; + + friend class MapItemViewDelegateIncubator; + friend class QDeclarativeGeoMapItemView; +}; + +Q_DECLARE_TYPEINFO(QDeclarativeGeoMapItemViewItemData, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +#endif // QDECLARATIVEGEOMAPITEMVIEW_P_P_H diff --git a/src/imports/location/qdeclarativegeomapquickitem.cpp b/src/imports/location/qdeclarativegeomapquickitem.cpp new file mode 100644 index 0000000..a66efb1 --- /dev/null +++ b/src/imports/location/qdeclarativegeomapquickitem.cpp @@ -0,0 +1,354 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeomapquickitem_p.h" + +#include +#include +#include +#include "qdoublevector2d_p.h" +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype MapQuickItem + \instantiates QDeclarativeGeoMapQuickItem + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.5 + + \brief The MapQuickItem type displays an arbitrary Qt Quick object + on a Map. + + The MapQuickItem type is used to place an arbitrary Qt Quick object + on a Map at a specified location and size. Compared to floating an item + above the Map, a MapQuickItem will follow the panning (and optionally, the + zooming) of the Map as if it is on the Map surface. + + The \l{sourceItem} property contains the Qt Quick item to be drawn, which + can be any kind of visible type. + + \section2 Positioning and Sizing + + The positioning of the MapQuickItem on the Map is controlled by two + properties: \l coordinate and \l anchorPoint. If only \l coordinate is set, + it specifies a longitude/latitude coordinate for the item to be placed at. + The set coordinate will line up with the top-left corner of the contained + item when shown on the screen. + + The \l anchorPoint property provides a way to line up the coordinate with + other parts of the item than just the top-left corner, by setting a number + of pixels the item will be offset by. A simple way to think about it is + to note that the point given by \l anchorPoint on the item itself is the + point that will line up with the given \l coordinate when displayed. + + In addition to being anchored to the map, the MapQuickItem can optionally + follow the scale of the map, and change size when the Map is zoomed in or + zoomed out. This behaviour is controlled by the \l zoomLevel property. The + default behaviour if \l zoomLevel is not set is for the item to be drawn + "on the screen" rather than "on the map", so that its size remains the same + regardless of the zoom level of the Map. + + \section2 Performance + + Performance of a MapQuickItem is normally in the same ballpark as the + contained Qt Quick item alone. Overheads added amount to a translation + and (possibly) scaling of the original item, as well as a transformation + from longitude and latitude to screen position. + + \section2 Limitations + + \note Due to an implementation detail, items placed inside a + MapQuickItem will have a \c{parent} item which is not the MapQuickItem. + Refer to the MapQuickItem by its \c{id}, and avoid the use of \c{anchor} + in the \c{sourceItem}. + + \section2 Example Usage + + The following snippet shows a MapQuickItem containing an Image object, + to display a Marker on the Map. This strategy is used to show the map + markers in the MapViewer example. + + \snippet mapviewer/map/Marker.qml mqi-top + \snippet mapviewer/map/Marker.qml mqi-anchor + \snippet mapviewer/map/Marker.qml mqi-closeimage + \snippet mapviewer/map/Marker.qml mqi-close + + \image api-mapquickitem.png +*/ + +QDeclarativeGeoMapQuickItem::QDeclarativeGeoMapQuickItem(QQuickItem *parent) +: QDeclarativeGeoMapItemBase(parent), zoomLevel_(0.0), + mapAndSourceItemSet_(false), updatingGeometry_(false) +{ + setFlag(ItemHasContents, true); + opacityContainer_ = new QQuickItem(this); + opacityContainer_->setParentItem(this); + opacityContainer_->setFlag(ItemHasContents, true); +} + +QDeclarativeGeoMapQuickItem::~QDeclarativeGeoMapQuickItem() {} + +/*! + \qmlproperty coordinate MapQuickItem::coordinate + + This property holds the anchor coordinate of the MapQuickItem. The point + on the sourceItem that is specified by anchorPoint is kept aligned with + this coordinate when drawn on the map. + + In the image below, there are 3 MapQuickItems that are identical except + for the value of their anchorPoint properties. The values of anchorPoint + for each are written on top of the item. + + \image api-mapquickitem-anchor.png +*/ +void QDeclarativeGeoMapQuickItem::setCoordinate(const QGeoCoordinate &coordinate) +{ + if (coordinate_ == coordinate) + return; + + coordinate_ = coordinate; + + polishAndUpdate(); + emit coordinateChanged(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapQuickItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) +{ + QDeclarativeGeoMapItemBase::setMap(quickMap,map); + if (map && quickMap) { + connect(map, SIGNAL(cameraDataChanged(QGeoCameraData)), + this, SLOT(polishAndUpdate())); + polishAndUpdate(); + } +} + +/*! + \internal +*/ +void QDeclarativeGeoMapQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + if (!mapAndSourceItemSet_ || updatingGeometry_ || + newGeometry.topLeft() == oldGeometry.topLeft()) { + QDeclarativeGeoMapItemBase::geometryChanged(newGeometry, oldGeometry); + return; + } + + QGeoCoordinate newCoordinate = map()->itemPositionToCoordinate(QDoubleVector2D(x(), y()) + (scaleFactor() * QDoubleVector2D(anchorPoint_)), false); + if (newCoordinate.isValid()) + setCoordinate(newCoordinate); + + // Not calling QDeclarativeGeoMapItemBase::geometryChanged() as it will be called from a nested + // call to this function. +} + +/*! + \internal +*/ +QGeoCoordinate QDeclarativeGeoMapQuickItem::coordinate() +{ + return coordinate_; +} + +/*! + \qmlproperty object MapQuickItem::sourceItem + + This property holds the source item that will be drawn on the map. +*/ +void QDeclarativeGeoMapQuickItem::setSourceItem(QQuickItem *sourceItem) +{ + if (sourceItem_.data() == sourceItem) + return; + sourceItem_ = sourceItem; + + polishAndUpdate(); + emit sourceItemChanged(); +} + +QQuickItem *QDeclarativeGeoMapQuickItem::sourceItem() +{ + return sourceItem_.data(); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapQuickItem::afterChildrenChanged() +{ + QList kids = childItems(); + if (kids.size() > 0) { + bool printedWarning = false; + foreach (QQuickItem *i, kids) { + if (i->flags() & QQuickItem::ItemHasContents + && !qobject_cast(i) + && sourceItem_.data() != i + && opacityContainer_ != i) { + if (!printedWarning) { + qmlInfo(this) << "Use the sourceItem property for the contained item, direct children are not supported"; + printedWarning = true; + } + + qmlInfo(i) << "deleting this child"; + i->deleteLater(); + } + } + } +} + +/*! + \qmlproperty QPointF MapQuickItem::anchorPoint + + This property determines which point on the sourceItem that will be lined + up with the coordinate on the map. +*/ +void QDeclarativeGeoMapQuickItem::setAnchorPoint(const QPointF &anchorPoint) +{ + if (anchorPoint == anchorPoint_) + return; + anchorPoint_ = anchorPoint; + polishAndUpdate(); + emit anchorPointChanged(); +} + +QPointF QDeclarativeGeoMapQuickItem::anchorPoint() const +{ + return anchorPoint_; +} + +/*! + \qmlproperty real MapQuickItem::zoomLevel + + This property controls the scaling behaviour of the contents of the + MapQuickItem. In particular, by setting this property it is possible + to choose between objects that are drawn on the screen (and sized in + screen pixels), and those drawn on the map surface (which change size + with the zoom level of the map). + + The default value for this property is 0.0, which corresponds to drawing + the object on the screen surface. If set to another value, the object will + be drawn on the map surface instead. The value (if not zero) specifies the + zoomLevel at which the object will be visible at a scale of 1:1 (ie, where + object pixels and screen pixels are the same). At zoom levels lower than + this, the object will appear smaller, and at higher zoom levels, appear + larger. This is in contrast to when this property is set to zero, where + the object remains the same size on the screen at all zoom levels. +*/ +void QDeclarativeGeoMapQuickItem::setZoomLevel(qreal zoomLevel) +{ + if (zoomLevel == zoomLevel_) + return; + zoomLevel_ = zoomLevel; + polishAndUpdate(); + emit zoomLevelChanged(); +} + +qreal QDeclarativeGeoMapQuickItem::zoomLevel() const +{ + return zoomLevel_; +} + +/*! + \internal +*/ +void QDeclarativeGeoMapQuickItem::updatePolish() +{ + if (!quickMap() && sourceItem_) { + mapAndSourceItemSet_ = false; + sourceItem_.data()->setParentItem(0); + return; + } + + if (!quickMap() || !map() || !sourceItem_) { + mapAndSourceItemSet_ = false; + return; + } + + if (!mapAndSourceItemSet_ && quickMap() && map() && sourceItem_) { + mapAndSourceItemSet_ = true; + sourceItem_.data()->setParentItem(opacityContainer_); + sourceItem_.data()->setTransformOrigin(QQuickItem::TopLeft); + connect(sourceItem_.data(), SIGNAL(xChanged()), + this, SLOT(polishAndUpdate())); + connect(sourceItem_.data(), SIGNAL(yChanged()), + this, SLOT(polishAndUpdate())); + connect(sourceItem_.data(), SIGNAL(widthChanged()), + this, SLOT(polishAndUpdate())); + connect(sourceItem_.data(), SIGNAL(heightChanged()), + this, SLOT(polishAndUpdate())); + } + + QScopedValueRollback rollback(updatingGeometry_); + updatingGeometry_ = true; + + opacityContainer_->setOpacity(zoomLevelOpacity()); + + sourceItem_.data()->setScale(scaleFactor()); + sourceItem_.data()->setPosition(QPointF(0,0)); + setWidth(sourceItem_.data()->width()); + setHeight(sourceItem_.data()->height()); + setPositionOnMap(coordinate(), scaleFactor() * anchorPoint_); +} + +/*! + \internal +*/ +void QDeclarativeGeoMapQuickItem::afterViewportChanged(const QGeoMapViewportChangeEvent &event) +{ + Q_UNUSED(event); +} + +/*! + \internal +*/ +qreal QDeclarativeGeoMapQuickItem::scaleFactor() +{ + qreal scale = 1.0; + // use 1+x to avoid fuzzy compare against zero + if (!qFuzzyCompare(1.0 + zoomLevel_, 1.0)) + scale = std::pow(0.5, zoomLevel_ - map()->cameraData().zoomLevel()); + return scale; +} + +#include "moc_qdeclarativegeomapquickitem_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomapquickitem_p.h b/src/imports/location/qdeclarativegeomapquickitem_p.h new file mode 100644 index 0000000..0410f06 --- /dev/null +++ b/src/imports/location/qdeclarativegeomapquickitem_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOMAPQUICKITEM_H +#define QDECLARATIVEGEOMAPQUICKITEM_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include "qdeclarativegeomap_p.h" +#include "qdeclarativegeomapitembase_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoMapQuickItem : public QDeclarativeGeoMapItemBase +{ + Q_OBJECT + Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged) + Q_PROPERTY(QPointF anchorPoint READ anchorPoint WRITE setAnchorPoint NOTIFY anchorPointChanged) + Q_PROPERTY(qreal zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged) + Q_PROPERTY(QQuickItem *sourceItem READ sourceItem WRITE setSourceItem NOTIFY sourceItemChanged) + +public: + explicit QDeclarativeGeoMapQuickItem(QQuickItem *parent = 0); + ~QDeclarativeGeoMapQuickItem(); + + virtual void setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) Q_DECL_OVERRIDE; + + void setCoordinate(const QGeoCoordinate &coordinate); + QGeoCoordinate coordinate(); + + void setSourceItem(QQuickItem *sourceItem); + QQuickItem *sourceItem(); + + void setAnchorPoint(const QPointF &anchorPoint); + QPointF anchorPoint() const; + + void setZoomLevel(qreal zoomLevel); + qreal zoomLevel() const; + +Q_SIGNALS: + void coordinateChanged(); + void sourceItemChanged(); + void anchorPointChanged(); + void zoomLevelChanged(); + +protected: + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void updatePolish() Q_DECL_OVERRIDE; + +protected Q_SLOTS: + virtual void afterChildrenChanged() Q_DECL_OVERRIDE; + virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; + +private: + qreal scaleFactor(); + QGeoCoordinate coordinate_; + QPointer sourceItem_; + QQuickItem *opacityContainer_; + QPointF anchorPoint_; + qreal zoomLevel_; + bool mapAndSourceItemSet_; + bool updatingGeometry_; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeGeoMapQuickItem) + +#endif diff --git a/src/imports/location/qdeclarativegeomaptype.cpp b/src/imports/location/qdeclarativegeomaptype.cpp new file mode 100644 index 0000000..0b90ec3 --- /dev/null +++ b/src/imports/location/qdeclarativegeomaptype.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeomaptype_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype MapType + \instantiates QDeclarativeGeoMapType + \inherits QObject + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.5 + + \brief The MapType type holds information about a map type. + + This includes the map type's \l name and \l description, the \l style and + a flag to indicate if the map type is optimized for mobile devices (\l mobile). +*/ + +QDeclarativeGeoMapType::QDeclarativeGeoMapType(const QGeoMapType mapType, QObject *parent) + : QObject(parent), + mapType_(mapType) {} + +QDeclarativeGeoMapType::~QDeclarativeGeoMapType() {} + +/*! + \qmlproperty enumeration MapType::style + + This read-only property gives access to the style of the map type. + + \list + \li MapType.NoMap - No map. + \li MapType.StreetMap - A street map. + \li MapType.SatelliteMapDay - A map with day-time satellite imagery. + \li MapType.SatelliteMapNight - A map with night-time satellite imagery. + \li MapType.TerrainMap - A terrain map. + \li MapType.HybridMap - A map with satellite imagery and street information. + \li MapType.GrayStreetMap - A gray-shaded street map. + \li MapType.PedestrianMap - A street map suitable for pedestriants. + \li MapType.CarNavigationMap - A street map suitable for car navigation. + \li MapType.CycleMap - A street map suitable for cyclists. + \li MapType.CustomMap - A custom map type. + \endlist +*/ +QDeclarativeGeoMapType::MapStyle QDeclarativeGeoMapType::style() const +{ + return QDeclarativeGeoMapType::MapStyle(mapType_.style()); +} + +/*! + \qmlproperty string MapType::name + + This read-only property holds the name of the map type as a single formatted string. +*/ +QString QDeclarativeGeoMapType::name() const +{ + return mapType_.name(); +} + +/*! + \qmlproperty string MapType::description + + This read-only property holds the description of the map type as a single formatted string. +*/ +QString QDeclarativeGeoMapType::description() const +{ + return mapType_.description(); +} + +/*! + \qmlproperty bool MapType::mobile + + \brief Whether the map type is optimized for the use on a mobile device. + + Map types for mobile devices usually have higher constrast to counteract the + effects of sunlight and a reduced color for improved readability. +*/ +bool QDeclarativeGeoMapType::mobile() const +{ + return mapType_.mobile(); +} + +/*! + \qmlproperty bool MapType::night + \since Qt Location 5.4 + + \brief Whether the map type is optimized for use at night. + + Map types suitable for use at night usually have a dark background. +*/ +bool QDeclarativeGeoMapType::night() const +{ + return mapType_.night(); +} + +#include "moc_qdeclarativegeomaptype_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomaptype_p.h b/src/imports/location/qdeclarativegeomaptype_p.h new file mode 100644 index 0000000..980c594 --- /dev/null +++ b/src/imports/location/qdeclarativegeomaptype_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOMAPTYPE_H +#define QDECLARATIVEGEOMAPTYPE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoMapType : public QObject +{ + Q_OBJECT + Q_ENUMS(MapStyle) + + Q_PROPERTY(MapStyle style READ style CONSTANT) + Q_PROPERTY(QString name READ name CONSTANT) + Q_PROPERTY(QString description READ description CONSTANT) + Q_PROPERTY(bool mobile READ mobile CONSTANT) + Q_PROPERTY(bool night READ night CONSTANT REVISION 1) + +public: + enum MapStyle { + NoMap = QGeoMapType::NoMap, + StreetMap = QGeoMapType::StreetMap, + SatelliteMapDay = QGeoMapType::SatelliteMapDay, + SatelliteMapNight = QGeoMapType::SatelliteMapNight, + TerrainMap = QGeoMapType::TerrainMap, + HybridMap = QGeoMapType::HybridMap, + TransitMap = QGeoMapType::TransitMap, + GrayStreetMap = QGeoMapType::GrayStreetMap, + PedestrianMap = QGeoMapType::PedestrianMap, + CarNavigationMap = QGeoMapType::CarNavigationMap, + CycleMap = QGeoMapType::CycleMap, + CustomMap = 100 + }; + + QDeclarativeGeoMapType(const QGeoMapType mapType, QObject *parent = 0); + ~QDeclarativeGeoMapType(); + + MapStyle style() const; + QString name() const; + QString description() const; + bool mobile() const; + bool night() const; + + const QGeoMapType mapType() { return mapType_; } + +private: + QGeoMapType mapType_; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeGeoMapType) + +#endif diff --git a/src/imports/location/qdeclarativegeoroute.cpp b/src/imports/location/qdeclarativegeoroute.cpp new file mode 100644 index 0000000..9fe2909 --- /dev/null +++ b/src/imports/location/qdeclarativegeoroute.cpp @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeoroute_p.h" +#include "locationvaluetypehelper_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Route + \instantiates QDeclarativeGeoRoute + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-routing + \since Qt Location 5.5 + + \brief The Route type represents one geographical route. + + A Route type contains high level information about a route, such + as the length the route, the estimated travel time for the route, + and enough information to render a basic image of the route on a map. + + The QGeoRoute object also contains a list of \l RouteSegment objects which + describe subsections of the route in greater detail. + + The primary means of acquiring Route objects is \l RouteModel. + + \section1 Example + + This example shows how to display a route's maneuvers in a ListView: + + \snippet declarative/routing.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/routing.qml Route Maneuver List1 + \snippet declarative/routing.qml Route Maneuver List2 + \snippet declarative/routing.qml Route Maneuver List3 + +*/ + +QDeclarativeGeoRoute::QDeclarativeGeoRoute(QObject *parent) + : QObject(parent) +{ + this->init(); +} + +QDeclarativeGeoRoute::QDeclarativeGeoRoute(const QGeoRoute &route, QObject *parent) + : QObject(parent), + route_(route) +{ + this->init(); +} + +QDeclarativeGeoRoute::~QDeclarativeGeoRoute() {} + +void QDeclarativeGeoRoute::init() +{ + QGeoRouteSegment segment = route_.firstRouteSegment(); + while (segment.isValid()) { + QDeclarativeGeoRouteSegment *routeSegment = new QDeclarativeGeoRouteSegment(segment, this); + QQmlEngine::setContextForObject(routeSegment, QQmlEngine::contextForObject(this)); + segments_.append(routeSegment); + segment = segment.nextRouteSegment(); + } +} + +/*! + \internal +*/ +QList QDeclarativeGeoRoute::routePath() +{ + return route_.path(); +} + +/*! + \qmlproperty georectangle QtLocation::Route::bounds + + Read-only property which holds a bounding box which encompasses the entire route. + +*/ + +QGeoRectangle QDeclarativeGeoRoute::bounds() const +{ + return route_.bounds(); +} + +/*! + \qmlproperty int QtLocation::Route::travelTime + + Read-only property which holds the estimated amount of time it will take to + traverse this route, in seconds. + +*/ + +int QDeclarativeGeoRoute::travelTime() const +{ + return route_.travelTime(); +} + +/*! + \qmlproperty real QtLocation::Route::distance + + Read-only property which holds distance covered by this route, in meters. +*/ + +qreal QDeclarativeGeoRoute::distance() const +{ + return route_.distance(); +} + +/*! + \qmlproperty QJSValue QtLocation::Route::path + + Read-only property which holds the geographical coordinates of this route. + Coordinates are listed in the order in which they would be traversed by someone + traveling along this segment of the route. + + To access individual segments you can use standard list accessors: 'path.length' + indicates the number of objects and 'path[index starting from zero]' gives + the actual object. + + \sa QtPositioning::coordinate +*/ + +QJSValue QDeclarativeGeoRoute::path() const +{ + QQmlContext *context = QQmlEngine::contextForObject(parent()); + QQmlEngine *engine = context->engine(); + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); + + QV4::Scope scope(v4); + QV4::Scoped pathArray(scope, v4->newArrayObject(route_.path().length())); + for (int i = 0; i < route_.path().length(); ++i) { + const QGeoCoordinate &c = route_.path().at(i); + + QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(c))); + pathArray->putIndexed(i, cv); + } + + return QJSValue(v4, pathArray.asReturnedValue()); +} + +void QDeclarativeGeoRoute::setPath(const QJSValue &value) +{ + if (!value.isArray()) + return; + + QList pathList; + quint32 length = value.property(QStringLiteral("length")).toUInt(); + for (quint32 i = 0; i < length; ++i) { + bool ok; + QGeoCoordinate c = parseCoordinate(value.property(i), &ok); + + if (!ok || !c.isValid()) { + qmlInfo(this) << "Unsupported path type"; + return; + } + + pathList.append(c); + } + + if (route_.path() == pathList) + return; + + route_.setPath(pathList); + + emit pathChanged(); +} + +/*! + \qmlproperty list QtLocation::Route::segments + + Read-only property which holds the list of \l RouteSegment objects of this route. + + To access individual segments you can use standard list accessors: 'segments.length' + indicates the number of objects and 'segments[index starting from zero]' gives + the actual objects. + + \sa RouteSegment +*/ + +QQmlListProperty QDeclarativeGeoRoute::segments() +{ + return QQmlListProperty(this, 0, segments_append, segments_count, + segments_at, segments_clear); +} + +/*! + \internal +*/ +void QDeclarativeGeoRoute::segments_append(QQmlListProperty *prop, + QDeclarativeGeoRouteSegment *segment) +{ + static_cast(prop->object)->appendSegment(segment); +} + +/*! + \internal +*/ +int QDeclarativeGeoRoute::segments_count(QQmlListProperty *prop) +{ + return static_cast(prop->object)->segments_.count(); +} + +/*! + \internal +*/ +QDeclarativeGeoRouteSegment *QDeclarativeGeoRoute::segments_at(QQmlListProperty *prop, int index) +{ + return static_cast(prop->object)->segments_.at(index); +} + +/*! + \internal +*/ +void QDeclarativeGeoRoute::segments_clear(QQmlListProperty *prop) +{ + static_cast(prop->object)->clearSegments(); +} + +/*! + \internal +*/ +void QDeclarativeGeoRoute::appendSegment(QDeclarativeGeoRouteSegment *segment) +{ + segments_.append(segment); +} + +/*! + \internal +*/ +void QDeclarativeGeoRoute::clearSegments() +{ + segments_.clear(); +} + +#include "moc_qdeclarativegeoroute_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeoroute_p.h b/src/imports/location/qdeclarativegeoroute_p.h new file mode 100644 index 0000000..9bb4608 --- /dev/null +++ b/src/imports/location/qdeclarativegeoroute_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOROUTE_H +#define QDECLARATIVEGEOROUTE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeoroutesegment_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoRoute : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QGeoRectangle bounds READ bounds CONSTANT) + Q_PROPERTY(int travelTime READ travelTime CONSTANT) + Q_PROPERTY(qreal distance READ distance CONSTANT) + Q_PROPERTY(QJSValue path READ path WRITE setPath NOTIFY pathChanged) + Q_PROPERTY(QQmlListProperty segments READ segments CONSTANT) + +public: + explicit QDeclarativeGeoRoute(QObject *parent = 0); + QDeclarativeGeoRoute(const QGeoRoute &route, QObject *parent = 0); + ~QDeclarativeGeoRoute(); + + QGeoRectangle bounds() const; + int travelTime() const; + qreal distance() const; + + QJSValue path() const; + void setPath(const QJSValue &value); + + QQmlListProperty segments(); + + void appendSegment(QDeclarativeGeoRouteSegment *segment); + void clearSegments(); + +Q_SIGNALS: + void pathChanged(); + +private: + static void segments_append(QQmlListProperty *prop, QDeclarativeGeoRouteSegment *segment); + static int segments_count(QQmlListProperty *prop); + static QDeclarativeGeoRouteSegment *segments_at(QQmlListProperty *prop, int index); + static void segments_clear(QQmlListProperty *prop); + + void init(); + QList routePath(); + + QGeoRoute route_; + QList segments_; + friend class QDeclarativeRouteMapItem; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/qdeclarativegeoroutemodel.cpp b/src/imports/location/qdeclarativegeoroutemodel.cpp new file mode 100644 index 0000000..0c64c23 --- /dev/null +++ b/src/imports/location/qdeclarativegeoroutemodel.cpp @@ -0,0 +1,1322 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeoroutemodel_p.h" +#include "qdeclarativegeoroute_p.h" +#include "error_messages.h" +#include "locationvaluetypehelper_p.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype RouteModel + \instantiates QDeclarativeGeoRouteModel + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-routing + \since Qt Location 5.5 + + \brief The RouteModel type provides access to routes. + + The RouteModel type is used as part of a model/view grouping to retrieve + geographic routes from a backend provider. Routes include data about driving + directions between two points, walking directions with multiple waypoints, + and various other similar concepts. It functions much like other Model + types in QML (see for example \l {Models and Views in Qt Quick#ListModel}{ListModel} and + \l XmlListModel), and interacts with views such as \l MapItemView, and \l{ListView}. + + Like \l Map and \l GeocodeModel, all the data for a RouteModel to work comes + from a services plugin. This is contained in the \l{plugin} property, and + this must be set before the RouteModel can do any useful work. + + Once the plugin is set, create a \l RouteQuery with the appropriate + waypoints and other settings, and set the RouteModel's \l{query} + property. If \l autoUpdate is enabled, the update will being automatically. + Otherwise, the \l{update} method may be used. By default, autoUpdate is + disabled. + + The data stored and returned in the RouteModel consists of \l Route objects, + as a list with the role name "routeData". See the documentation for \l Route + for further details on its structure and contents. + + \section2 Example Usage + + The following snippet is two-part, showing firstly the declaration of + objects, and secondly a short piece of procedural code using it. We set + the routeModel's \l{autoUpdate} property to false, and call \l{update} once + the query is set up, to avoid useless extra requests halfway through the + set up of the query. + + \code + Plugin { + id: aPlugin + name: "osm" + } + + RouteQuery { + id: aQuery + } + + RouteModel { + id: routeModel + plugin: aPlugin + query: aQuery + autoUpdate: false + } + \endcode + + \code + { + aQuery.addWaypoint(...) + aQuery.addWaypoint(...) + aQuery.travelModes = ... + routeModel.update() + } + \endcode + +*/ + +QDeclarativeGeoRouteModel::QDeclarativeGeoRouteModel(QObject *parent) + : QAbstractListModel(parent), + complete_(false), + plugin_(0), + routeQuery_(0), + reply_(0), + autoUpdate_(false), + status_(QDeclarativeGeoRouteModel::Null), + error_(QDeclarativeGeoRouteModel::NoError) +{ +} + +QDeclarativeGeoRouteModel::~QDeclarativeGeoRouteModel() +{ + if (!routes_.empty()) { + qDeleteAll(routes_); + routes_.clear(); + } + delete reply_; +} + +/*! + \qmlproperty int QtLocation::RouteModel::count + + This property holds how many routes the model currently has. + Amongst other uses, you can use this value when accessing routes + via the QtLocation::RouteModel::get -method. +*/ + +int QDeclarativeGeoRouteModel::count() const +{ + return routes_.count(); +} + +/*! + \qmlmethod void QtLocation::RouteModel::reset() + + Resets the model. All route data is cleared, any outstanding requests + are aborted and possible errors are cleared. Model status will be set + to RouteModel.Null +*/ + +void QDeclarativeGeoRouteModel::reset() +{ + if (!routes_.isEmpty()) { + beginResetModel(); + qDeleteAll(routes_); + routes_.clear(); + emit countChanged(); + emit routesChanged(); + endResetModel(); + } + + abortRequest(); + setError(NoError, QString()); + setStatus(QDeclarativeGeoRouteModel::Null); +} + +/*! + \qmlmethod void QtLocation::RouteModel::cancel() + + Cancels any outstanding requests and clears errors. Model status will be set to either + RouteModel.Null or RouteModel.Ready. +*/ +void QDeclarativeGeoRouteModel::cancel() +{ + abortRequest(); + setError(NoError, QString()); + setStatus(routes_.isEmpty() ? Null : Ready); +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::abortRequest() +{ + if (reply_) { + reply_->abort(); + reply_->deleteLater(); + reply_ = 0; + } +} + + +/*! + \qmlmethod void QtLocation::RouteModel::get(int) + + Returns the Route at given index. Use \l count property to check the + amount of routes available. The routes are indexed from zero, so the accessible range + is 0...(count - 1). + + If you access out of bounds, a zero (null object) is returned and a warning is issued. +*/ + +QDeclarativeGeoRoute *QDeclarativeGeoRouteModel::get(int index) +{ + if (index < 0 || index >= routes_.count()) { + qmlInfo(this) << QStringLiteral("Index '%1' out of range").arg(index); + return 0; + } + return routes_.at(index); +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::componentComplete() +{ + complete_ = true; + if (autoUpdate_) { + update(); + } +} + +/*! + \internal +*/ +int QDeclarativeGeoRouteModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return routes_.count(); +} + +/*! + \internal +*/ +QVariant QDeclarativeGeoRouteModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + qmlInfo(this) << QStringLiteral("Error in indexing route model's data (invalid index)."); + return QVariant(); + } + + if (index.row() >= routes_.count()) { + qmlInfo(this) << QStringLiteral("Fatal error in indexing route model's data (index overflow)."); + return QVariant(); + } + + if (role == RouteRole) { + QObject *route = routes_.at(index.row()); + return QVariant::fromValue(route); + } + return QVariant(); +} + +QHash QDeclarativeGeoRouteModel::roleNames() const +{ + QHash roleNames = QAbstractListModel::roleNames(); + roleNames.insert(RouteRole, "routeData"); + return roleNames; +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::setPlugin(QDeclarativeGeoServiceProvider *plugin) +{ + if (plugin_ == plugin) + return; + + reset(); // reset the model + + if (plugin_) + disconnect(plugin_, SIGNAL(localesChanged()), this, SIGNAL(measurementSystemChanged())); + if (plugin) + connect(plugin, SIGNAL(localesChanged()), this, SIGNAL(measurementSystemChanged())); + + plugin_ = plugin; + + if (complete_) + emit pluginChanged(); + + if (!plugin) + return; + + if (plugin_->isAttached()) { + pluginReady(); + } else { + connect(plugin_, SIGNAL(attached()), + this, SLOT(pluginReady())); + } +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::pluginReady() +{ + QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); + QGeoRoutingManager *routingManager = serviceProvider->routingManager(); + + if (serviceProvider->error() != QGeoServiceProvider::NoError) { + QDeclarativeGeoRouteModel::RouteError newError = UnknownError; + switch (serviceProvider->error()) { + case QGeoServiceProvider::NotSupportedError: + newError = EngineNotSetError; break; + case QGeoServiceProvider::UnknownParameterError: + newError = UnknownParameterError; break; + case QGeoServiceProvider::MissingRequiredParameterError: + newError = MissingRequiredParameterError; break; + case QGeoServiceProvider::ConnectionError: + newError = CommunicationError; break; + default: + break; + } + + setError(newError, serviceProvider->errorString()); + return; + } + + if (!routingManager) { + setError(EngineNotSetError, tr("Plugin does not support routing.")); + return; + } + + connect(routingManager, SIGNAL(finished(QGeoRouteReply*)), + this, SLOT(routingFinished(QGeoRouteReply*))); + connect(routingManager, SIGNAL(error(QGeoRouteReply*,QGeoRouteReply::Error,QString)), + this, SLOT(routingError(QGeoRouteReply*,QGeoRouteReply::Error,QString))); +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::queryDetailsChanged() +{ + if (autoUpdate_ && complete_) + update(); +} + +/*! + \qmlproperty Plugin QtLocation::RouteModel::plugin + + This property holds the plugin that providers the actual + routing service. Note that all plugins do not necessarily + provide routing (could for example provide only geocoding or maps). + + A valid plugin must be set before the RouteModel can perform any useful + operations. + + \sa Plugin +*/ + +QDeclarativeGeoServiceProvider *QDeclarativeGeoRouteModel::plugin() const +{ + return plugin_; +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::setQuery(QDeclarativeGeoRouteQuery *query) +{ + if (!query || query == routeQuery_) + return; + if (routeQuery_) + routeQuery_->disconnect(this); + routeQuery_ = query; + connect(query, SIGNAL(queryDetailsChanged()), this, SLOT(queryDetailsChanged())); + if (complete_) { + emit queryChanged(); + if (autoUpdate_) + update(); + } +} + +/*! + \qmlproperty RouteQuery QtLocation::RouteModel::query + + This property holds the data of the route request. + The primary data are the waypoint coordinates and possible further + preferences (means of traveling, things to avoid on route etc). +*/ + +QDeclarativeGeoRouteQuery *QDeclarativeGeoRouteModel::query() const +{ + return routeQuery_; +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::setAutoUpdate(bool autoUpdate) +{ + if (autoUpdate_ == autoUpdate) + return; + autoUpdate_ = autoUpdate; + if (complete_) + emit autoUpdateChanged(); +} + +/*! + \qmlproperty bool QtLocation::RouteModel::autoUpdate + + This property controls whether the Model automatically updates in response + to changes in its attached RouteQuery. The default value of this property + is false. + + If setting this value to 'true', note that any change at all in + the RouteQuery object set in the \l{query} property will trigger a new + request to be sent. If you are adjusting many properties of the RouteQuery + with autoUpdate enabled, this can generate large numbers of useless (and + later discarded) requests. +*/ + +bool QDeclarativeGeoRouteModel::autoUpdate() const +{ + return autoUpdate_; +} + +/*! + \qmlproperty Locale::MeasurementSystem QtLocation::RouteModel::measurementSystem + + This property holds the measurement system which will be used when calculating the route. This + property is changed when the \l {QtLocation::Plugin::locales}{Plugin::locales} property of + \l {QtLocation::RouteModel::plugin}{plugin} changes. + + If setting this property it must be set after the \l {QtLocation::RouteModel::plugin}{plugin} + property is set. +*/ +void QDeclarativeGeoRouteModel::setMeasurementSystem(QLocale::MeasurementSystem ms) +{ + if (!plugin_) + return; + + QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); + if (!serviceProvider) + return; + + QGeoRoutingManager *routingManager = serviceProvider->routingManager(); + if (!routingManager) + return; + + if (routingManager->measurementSystem() == ms) + return; + + routingManager->setMeasurementSystem(ms); + emit measurementSystemChanged(); +} + +QLocale::MeasurementSystem QDeclarativeGeoRouteModel::measurementSystem() const +{ + if (!plugin_) + return QLocale().measurementSystem(); + + QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); + if (!serviceProvider) { + if (plugin_->locales().isEmpty()) + return QLocale().measurementSystem(); + + return QLocale(plugin_->locales().first()).measurementSystem(); + } + + QGeoRoutingManager *routingManager = serviceProvider->routingManager(); + if (!routingManager) { + if (plugin_->locales().isEmpty()) + return QLocale().measurementSystem(); + + return QLocale(plugin_->locales().first()).measurementSystem(); + } + + return routingManager->measurementSystem(); +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::setStatus(QDeclarativeGeoRouteModel::Status status) +{ + if (status_ == status) + return; + + status_ = status; + + if (complete_) + emit statusChanged(); +} + +/*! + \qmlproperty enumeration QtLocation::RouteModel::status + + This read-only property holds the current status of the model. + + \list + \li RouteModel.Null - No route requests have been issued or \l reset has been called. + \li RouteModel.Ready - Route request(s) have finished successfully. + \li RouteModel.Loading - Route request has been issued but not yet finished + \li RouteModel.Error - Routing error has occurred, details are in \l error and \l errorString + \endlist +*/ + +QDeclarativeGeoRouteModel::Status QDeclarativeGeoRouteModel::status() const +{ + return status_; +} + +/*! + \qmlproperty string QtLocation::RouteModel::errorString + + This read-only property holds the textual presentation of the latest routing error. + If no error has occurred or the model has been reset, an empty string is returned. + + An empty string may also be returned if an error occurred which has no associated + textual representation. +*/ + +QString QDeclarativeGeoRouteModel::errorString() const +{ + return errorString_; +} + +/*! + \qmlproperty enumeration QtLocation::RouteModel::error + + This read-only property holds the latest error value of the routing request. + + \list + \li RouteModel.NoError - No error has occurred. + \li RouteModel.CommunicationError - An error occurred while communicating with the service provider. + \li RouteModel.EngineNotSetError - The model's plugin property was not set or there is no routing manager associated with the plugin. + \li RouteModel.MissingRequiredParameterError - A required parameter was not specified. + \li RouteModel.ParseError - The response from the service provider was in an unrecognizable format. + \li RouteModel.UnknownError - An error occurred which does not fit into any of the other categories. + \li RouteModel.UnknownParameterError - The plugin did not recognize one of the parameters it was given. + \li RouteModel.UnsupportedOptionError - The requested operation is not supported by the routing provider. + This may happen when the loaded engine does not support a particular + type of routing request. + \endlist +*/ + +QDeclarativeGeoRouteModel::RouteError QDeclarativeGeoRouteModel::error() const +{ + return error_; +} + +void QDeclarativeGeoRouteModel::setError(RouteError error, const QString& errorString) +{ + if (error_ == error && errorString_ == errorString) + return; + error_ = error; + errorString_ = errorString; + emit errorChanged(); +} + +/*! + \qmlmethod void QtLocation::RouteModel::update() + + Instructs the RouteModel to update its data. This is most useful + when \l autoUpdate is disabled, to force a refresh when the query + has been changed. +*/ +void QDeclarativeGeoRouteModel::update() +{ + if (!complete_) + return; + + if (!plugin_) { + setError(EngineNotSetError, tr("Cannot route, plugin not set.")); + return; + } + + QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); + if (!serviceProvider) + return; + + QGeoRoutingManager *routingManager = serviceProvider->routingManager(); + if (!routingManager) { + setError(EngineNotSetError, tr("Cannot route, route manager not set.")); + return; + } + if (!routeQuery_) { + setError(ParseError,"Cannot route, valid query not set."); + return; + } + abortRequest(); // Clear previus requests + QGeoRouteRequest request = routeQuery_->routeRequest(); + if (request.waypoints().count() < 2) { + setError(ParseError,tr("Not enough waypoints for routing.")); + return; + } + + setError(NoError, QString()); + + reply_ = routingManager->calculateRoute(request); + setStatus(QDeclarativeGeoRouteModel::Loading); + if (reply_->isFinished()) { + if (reply_->error() == QGeoRouteReply::NoError) { + routingFinished(reply_); + } else { + routingError(reply_, reply_->error(), reply_->errorString()); + } + } +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::routingFinished(QGeoRouteReply *reply) +{ + if (reply != reply_ || reply->error() != QGeoRouteReply::NoError) + return; + + beginResetModel(); + int oldCount = routes_.count(); + qDeleteAll(routes_); + // Convert routes to declarative + routes_.clear(); + for (int i = 0; i < reply->routes().size(); ++i) { + QDeclarativeGeoRoute *route = new QDeclarativeGeoRoute(reply->routes().at(i), this); + QQmlEngine::setContextForObject(route, QQmlEngine::contextForObject(this)); + routes_.append(route); + } + endResetModel(); + + setError(NoError, QString()); + setStatus(QDeclarativeGeoRouteModel::Ready); + + reply->deleteLater(); + reply_ = 0; + + if (oldCount != 0 || routes_.count() != 0) + emit routesChanged(); + if (oldCount != routes_.count()) + emit countChanged(); +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteModel::routingError(QGeoRouteReply *reply, + QGeoRouteReply::Error error, + const QString &errorString) +{ + if (reply != reply_) + return; + setError(static_cast(error), errorString); + setStatus(QDeclarativeGeoRouteModel::Error); + reply->deleteLater(); + reply_ = 0; +} + + +/*! + \qmltype RouteQuery + \instantiates QDeclarativeGeoRouteQuery + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-routing + \since Qt Location 5.5 + + \brief The RouteQuery type is used to provide query parameters to a + RouteModel. + + A RouteQuery contains all the parameters necessary to make a request + to a routing service, which can then populate the contents of a RouteModel. + + These parameters describe key details of the route, such as \l waypoints to + pass through, \l excludedAreas to avoid, the \l travelModes in use, as well + as detailed preferences on how to optimize the route and what features + to prefer or avoid along the path (such as toll roads, highways, etc). + + RouteQuery objects are used exclusively to fill out the value of a + RouteModel's \l{RouteModel::query}{query} property, which can then begin + the retrieval process to populate the model. + + \section2 Example Usage + + The following snipped shows an incomplete example of creating a RouteQuery + object and setting it as the value of a RouteModel's \l{RouteModel::query}{query} + property. + + \code + RouteQuery { + id: aQuery + } + + RouteModel { + query: aQuery + autoUpdate: false + } + \endcode + + For a more complete example, see the documentation for the \l{RouteModel} + type, and the Mapviewer example. + + \sa RouteModel + +*/ + +QDeclarativeGeoRouteQuery::QDeclarativeGeoRouteQuery(QObject *parent) +: QObject(parent), complete_(false), m_excludedAreaCoordinateChanged(false) +{ +} + +QDeclarativeGeoRouteQuery::~QDeclarativeGeoRouteQuery() +{ +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteQuery::componentComplete() +{ + complete_ = true; +} + +/*! + \qmlproperty QList RouteQuery::featureTypes + + List of features that will be considered when planning the + route. Features with a weight of NeutralFeatureWeight will not be returned. + + \list + \li RouteQuery.NoFeature - No features will be taken into account when planning the route + \li RouteQuery.TollFeature - Consider tollways when planning the route + \li RouteQuery.HighwayFeature - Consider highways when planning the route + \li RouteQuery.PublicTransitFeature - Consider public transit when planning the route + \li RouteQuery.FerryFeature - Consider ferries when planning the route + \li RouteQuery.TunnelFeature - Consider tunnels when planning the route + \li RouteQuery.DirtRoadFeature - Consider dirt roads when planning the route + \li RouteQuery.ParksFeature - Consider parks when planning the route + \li RouteQuery.MotorPoolLaneFeature - Consider motor pool lanes when planning the route + \endlist + + \sa setFeatureWeight, featureWeight +*/ + +QList QDeclarativeGeoRouteQuery::featureTypes() +{ + QList list; + + for (int i = 0; i < request_.featureTypes().count(); ++i) { + list.append(static_cast(request_.featureTypes().at(i))); + } + return list; +} + +/*! + \qmlproperty int RouteQuery::numberAlternativeRoutes + + The number of alternative routes requested when requesting routes. + The default value is 0. +*/ + + +int QDeclarativeGeoRouteQuery::numberAlternativeRoutes() const +{ + return request_.numberAlternativeRoutes(); +} + +void QDeclarativeGeoRouteQuery::setNumberAlternativeRoutes(int numberAlternativeRoutes) +{ + if (numberAlternativeRoutes == request_.numberAlternativeRoutes()) + return; + + request_.setNumberAlternativeRoutes(numberAlternativeRoutes); + + if (complete_) { + emit numberAlternativeRoutesChanged(); + emit queryDetailsChanged(); + } +} + +/*! + \qmlproperty QJSValue RouteQuery::waypoints + + + The waypoint coordinates of the desired route. + The waypoints should be given in order from origin to destination. + Two or more coordinates are needed. + + Waypoints can be set as part of the RouteQuery type declaration or + dynamically with the functions provided. + + \sa addWaypoint, removeWaypoint, clearWaypoints +*/ + +QJSValue QDeclarativeGeoRouteQuery::waypoints() +{ + QQmlContext *context = QQmlEngine::contextForObject(parent()); + QQmlEngine *engine = context->engine(); + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); + + QV4::Scope scope(v4); + QV4::Scoped waypointArray(scope, v4->newArrayObject(request_.waypoints().length())); + for (int i = 0; i < request_.waypoints().length(); ++i) { + const QGeoCoordinate &c = request_.waypoints().at(i); + + QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(c))); + waypointArray->putIndexed(i, cv); + } + + return QJSValue(v4, waypointArray.asReturnedValue()); +} + +void QDeclarativeGeoRouteQuery::setWaypoints(const QJSValue &value) +{ + if (!value.isArray()) + return; + + QList waypointList; + quint32 length = value.property(QStringLiteral("length")).toUInt(); + for (quint32 i = 0; i < length; ++i) { + bool ok; + QGeoCoordinate c = parseCoordinate(value.property(i), &ok); + + if (!ok || !c.isValid()) { + qmlInfo(this) << "Unsupported waypoint type"; + return; + } + + waypointList.append(c); + } + + if (request_.waypoints() == waypointList) + return; + + request_.setWaypoints(waypointList); + + emit waypointsChanged(); + emit queryDetailsChanged(); +} + +/*! + \qmlproperty list RouteQuery::excludedAreas + + Areas that the route must not cross. + + Excluded areas can be set as part of the \l RouteQuery type declaration or + dynamically with the functions provided. + + \sa addExcludedArea, removeExcludedArea, clearExcludedAreas +*/ +QJSValue QDeclarativeGeoRouteQuery::excludedAreas() const +{ + QQmlContext *context = QQmlEngine::contextForObject(parent()); + QQmlEngine *engine = context->engine(); + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); + + QV4::Scope scope(v4); + QV4::Scoped excludedAreasArray(scope, v4->newArrayObject(request_.excludeAreas().length())); + for (int i = 0; i < request_.excludeAreas().length(); ++i) { + const QGeoRectangle &r = request_.excludeAreas().at(i); + + QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(r))); + excludedAreasArray->putIndexed(i, cv); + } + + return QJSValue(v4, excludedAreasArray.asReturnedValue()); +} + +void QDeclarativeGeoRouteQuery::setExcludedAreas(const QJSValue &value) +{ + if (!value.isArray()) + return; + + QList excludedAreasList; + quint32 length = value.property(QStringLiteral("length")).toUInt(); + for (quint32 i = 0; i < length; ++i) { + bool ok; + QGeoRectangle r = parseRectangle(value.property(i), &ok); + + if (!ok || !r.isValid()) { + qmlInfo(this) << "Unsupported area type"; + return; + } + + excludedAreasList.append(r); + } + + if (request_.excludeAreas() == excludedAreasList) + return; + + request_.setExcludeAreas(excludedAreasList); + + emit excludedAreasChanged(); + emit queryDetailsChanged(); +} + +/*! + \qmlmethod void QtLocation::RouteQuery::addExcludedArea(georectangle) + + Adds the given area to excluded areas (areas that the route must not cross). + Same area can only be added once. + + \sa removeExcludedArea, clearExcludedAreas +*/ + + +void QDeclarativeGeoRouteQuery::addExcludedArea(const QGeoRectangle &area) +{ + if (!area.isValid()) + return; + + QList excludedAreas = request_.excludeAreas(); + + if (excludedAreas.contains(area)) + return; + + excludedAreas.append(area); + + request_.setExcludeAreas(excludedAreas); + + if (complete_) { + emit excludedAreasChanged(); + emit queryDetailsChanged(); + } +} + +/*! + \qmlmethod void QtLocation::RouteQuery::removeExcludedArea(georectangle) + + Removes the given area to excluded areas (areas that the route must not cross). + + \sa addExcludedArea, clearExcludedAreas +*/ + +void QDeclarativeGeoRouteQuery::removeExcludedArea(const QGeoRectangle &area) +{ + if (!area.isValid()) + return; + + QList excludedAreas = request_.excludeAreas(); + + int index = excludedAreas.lastIndexOf(area); + if (index == -1) { + qmlInfo(this) << QStringLiteral("Cannot remove nonexistent area."); + return; + } + excludedAreas.removeAt(index); + request_.setExcludeAreas(excludedAreas); + + emit excludedAreasChanged(); + emit queryDetailsChanged(); +} + +/*! + \qmlmethod void QtLocation::RouteQuery::clearExcludedAreas() + + Clears all excluded areas (areas that the route must not cross). + + \sa addExcludedArea, removeExcludedArea +*/ + +void QDeclarativeGeoRouteQuery::clearExcludedAreas() +{ + if (request_.excludeAreas().isEmpty()) + return; + + request_.setExcludeAreas(QList()); + + emit excludedAreasChanged(); + emit queryDetailsChanged(); +} + +/*! + \qmlmethod void QtLocation::RouteQuery::addWaypoint(coordinate) + + Appends a coordinate to the list of waypoints. Same coordinate + can be set multiple times. + + \sa removeWaypoint, clearWaypoints +*/ +void QDeclarativeGeoRouteQuery::addWaypoint(const QGeoCoordinate &waypoint) +{ + if (!waypoint.isValid()) { + qmlInfo(this) << QStringLiteral("Not adding invalid waypoint."); + return; + } + + QList waypoints = request_.waypoints(); + waypoints.append(waypoint); + request_.setWaypoints(waypoints); + + if (complete_) { + emit waypointsChanged(); + emit queryDetailsChanged(); + } +} + +/*! + \qmlmethod void QtLocation::RouteQuery::removeWaypoint(coordinate) + + Removes the given from the list of waypoints. In case same coordinate + appears multiple times, the most recently added coordinate instance is + removed. + + \sa addWaypoint, clearWaypoints +*/ +void QDeclarativeGeoRouteQuery::removeWaypoint(const QGeoCoordinate &waypoint) +{ + QList waypoints = request_.waypoints(); + + int index = waypoints.lastIndexOf(waypoint); + if (index == -1) { + qmlInfo(this) << QStringLiteral("Cannot remove nonexistent waypoint."); + return; + } + + waypoints.removeAt(index); + + request_.setWaypoints(waypoints); + + emit waypointsChanged(); + emit queryDetailsChanged(); +} + +/*! + \qmlmethod void QtLocation::RouteQuery::clearWaypoints() + + Clears all waypoints. + + \sa removeWaypoint, addWaypoint +*/ +void QDeclarativeGeoRouteQuery::clearWaypoints() +{ + if (request_.waypoints().isEmpty()) + return; + + request_.setWaypoints(QList()); + + emit waypointsChanged(); + emit queryDetailsChanged(); +} + +/*! + \qmlmethod void QtLocation::RouteQuery::setFeatureWeight(FeatureType, FeatureWeight) + + Defines the weight to associate with a feature during the planning of a + route. + + Following lists the possible feature weights: + + \list + \li RouteQuery.NeutralFeatureWeight - The presence or absence of the feature will not affect the planning of the route + \li RouteQuery.PreferFeatureWeight - Routes which contain the feature will be preferred over those that do not + \li RouteQuery.RequireFeatureWeight - Only routes which contain the feature will be considered, otherwise no route will be returned + \li RouteQuery.AvoidFeatureWeight - Routes which do not contain the feature will be preferred over those that do + \li RouteQuery.DisallowFeatureWeight - Only routes which do not contain the feature will be considered, otherwise no route will be returned + \endlist + + \sa featureTypes, resetFeatureWeights, featureWeight + +*/ + +void QDeclarativeGeoRouteQuery::setFeatureWeight(FeatureType featureType, FeatureWeight featureWeight) +{ + if (featureType == NoFeature && !request_.featureTypes().isEmpty()) { + resetFeatureWeights(); + return; + } + + // Check if the weight changes, as we need to signal it + FeatureWeight originalWeight = static_cast(request_.featureWeight(static_cast(featureType))); + if (featureWeight == originalWeight) + return; + + request_.setFeatureWeight(static_cast(featureType), + static_cast(featureWeight)); + if (complete_ && ((originalWeight == NeutralFeatureWeight) || (featureWeight == NeutralFeatureWeight))) { + // featureTypes should now give a different list, because the original and new weight + // were not same, and other one was neutral weight + emit featureTypesChanged(); + emit queryDetailsChanged(); + } +} + +/*! + \qmlmethod void QtLocation::RouteQuery::resetFeatureWeights() + + Resets all feature weights to their default state (NeutralFeatureWeight). + + \sa featureTypes, setFeatureWeight, featureWeight +*/ +void QDeclarativeGeoRouteQuery::resetFeatureWeights() +{ + // reset all feature types. + QList featureTypes = request_.featureTypes(); + for (int i = 0; i < featureTypes.count(); ++i) { + request_.setFeatureWeight(featureTypes.at(i), QGeoRouteRequest::NeutralFeatureWeight); + } + if (complete_) { + emit featureTypesChanged(); + emit queryDetailsChanged(); + } +} + +/*! + \qmlmethod FeatureWeight QtLocation::RouteQuery::featureWeight(FeatureType featureType) + + Gets the weight for the \a featureType. + + \sa featureTypes, setFeatureWeight, resetFeatureWeights +*/ + +int QDeclarativeGeoRouteQuery::featureWeight(FeatureType featureType) +{ + return request_.featureWeight(static_cast(featureType)); +} + +/*! + \internal +*/ +void QDeclarativeGeoRouteQuery::setTravelModes(QDeclarativeGeoRouteQuery::TravelModes travelModes) +{ + QGeoRouteRequest::TravelModes reqTravelModes; + + if (travelModes & QDeclarativeGeoRouteQuery::CarTravel) + reqTravelModes |= QGeoRouteRequest::CarTravel; + if (travelModes & QDeclarativeGeoRouteQuery::PedestrianTravel) + reqTravelModes |= QGeoRouteRequest::PedestrianTravel; + if (travelModes & QDeclarativeGeoRouteQuery::BicycleTravel) + reqTravelModes |= QGeoRouteRequest::BicycleTravel; + if (travelModes & QDeclarativeGeoRouteQuery::PublicTransitTravel) + reqTravelModes |= QGeoRouteRequest::PublicTransitTravel; + if (travelModes & QDeclarativeGeoRouteQuery::TruckTravel) + reqTravelModes |= QGeoRouteRequest::TruckTravel; + + if (reqTravelModes == request_.travelModes()) + return; + + request_.setTravelModes(reqTravelModes); + + if (complete_) { + emit travelModesChanged(); + emit queryDetailsChanged(); + } +} + + +/*! + \qmlproperty enumeration RouteQuery::segmentDetail + + The level of detail which will be used in the representation of routing segments. + + \list + \li RouteQuery.NoSegmentData - No segment data should be included with the route + \li RouteQuery.BasicSegmentData - Basic segment data will be included with the route + \endlist + + The default value is RouteQuery.BasicSegmentData +*/ + +void QDeclarativeGeoRouteQuery::setSegmentDetail(SegmentDetail segmentDetail) +{ + if (static_cast(segmentDetail) == request_.segmentDetail()) + return; + request_.setSegmentDetail(static_cast(segmentDetail)); + if (complete_) { + emit segmentDetailChanged(); + emit queryDetailsChanged(); + } +} + +QDeclarativeGeoRouteQuery::SegmentDetail QDeclarativeGeoRouteQuery::segmentDetail() const +{ + return static_cast(request_.segmentDetail()); +} + +/*! + \qmlproperty enumeration RouteQuery::maneuverDetail + + The level of detail which will be used in the representation of routing maneuvers. + + \list + \li RouteQuery.NoManeuvers - No maneuvers should be included with the route + \li RouteQuery.BasicManeuvers - Basic maneuvers will be included with the route + \endlist + + The default value is RouteQuery.BasicManeuvers +*/ + +void QDeclarativeGeoRouteQuery::setManeuverDetail(ManeuverDetail maneuverDetail) +{ + if (static_cast(maneuverDetail) == request_.maneuverDetail()) + return; + request_.setManeuverDetail(static_cast(maneuverDetail)); + if (complete_) { + emit maneuverDetailChanged(); + emit queryDetailsChanged(); + } +} + +QDeclarativeGeoRouteQuery::ManeuverDetail QDeclarativeGeoRouteQuery::maneuverDetail() const +{ + return static_cast(request_.maneuverDetail()); +} + +/*! + \qmlproperty enumeration RouteQuery::travelModes + + The travel modes which should be considered during the planning of the route. + Values can be combined with OR ('|') -operator. + + \list + \li RouteQuery.CarTravel - The route will be optimized for someone who is driving a car + \li RouteQuery.PedestrianTravel - The route will be optimized for someone who is walking + \li RouteQuery.BicycleTravel - The route will be optimized for someone who is riding a bicycle + \li RouteQuery.PublicTransitTravel - The route will be optimized for someone who is making use of public transit + \li RouteQuery.TruckTravel - The route will be optimized for someone who is driving a truck + \endlist + + The default value is RouteQuery.CarTravel +*/ + +QDeclarativeGeoRouteQuery::TravelModes QDeclarativeGeoRouteQuery::travelModes() const +{ + QGeoRouteRequest::TravelModes reqTravelModes = request_.travelModes(); + QDeclarativeGeoRouteQuery::TravelModes travelModes; + + if (reqTravelModes & QGeoRouteRequest::CarTravel) + travelModes |= QDeclarativeGeoRouteQuery::CarTravel; + if (reqTravelModes & QGeoRouteRequest::PedestrianTravel) + travelModes |= QDeclarativeGeoRouteQuery::PedestrianTravel; + if (reqTravelModes & QGeoRouteRequest::BicycleTravel) + travelModes |= QDeclarativeGeoRouteQuery::BicycleTravel; + if (reqTravelModes & QGeoRouteRequest::PublicTransitTravel) + travelModes |= QDeclarativeGeoRouteQuery::PublicTransitTravel; + if (reqTravelModes & QGeoRouteRequest::TruckTravel) + travelModes |= QDeclarativeGeoRouteQuery::TruckTravel; + + return travelModes; +} + +/*! + \qmlproperty enumeration RouteQuery::routeOptimizations + + The route optimizations which should be considered during the planning of the route. + Values can be combined with OR ('|') -operator. + + \list + \li RouteQuery.ShortestRoute - Minimize the length of the journey + \li RouteQuery.FastestRoute - Minimize the traveling time for the journey + \li RouteQuery.MostEconomicRoute - Minimize the cost of the journey + \li RouteQuery.MostScenicRoute - Maximize the scenic potential of the journey + \endlist + + The default value is RouteQuery.FastestRoute +*/ + +QDeclarativeGeoRouteQuery::RouteOptimizations QDeclarativeGeoRouteQuery::routeOptimizations() const +{ + QGeoRouteRequest::RouteOptimizations reqOptimizations = request_.routeOptimization(); + QDeclarativeGeoRouteQuery::RouteOptimizations optimization; + + if (reqOptimizations & QGeoRouteRequest::ShortestRoute) + optimization |= QDeclarativeGeoRouteQuery::ShortestRoute; + if (reqOptimizations & QGeoRouteRequest::FastestRoute) + optimization |= QDeclarativeGeoRouteQuery::FastestRoute; + if (reqOptimizations & QGeoRouteRequest::MostEconomicRoute) + optimization |= QDeclarativeGeoRouteQuery::MostEconomicRoute; + if (reqOptimizations & QGeoRouteRequest::MostScenicRoute) + optimization |= QDeclarativeGeoRouteQuery::MostScenicRoute; + + return optimization; +} + +void QDeclarativeGeoRouteQuery::setRouteOptimizations(QDeclarativeGeoRouteQuery::RouteOptimizations optimization) +{ + QGeoRouteRequest::RouteOptimizations reqOptimizations; + + if (optimization & QDeclarativeGeoRouteQuery::ShortestRoute) + reqOptimizations |= QGeoRouteRequest::ShortestRoute; + if (optimization & QDeclarativeGeoRouteQuery::FastestRoute) + reqOptimizations |= QGeoRouteRequest::FastestRoute; + if (optimization & QDeclarativeGeoRouteQuery::MostEconomicRoute) + reqOptimizations |= QGeoRouteRequest::MostEconomicRoute; + if (optimization & QDeclarativeGeoRouteQuery::MostScenicRoute) + reqOptimizations |= QGeoRouteRequest::MostScenicRoute; + + if (reqOptimizations == request_.routeOptimization()) + return; + + request_.setRouteOptimization(reqOptimizations); + + if (complete_) { + emit routeOptimizationsChanged(); + emit queryDetailsChanged(); + } +} + +/*! + \internal +*/ +QGeoRouteRequest QDeclarativeGeoRouteQuery::routeRequest() const +{ + return request_; +} + +void QDeclarativeGeoRouteQuery::excludedAreaCoordinateChanged() +{ + if (!m_excludedAreaCoordinateChanged) { + m_excludedAreaCoordinateChanged = true; + QMetaObject::invokeMethod(this, "doCoordinateChanged", Qt::QueuedConnection); + } +} + +void QDeclarativeGeoRouteQuery::doCoordinateChanged() +{ + m_excludedAreaCoordinateChanged = false; + emit queryDetailsChanged(); +} + +#include "moc_qdeclarativegeoroutemodel_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeoroutemodel_p.h b/src/imports/location/qdeclarativegeoroutemodel_p.h new file mode 100644 index 0000000..66769ea --- /dev/null +++ b/src/imports/location/qdeclarativegeoroutemodel_p.h @@ -0,0 +1,344 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOROUTEMODEL_H +#define QDECLARATIVEGEOROUTEMODEL_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeoserviceprovider_p.h" + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoServiceProvider; +class QGeoRoutingManager; +class QDeclarativeGeoRoute; +class QDeclarativeGeoRouteQuery; + +class QDeclarativeGeoRouteModel : public QAbstractListModel, public QQmlParserStatus +{ + Q_OBJECT + Q_ENUMS(Status) + Q_ENUMS(RouteError) + + Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) + Q_PROPERTY(QDeclarativeGeoRouteQuery *query READ query WRITE setQuery NOTIFY queryChanged) + Q_PROPERTY(int count READ count NOTIFY countChanged) + Q_PROPERTY(bool autoUpdate READ autoUpdate WRITE setAutoUpdate NOTIFY autoUpdateChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) + Q_PROPERTY(RouteError error READ error NOTIFY errorChanged) + Q_PROPERTY(QLocale::MeasurementSystem measurementSystem READ measurementSystem WRITE setMeasurementSystem NOTIFY measurementSystemChanged) + + Q_INTERFACES(QQmlParserStatus) + +public: + enum Roles { + RouteRole = Qt::UserRole + 500 + }; + + enum Status { + Null, + Ready, + Loading, + Error + }; + + enum RouteError { + NoError = QGeoRouteReply::NoError, + EngineNotSetError = QGeoRouteReply::EngineNotSetError, + CommunicationError = QGeoRouteReply::CommunicationError, + ParseError = QGeoRouteReply::ParseError, + UnsupportedOptionError = QGeoRouteReply::UnsupportedOptionError, + UnknownError = QGeoRouteReply::UnknownError, + //we leave gap for future QGeoRouteReply errors + + //QGeoServiceProvider related errors start here + UnknownParameterError = 100, + MissingRequiredParameterError + }; + + explicit QDeclarativeGeoRouteModel(QObject *parent = 0); + ~QDeclarativeGeoRouteModel(); + + // From QQmlParserStatus + void classBegin() {} + void componentComplete(); + + // From QAbstractListModel + int rowCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + virtual QHash roleNames() const; + + void setPlugin(QDeclarativeGeoServiceProvider *plugin); + QDeclarativeGeoServiceProvider *plugin() const; + + void setQuery(QDeclarativeGeoRouteQuery *query); + QDeclarativeGeoRouteQuery *query() const; + + void setAutoUpdate(bool autoUpdate); + bool autoUpdate() const; + + void setMeasurementSystem(QLocale::MeasurementSystem ms); + QLocale::MeasurementSystem measurementSystem() const; + + Status status() const; + QString errorString() const; + RouteError error() const; + + int count() const; + Q_INVOKABLE QDeclarativeGeoRoute *get(int index); + Q_INVOKABLE void reset(); + Q_INVOKABLE void cancel(); + +Q_SIGNALS: + void countChanged(); + void pluginChanged(); + void queryChanged(); + void autoUpdateChanged(); + void statusChanged(); + void errorChanged(); //emitted also for errorString notification + void routesChanged(); + void measurementSystemChanged(); + +public Q_SLOTS: + void update(); + +private Q_SLOTS: + void routingFinished(QGeoRouteReply *reply); + void routingError(QGeoRouteReply *reply, + QGeoRouteReply::Error error, + const QString &errorString); + void queryDetailsChanged(); + void pluginReady(); + +private: + void setStatus(Status status); + void setError(RouteError error, const QString &errorString); + void abortRequest(); + + bool complete_; + + QDeclarativeGeoServiceProvider *plugin_; + QDeclarativeGeoRouteQuery *routeQuery_; + QGeoRouteReply *reply_; + + QList routes_; + bool autoUpdate_; + Status status_; + QString errorString_; + RouteError error_; +}; + +class QDeclarativeGeoRouteQuery : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_ENUMS(TravelMode) + Q_ENUMS(FeatureType) + Q_ENUMS(FeatureWeight) + Q_ENUMS(SegmentDetail) + Q_ENUMS(ManeuverDetail) + Q_ENUMS(RouteOptimization) + Q_FLAGS(RouteOptimizations) + Q_FLAGS(ManeuverDetails) + Q_FLAGS(SegmentDetails) + Q_FLAGS(TravelModes) + + Q_PROPERTY(int numberAlternativeRoutes READ numberAlternativeRoutes WRITE setNumberAlternativeRoutes NOTIFY numberAlternativeRoutesChanged) + Q_PROPERTY(TravelModes travelModes READ travelModes WRITE setTravelModes NOTIFY travelModesChanged) + Q_PROPERTY(RouteOptimizations routeOptimizations READ routeOptimizations WRITE setRouteOptimizations NOTIFY routeOptimizationsChanged) + Q_PROPERTY(SegmentDetail segmentDetail READ segmentDetail WRITE setSegmentDetail NOTIFY segmentDetailChanged) + Q_PROPERTY(ManeuverDetail maneuverDetail READ maneuverDetail WRITE setManeuverDetail NOTIFY maneuverDetailChanged) + Q_PROPERTY(QJSValue waypoints READ waypoints WRITE setWaypoints NOTIFY waypointsChanged) + Q_PROPERTY(QJSValue excludedAreas READ excludedAreas WRITE setExcludedAreas NOTIFY excludedAreasChanged) + Q_PROPERTY(QList featureTypes READ featureTypes NOTIFY featureTypesChanged) + Q_INTERFACES(QQmlParserStatus) + +public: + + explicit QDeclarativeGeoRouteQuery(QObject *parent = 0); + ~QDeclarativeGeoRouteQuery(); + + // From QQmlParserStatus + void classBegin() {} + void componentComplete(); + + QGeoRouteRequest routeRequest() const; + + enum TravelMode { + CarTravel = QGeoRouteRequest::CarTravel, + PedestrianTravel = QGeoRouteRequest::PedestrianTravel, + BicycleTravel = QGeoRouteRequest::BicycleTravel, + PublicTransitTravel = QGeoRouteRequest::PublicTransitTravel, + TruckTravel = QGeoRouteRequest::TruckTravel + }; + Q_DECLARE_FLAGS(TravelModes, TravelMode) + + enum FeatureType { + NoFeature = QGeoRouteRequest::NoFeature, + TollFeature = QGeoRouteRequest::TollFeature, + HighwayFeature = QGeoRouteRequest::HighwayFeature, + PublicTransitFeature = QGeoRouteRequest::PublicTransitFeature, + FerryFeature = QGeoRouteRequest::FerryFeature, + TunnelFeature = QGeoRouteRequest::TunnelFeature, + DirtRoadFeature = QGeoRouteRequest::DirtRoadFeature, + ParksFeature = QGeoRouteRequest::ParksFeature, + MotorPoolLaneFeature = QGeoRouteRequest::MotorPoolLaneFeature + }; + Q_DECLARE_FLAGS(FeatureTypes, FeatureType) + + enum FeatureWeight { + NeutralFeatureWeight = QGeoRouteRequest::NeutralFeatureWeight, + PreferFeatureWeight = QGeoRouteRequest::PreferFeatureWeight, + RequireFeatureWeight = QGeoRouteRequest::RequireFeatureWeight, + AvoidFeatureWeight = QGeoRouteRequest::AvoidFeatureWeight, + DisallowFeatureWeight = QGeoRouteRequest::DisallowFeatureWeight + }; + Q_DECLARE_FLAGS(FeatureWeights, FeatureWeight) + + enum RouteOptimization { + ShortestRoute = QGeoRouteRequest::ShortestRoute, + FastestRoute = QGeoRouteRequest::FastestRoute, + MostEconomicRoute = QGeoRouteRequest::MostEconomicRoute, + MostScenicRoute = QGeoRouteRequest::MostScenicRoute + }; + Q_DECLARE_FLAGS(RouteOptimizations, RouteOptimization) + + enum SegmentDetail { + NoSegmentData = 0x0000, + BasicSegmentData = 0x0001 + }; + Q_DECLARE_FLAGS(SegmentDetails, SegmentDetail) + + enum ManeuverDetail { + NoManeuvers = 0x0000, + BasicManeuvers = 0x0001 + }; + Q_DECLARE_FLAGS(ManeuverDetails, ManeuverDetail) + + void setNumberAlternativeRoutes(int numberAlternativeRoutes); + int numberAlternativeRoutes() const; + + //QList featureTypes(); + QList featureTypes(); + + + QJSValue waypoints(); + void setWaypoints(const QJSValue &value); + + // READ functions for list properties + QJSValue excludedAreas() const; + void setExcludedAreas(const QJSValue &value); + + Q_INVOKABLE void addWaypoint(const QGeoCoordinate &waypoint); + Q_INVOKABLE void removeWaypoint(const QGeoCoordinate &waypoint); + Q_INVOKABLE void clearWaypoints(); + + Q_INVOKABLE void addExcludedArea(const QGeoRectangle &area); + Q_INVOKABLE void removeExcludedArea(const QGeoRectangle &area); + Q_INVOKABLE void clearExcludedAreas(); + + Q_INVOKABLE void setFeatureWeight(FeatureType featureType, FeatureWeight featureWeight); + Q_INVOKABLE int featureWeight(FeatureType featureType); + Q_INVOKABLE void resetFeatureWeights(); + + /* + feature weights + */ + + void setTravelModes(TravelModes travelModes); + TravelModes travelModes() const; + + void setSegmentDetail(SegmentDetail segmentDetail); + SegmentDetail segmentDetail() const; + + void setManeuverDetail(ManeuverDetail maneuverDetail); + ManeuverDetail maneuverDetail() const; + + void setRouteOptimizations(RouteOptimizations optimization); + RouteOptimizations routeOptimizations() const; + +Q_SIGNALS: + void numberAlternativeRoutesChanged(); + void travelModesChanged(); + void routeOptimizationsChanged(); + + void waypointsChanged(); + void excludedAreasChanged(); + + void featureTypesChanged(); + void maneuverDetailChanged(); + void segmentDetailChanged(); + + void queryDetailsChanged(); + +private Q_SLOTS: + void excludedAreaCoordinateChanged(); + +private: + Q_INVOKABLE void doCoordinateChanged(); + + QGeoRouteRequest request_; + bool complete_; + bool m_excludedAreaCoordinateChanged; + +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/qdeclarativegeoroutesegment.cpp b/src/imports/location/qdeclarativegeoroutesegment.cpp new file mode 100644 index 0000000..acfe244 --- /dev/null +++ b/src/imports/location/qdeclarativegeoroutesegment.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeoroutesegment_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype RouteSegment + \instantiates QDeclarativeGeoRouteSegment + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-routing + \since Qt Location 5.5 + + \brief The RouteSegment type represents a segment of a Route. + + A RouteSegment instance has information about the physical layout + of the route segment, the length of the route and estimated time required + to traverse the route segment and optional RouteManeuvers associated with + the end of the route segment. + + RouteSegment instances can be thought of as edges on a routing + graph, with RouteManeuver instances as optional labels attached to the + vertices of the graph. + + The primary means of acquiring Route objects is via Routes via \l RouteModel. + + \section1 Example + + The following QML snippet demonstrates how to print information about a + route segment: + + \snippet declarative/routing.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/routing.qml RouteSegment +*/ + +QDeclarativeGeoRouteSegment::QDeclarativeGeoRouteSegment(QObject *parent) + : QObject(parent) +{ + maneuver_ = new QDeclarativeGeoManeuver(this); +} + +QDeclarativeGeoRouteSegment::QDeclarativeGeoRouteSegment(const QGeoRouteSegment &segment, + QObject *parent) + : QObject(parent), + segment_(segment) +{ + maneuver_ = new QDeclarativeGeoManeuver(segment_.maneuver(), this); +} + +QDeclarativeGeoRouteSegment::~QDeclarativeGeoRouteSegment() {} + +/*! + \qmlproperty int QtLocation::RouteSegment::travelTime + + Read-only property which holds the estimated amount of time it will take to + traverse this segment, in seconds. + +*/ + +int QDeclarativeGeoRouteSegment::travelTime() const +{ + return segment_.travelTime(); +} + +/*! + \qmlproperty real QtLocation::RouteSegment::distance + + Read-only property which holds the distance covered by this segment of the route, in meters. + +*/ + +qreal QDeclarativeGeoRouteSegment::distance() const +{ + return segment_.distance(); +} + +/*! + \qmlproperty RouteManeuver QtLocation::RouteSegment::maneuver + + Read-only property which holds the maneuver for this route segment. + + Will return invalid maneuver if no information has been attached to the endpoint + of this route segment. +*/ + +QDeclarativeGeoManeuver *QDeclarativeGeoRouteSegment::maneuver() const +{ + return maneuver_; +} + +/*! + \qmlproperty QJSValue QtLocation::RouteSegment::path + + Read-only property which holds the geographical coordinates of this segment. + Coordinates are listed in the order in which they would be traversed by someone + traveling along this segment of the route. + + To access individual segments you can use standard list accessors: 'path.length' + indicates the number of objects and 'path[index starting from zero]' gives + the actual object. + + \sa QtPositioning::coordinate +*/ + +QJSValue QDeclarativeGeoRouteSegment::path() const +{ + QQmlContext *context = QQmlEngine::contextForObject(parent()); + QQmlEngine *engine = context->engine(); + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); + + QV4::Scope scope(v4); + QV4::Scoped pathArray(scope, v4->newArrayObject(segment_.path().length())); + for (int i = 0; i < segment_.path().length(); ++i) { + const QGeoCoordinate &c = segment_.path().at(i); + + QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(c))); + pathArray->putIndexed(i, cv); + } + + return QJSValue(v4, pathArray.asReturnedValue()); +} + +#include "moc_qdeclarativegeoroutesegment_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeoroutesegment_p.h b/src/imports/location/qdeclarativegeoroutesegment_p.h new file mode 100644 index 0000000..e6cf5aa --- /dev/null +++ b/src/imports/location/qdeclarativegeoroutesegment_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOROUTESEGMENT_H +#define QDECLARATIVEGEOROUTESEGMENT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeomaneuver_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoRouteSegment : public QObject +{ + Q_OBJECT + + Q_PROPERTY(int travelTime READ travelTime CONSTANT) + Q_PROPERTY(qreal distance READ distance CONSTANT) + Q_PROPERTY(QJSValue path READ path CONSTANT) + Q_PROPERTY(QDeclarativeGeoManeuver *maneuver READ maneuver CONSTANT) + +public: + explicit QDeclarativeGeoRouteSegment(QObject *parent = 0); + QDeclarativeGeoRouteSegment(const QGeoRouteSegment &segment, QObject *parent = 0); + ~QDeclarativeGeoRouteSegment(); + + int travelTime() const; + qreal distance() const; + QJSValue path() const; + QDeclarativeGeoManeuver *maneuver() const; + +private: + QGeoRouteSegment segment_; + QDeclarativeGeoManeuver *maneuver_; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/location/qdeclarativegeoserviceprovider.cpp b/src/imports/location/qdeclarativegeoserviceprovider.cpp new file mode 100644 index 0000000..5b655f7 --- /dev/null +++ b/src/imports/location/qdeclarativegeoserviceprovider.cpp @@ -0,0 +1,822 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeoserviceprovider_p.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Plugin + \instantiates QDeclarativeGeoServiceProvider + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-common + \since Qt Location 5.5 + + \brief The Plugin type describes a Location based services plugin. + + The Plugin type is used to declaratively specify which available + GeoServices plugin should be used for various tasks in the Location API. + Plugins are used by \l Map, \l RouteModel, and \l GeocodeModel + types, as well as a variety of others. + + Plugins recognized by the system have a \l name property, a simple string + normally indicating the name of the service that the Plugin retrieves + data from. They also have a variety of features, which can be test for using the + \l {supportsRouting()}, \l {supportsGeocoding()}, \l {supportsMapping()} and + \l {supportsPlaces()} methods. + + When a Plugin object is created, it is "detached" and not associated with + any actual service plugin. Once it has received information via setting + its \l name, \l preferred, or \l required properties, it will choose an + appropriate service plugin to attach to. Plugin objects can only be + attached once; to use multiple plugins, create multiple Plugin objects. + + \section2 Example Usage + + The following snippet shows a Plugin object being created with the + \l required and \l preferred properties set. This Plugin will attach to the + first found plugin that supports both mapping and geocoding, and will + prefer plugins named "here" or "osm" to any others. + + \code + Plugin { + id: plugin + preferred: ["here", "osm"] + required: Plugin.AnyMappingFeatures | Plugin.AnyGeocodingFeatures + } + \endcode +*/ + +QDeclarativeGeoServiceProvider::QDeclarativeGeoServiceProvider(QObject *parent) +: QObject(parent), + sharedProvider_(0), + required_(new QDeclarativeGeoServiceProviderRequirements), + complete_(false), + experimental_(false) +{ + locales_.append(QLocale().name()); +} + +QDeclarativeGeoServiceProvider::~QDeclarativeGeoServiceProvider() +{ + delete required_; + delete sharedProvider_; +} + + + +/*! + \qmlproperty string Plugin::name + + This property holds the name of the plugin. Setting this property + will cause the Plugin to only attach to a plugin with exactly this + name. The value of \l required will be ignored. +*/ +void QDeclarativeGeoServiceProvider::setName(const QString &name) +{ + if (name_ == name) + return; + + name_ = name; + delete sharedProvider_; + sharedProvider_ = new QGeoServiceProvider(name_, parameterMap()); + sharedProvider_->setLocale(locales_.at(0)); + sharedProvider_->setAllowExperimental(experimental_); + + emit nameChanged(name_); + emit attached(); +} + +QString QDeclarativeGeoServiceProvider::name() const +{ + return name_; +} + + +/*! + \qmlproperty stringlist Plugin::availableServiceProviders + + This property holds a list of all available service plugins' names. This + can be used to manually enumerate the available plugins if the + control provided by \l name and \l required is not sufficient for your + needs. +*/ +QStringList QDeclarativeGeoServiceProvider::availableServiceProviders() +{ + return QGeoServiceProvider::availableServiceProviders(); +} + +/*! + \internal +*/ +void QDeclarativeGeoServiceProvider::componentComplete() +{ + complete_ = true; + if (!name_.isEmpty()) { + return; + } + + if (!prefer_.isEmpty() + || required_->mappingRequirements() != NoMappingFeatures + || required_->routingRequirements() != NoRoutingFeatures + || required_->geocodingRequirements() != NoGeocodingFeatures + || required_->placesRequirements() != NoPlacesFeatures) { + + QStringList providers = QGeoServiceProvider::availableServiceProviders(); + + /* first check any preferred plugins */ + foreach (const QString &name, prefer_) { + if (providers.contains(name)) { + // so we don't try it again later + providers.removeAll(name); + + QGeoServiceProvider sp(name, parameterMap(), experimental_); + if (required_->matches(&sp)) { + setName(name); + return; + } + } + } + + /* then try the rest */ + foreach (const QString &name, providers) { + QGeoServiceProvider sp(name, parameterMap(), experimental_); + if (required_->matches(&sp)) { + setName(name); + return; + } + } + + qmlInfo(this) << "Could not find a plugin with the required features to attach to"; + } +} + +/*! + \qmlmethod bool Plugin::supportsGeocoding(GeocodingFeatures features) + + This method returns a boolean indicating whether the specified set of \a features are supported + by the geo service provider plugin. True is returned if all specified \a features are + supported; otherwise false is returned. + + The \a features parameter can be any flag combination of: + \table + \header + \li Feature + \li Description + \row + \li Plugin.NoGeocodingFeatures + \li No geocoding features are supported. + \row + \li Plugin.OnlineGeocodingFeature + \li Online geocoding is supported. + \row + \li Plugin.OfflineGeocodingFeature + \li Offline geocoding is supported. + \row + \li Plugin.ReverseGeocodingFeature + \li Reverse geocoding is supported. + \row + \li Plugin.LocalizedGeocodingFeature + \li Supports returning geocoding results with localized addresses. + \row + \li Plugin.AnyGeocodingFeatures + \li Matches a geo service provider that provides any geocoding features. + \endtable +*/ +bool QDeclarativeGeoServiceProvider::supportsGeocoding(const GeocodingFeatures &feature) const +{ + QGeoServiceProvider *sp = sharedGeoServiceProvider(); + QGeoServiceProvider::GeocodingFeatures f = + static_cast(int(feature)); + if (f == QGeoServiceProvider::AnyGeocodingFeatures) + return (sp && (sp->geocodingFeatures() != QGeoServiceProvider::NoGeocodingFeatures)); + else + return (sp && (sp->geocodingFeatures() & f) == f); +} + +/*! + \qmlmethod bool Plugin::supportsMapping(MappingFeatures features) + + This method returns a boolean indicating whether the specified set of \a features are supported + by the geo service provider plugin. True is returned if all specified \a features are + supported; otherwise false is returned. + + The \a features parameter can be any flag combination of: + \table + \header + \li Feature + \li Description + \row + \li Plugin.NoMappingFeatures + \li No mapping features are supported. + \row + \li Plugin.OnlineMappingFeature + \li Online mapping is supported. + \row + \li Plugin.OfflineMappingFeature + \li Offline mapping is supported. + \row + \li Plugin.LocalizedMappingFeature + \li Supports returning localized map data. + \row + \li Plugin.AnyMappingFeatures + \li Matches a geo service provider that provides any mapping features. + \endtable +*/ +bool QDeclarativeGeoServiceProvider::supportsMapping(const MappingFeatures &feature) const +{ + QGeoServiceProvider *sp = sharedGeoServiceProvider(); + QGeoServiceProvider::MappingFeatures f = + static_cast(int(feature)); + if (f == QGeoServiceProvider::AnyMappingFeatures) + return (sp && (sp->mappingFeatures() != QGeoServiceProvider::NoMappingFeatures)); + else + return (sp && (sp->mappingFeatures() & f) == f); +} + +/*! + \qmlmethod bool Plugin::supportsRouting(RoutingFeatures features) + + This method returns a boolean indicating whether the specified set of \a features are supported + by the geo service provider plugin. True is returned if all specified \a features are + supported; otherwise false is returned. + + The \a features parameter can be any flag combination of: + \table + \header + \li Feature + \li Description + \row + \li Plugin.NoRoutingFeatures + \li No routing features are supported. + \row + \li Plugin.OnlineRoutingFeature + \li Online routing is supported. + \row + \li Plugin.OfflineRoutingFeature + \li Offline routing is supported. + \row + \li Plugin.LocalizedRoutingFeature + \li Supports returning routes with localized addresses and instructions. + \row + \li Plugin.RouteUpdatesFeature + \li Updating an existing route based on the current position is supported. + \row + \li Plugin.AlternativeRoutesFeature + \li Supports returning alternative routes. + \row + \li Plugin.ExcludeAreasRoutingFeature + \li Supports specifying a areas which the returned route must not cross. + \row + \li Plugin.AnyRoutingFeatures + \li Matches a geo service provider that provides any routing features. + \endtable +*/ +bool QDeclarativeGeoServiceProvider::supportsRouting(const RoutingFeatures &feature) const +{ + QGeoServiceProvider *sp = sharedGeoServiceProvider(); + QGeoServiceProvider::RoutingFeatures f = + static_cast(int(feature)); + if (f == QGeoServiceProvider::AnyRoutingFeatures) + return (sp && (sp->routingFeatures() != QGeoServiceProvider::NoRoutingFeatures)); + else + return (sp && (sp->routingFeatures() & f) == f); +} + +/*! + \qmlmethod bool Plugin::supportsPlaces(PlacesFeatures features) + + This method returns a boolean indicating whether the specified set of \a features are supported + by the geo service provider plugin. True is returned if all specified \a features are + supported; otherwise false is returned. + + The \a features parameter can be any flag combination of: + \table + \header + \li Feature + \li Description + \row + \li Plugin.NoPlacesFeatures + \li No places features are supported. + \row + \li Plugin.OnlinePlacesFeature + \li Online places is supported. + \row + \li Plugin.OfflinePlacesFeature + \li Offline places is supported. + \row + \li Plugin.SavePlaceFeature + \li Saving categories is supported. + \row + \li Plugin.RemovePlaceFeature + \li Removing or deleting places is supported. + \row + \li Plugin.PlaceRecommendationsFeature + \li Searching for recommended places similar to another place is supported. + \row + \li Plugin.SearchSuggestionsFeature + \li Search suggestions is supported. + \row + \li Plugin.LocalizedPlacesFeature + \li Supports returning localized place data. + \row + \li Plugin.NotificationsFeature + \li Notifications of place and category changes is supported. + \row + \li Plugin.PlaceMatchingFeature + \li Supports matching places from two different geo service providers. + \row + \li Plugin.AnyPlacesFeatures + \li Matches a geo service provider that provides any places features. + \endtable +*/ +bool QDeclarativeGeoServiceProvider::supportsPlaces(const PlacesFeatures &features) const +{ + QGeoServiceProvider *sp = sharedGeoServiceProvider(); + QGeoServiceProvider::PlacesFeatures f = + static_cast(int(features)); + if (f == QGeoServiceProvider::AnyPlacesFeatures) + return (sp && (sp->placesFeatures() != QGeoServiceProvider::NoPlacesFeatures)); + else + return (sp && (sp->placesFeatures() & f) == f); +} + +/*! + \qmlproperty enumeration Plugin::required + + This property contains the set of features that will be required by the + Plugin object when choosing which service plugin to attach to. If the + \l name property is set, this has no effect. + + Any of the following values or a bitwise combination of multiple values + may be set: + + \list + \li Plugin.NoFeatures + \li Plugin.GeocodingFeature + \li Plugin.ReverseGeocodingFeature + \li Plugin.RoutingFeature + \li Plugin.MappingFeature + \li Plugin.AnyPlacesFeature + \endlist +*/ +QDeclarativeGeoServiceProviderRequirements *QDeclarativeGeoServiceProvider::requirements() const +{ + return required_; +} + +/*! + \qmlproperty stringlist Plugin::preferred + + This property contains an ordered list of preferred plugin names, which + will be checked for the required features set in \l{Plugin::required}{required} + before any other available plugins are checked. +*/ +QStringList QDeclarativeGeoServiceProvider::preferred() const +{ + return prefer_; +} + +void QDeclarativeGeoServiceProvider::setPreferred(const QStringList &val) +{ + prefer_ = val; + emit preferredChanged(prefer_); +} + +/*! + \qmlproperty bool Plugin::isAttached + + This property indicates if the Plugin is attached to another Plugin. +*/ +bool QDeclarativeGeoServiceProvider::isAttached() const +{ + return (sharedProvider_ != 0); +} + +/*! + \qmlproperty bool Plugin::allowExperimental + + This property indicates if experimental plugins can be used. +*/ +bool QDeclarativeGeoServiceProvider::allowExperimental() const +{ + return experimental_; +} + +void QDeclarativeGeoServiceProvider::setAllowExperimental(bool allow) +{ + if (experimental_ == allow) + return; + + experimental_ = allow; + if (sharedProvider_) + sharedProvider_->setAllowExperimental(allow); + + emit allowExperimentalChanged(allow); +} + +/*! + \internal +*/ +QGeoServiceProvider *QDeclarativeGeoServiceProvider::sharedGeoServiceProvider() const +{ + return sharedProvider_; +} + +/*! + \qmlproperty stringlist Plugin::locales + + This property contains an ordered list of preferred plugin locales. If the first locale cannot be accommodated, then + the backend falls back to using the second, and so on. By default the locales property contains the system locale. + + The locales are specified as strings which have the format + "language[_script][_country]" or "C", where: + + \list + \li language is a lowercase, two-letter, ISO 639 language code, + \li script is a titlecase, four-letter, ISO 15924 script code, + \li country is an uppercase, two- or three-letter, ISO 3166 country code (also "419" as defined by United Nations), + \li the "C" locale is identical in behavior to English/UnitedStates as per QLocale + \endlist + + If the first specified locale cannot be accommodated, the \l {Plugin} falls back to the next and so forth. + Some \l {Plugin} backends may not support a set of locales which are rigidly defined. An arbitrary + example is that some \l {Place}'s in France could have French and English localizations, while + certain areas in America may only have the English localization available. In the above scenario, + the set of supported locales is context dependent on the search location. + + If the \l {Plugin} cannot accommodate any of the preferred locales, the manager falls + back to using a supported language that is backend specific. + + For \l {Plugin}'s that do not support locales, the locales list is always empty. + + The following code demonstrates how to set a single and multiple locales: + \snippet declarative/plugin.qml Plugin locale +*/ +QStringList QDeclarativeGeoServiceProvider::locales() const +{ + return locales_; +} + +void QDeclarativeGeoServiceProvider::setLocales(const QStringList &locales) +{ + if (locales_ == locales) + return; + + locales_ = locales; + + if (locales_.isEmpty()) + locales_.append(QLocale().name()); + + if (sharedProvider_) + sharedProvider_->setLocale(locales_.at(0)); + + emit localesChanged(); +} + +/*! + \qmlproperty list Plugin::parameters + \default + + This property holds the list of plugin parameters. +*/ +QQmlListProperty QDeclarativeGeoServiceProvider::parameters() +{ + return QQmlListProperty(this, + 0, + parameter_append, + parameter_count, + parameter_at, + parameter_clear); +} + +/*! + \internal +*/ +void QDeclarativeGeoServiceProvider::parameter_append(QQmlListProperty *prop, QDeclarativeGeoServiceProviderParameter *parameter) +{ + QDeclarativeGeoServiceProvider *p = static_cast(prop->object); + p->parameters_.append(parameter); + if (p->sharedProvider_) + p->sharedProvider_->setParameters(p->parameterMap()); +} + +/*! + \internal +*/ +int QDeclarativeGeoServiceProvider::parameter_count(QQmlListProperty *prop) +{ + return static_cast(prop->object)->parameters_.count(); +} + +/*! + \internal +*/ +QDeclarativeGeoServiceProviderParameter *QDeclarativeGeoServiceProvider::parameter_at(QQmlListProperty *prop, int index) +{ + return static_cast(prop->object)->parameters_[index]; +} + +/*! + \internal +*/ +void QDeclarativeGeoServiceProvider::parameter_clear(QQmlListProperty *prop) +{ + QDeclarativeGeoServiceProvider *p = static_cast(prop->object); + p->parameters_.clear(); + if (p->sharedProvider_) + p->sharedProvider_->setParameters(p->parameterMap()); +} + +/*! + \internal +*/ +QVariantMap QDeclarativeGeoServiceProvider::parameterMap() const +{ + QVariantMap map; + + for (int i = 0; i < parameters_.size(); ++i) { + QDeclarativeGeoServiceProviderParameter *parameter = parameters_.at(i); + map.insert(parameter->name(), parameter->value()); + } + + return map; +} + +/******************************************************************************* +*******************************************************************************/ + +QDeclarativeGeoServiceProviderRequirements::QDeclarativeGeoServiceProviderRequirements(QObject *parent) + : QObject(parent), + mapping_(QDeclarativeGeoServiceProvider::NoMappingFeatures), + routing_(QDeclarativeGeoServiceProvider::NoRoutingFeatures), + geocoding_(QDeclarativeGeoServiceProvider::NoGeocodingFeatures), + places_(QDeclarativeGeoServiceProvider::NoPlacesFeatures) +{ +} + +QDeclarativeGeoServiceProviderRequirements::~QDeclarativeGeoServiceProviderRequirements() +{ +} + +/*! + \internal +*/ +QDeclarativeGeoServiceProvider::MappingFeatures QDeclarativeGeoServiceProviderRequirements::mappingRequirements() const +{ + return mapping_; +} + +/*! + \internal +*/ +void QDeclarativeGeoServiceProviderRequirements::setMappingRequirements(const QDeclarativeGeoServiceProvider::MappingFeatures &features) +{ + if (mapping_ == features) + return; + + mapping_ = features; + emit mappingRequirementsChanged(mapping_); + emit requirementsChanged(); +} + +/*! + \internal +*/ +QDeclarativeGeoServiceProvider::RoutingFeatures QDeclarativeGeoServiceProviderRequirements::routingRequirements() const +{ + return routing_; +} + +/*! + \internal +*/ +void QDeclarativeGeoServiceProviderRequirements::setRoutingRequirements(const QDeclarativeGeoServiceProvider::RoutingFeatures &features) +{ + if (routing_ == features) + return; + + routing_ = features; + emit routingRequirementsChanged(routing_); + emit requirementsChanged(); +} + +/*! + \internal +*/ +QDeclarativeGeoServiceProvider::GeocodingFeatures QDeclarativeGeoServiceProviderRequirements::geocodingRequirements() const +{ + return geocoding_; +} + +/*! + \internal +*/ +void QDeclarativeGeoServiceProviderRequirements::setGeocodingRequirements(const QDeclarativeGeoServiceProvider::GeocodingFeatures &features) +{ + if (geocoding_ == features) + return; + + geocoding_ = features; + emit geocodingRequirementsChanged(geocoding_); + emit requirementsChanged(); +} + +/*! + \internal + + */ +QDeclarativeGeoServiceProvider::PlacesFeatures QDeclarativeGeoServiceProviderRequirements::placesRequirements() const +{ + return places_; +} + +/*! + \internal +*/ +void QDeclarativeGeoServiceProviderRequirements::setPlacesRequirements(const QDeclarativeGeoServiceProvider::PlacesFeatures &features) +{ + if (places_ == features) + return; + + places_ = features; + emit placesRequirementsChanged(places_); + emit requirementsChanged(); +} + +/*! + \internal +*/ +bool QDeclarativeGeoServiceProviderRequirements::matches(const QGeoServiceProvider *provider) const +{ + QGeoServiceProvider::MappingFeatures mapping = + static_cast(int(mapping_)); + + // extra curlies here to avoid "dangling" else, which could belong to either if + // same goes for all the rest of these blocks + if (mapping == QGeoServiceProvider::AnyMappingFeatures) { + if (provider->mappingFeatures() == QGeoServiceProvider::NoMappingFeatures) + return false; + } else { + if ((provider->mappingFeatures() & mapping) != mapping) + return false; + } + + QGeoServiceProvider::RoutingFeatures routing = + static_cast(int(routing_)); + + if (routing == QGeoServiceProvider::AnyRoutingFeatures) { + if (provider->routingFeatures() == QGeoServiceProvider::NoRoutingFeatures) + return false; + } else { + if ((provider->routingFeatures() & routing) != routing) + return false; + } + + QGeoServiceProvider::GeocodingFeatures geocoding = + static_cast(int(geocoding_)); + + if (geocoding == QGeoServiceProvider::AnyGeocodingFeatures) { + if (provider->geocodingFeatures() == QGeoServiceProvider::NoGeocodingFeatures) + return false; + } else { + if ((provider->geocodingFeatures() & geocoding) != geocoding) + return false; + } + + QGeoServiceProvider::PlacesFeatures places = + static_cast(int(places_)); + + if (places == QGeoServiceProvider::AnyPlacesFeatures) { + if (provider->placesFeatures() == QGeoServiceProvider::NoPlacesFeatures) + return false; + } else { + if ((provider->placesFeatures() & places) != places) + return false; + } + + return true; +} + +/******************************************************************************* +*******************************************************************************/ + +/*! + \qmltype PluginParameter + \instantiates QDeclarativeGeoServiceProviderParameter + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-common + \since Qt Location 5.5 + + \brief The PluginParameter type describes a parameter to a \l Plugin. + + The PluginParameter object is used to provide a parameter of some kind + to a Plugin. Typically these parameters contain details like an application + token for access to a service, or a proxy server to use for network access. + + To set such a parameter, declare a PluginParameter inside a \l Plugin + object, and give it \l{name} and \l{value} properties. A list of valid + parameter names for each plugin is available from the + \l {Qt Location#Plugin References and Parameters}{plugin reference pages}. + + \section2 Example Usage + + The following example shows an instantiation of the \l {Qt Location HERE Plugin}{HERE} plugin + with a mapping API \e app_id and \e token pair specific to the application. + + \code + Plugin { + name: "here" + PluginParameter { name: "here.app_id"; value: "EXAMPLE_API_ID" } + PluginParameter { name: "here.token"; value: "EXAMPLE_TOKEN_123" } + } + \endcode +*/ + +QDeclarativeGeoServiceProviderParameter::QDeclarativeGeoServiceProviderParameter(QObject *parent) + : QObject(parent) {} + +QDeclarativeGeoServiceProviderParameter::~QDeclarativeGeoServiceProviderParameter() {} + +/*! + \qmlproperty string PluginParameter::name + + This property holds the name of the plugin parameter as a single formatted string. +*/ +void QDeclarativeGeoServiceProviderParameter::setName(const QString &name) +{ + if (name_ == name) + return; + + name_ = name; + + emit nameChanged(name_); +} + +QString QDeclarativeGeoServiceProviderParameter::name() const +{ + return name_; +} + +/*! + \qmlproperty QVariant PluginParameter::value + + This property holds the value of the plugin parameter which support different types of values (variant). +*/ +void QDeclarativeGeoServiceProviderParameter::setValue(const QVariant &value) +{ + if (value_ == value) + return; + + value_ = value; + + emit valueChanged(value_); +} + +QVariant QDeclarativeGeoServiceProviderParameter::value() const +{ + return value_; +} + +/******************************************************************************* +*******************************************************************************/ + +#include "moc_qdeclarativegeoserviceprovider_p.cpp" + +QT_END_NAMESPACE + diff --git a/src/imports/location/qdeclarativegeoserviceprovider_p.h b/src/imports/location/qdeclarativegeoserviceprovider_p.h new file mode 100644 index 0000000..f7a2ee8 --- /dev/null +++ b/src/imports/location/qdeclarativegeoserviceprovider_p.h @@ -0,0 +1,282 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEQGEOSERVICEPROVIDER_H +#define QDECLARATIVEQGEOSERVICEPROVIDER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoServiceProviderParameter : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged) + +public: + explicit QDeclarativeGeoServiceProviderParameter(QObject *parent = 0); + ~QDeclarativeGeoServiceProviderParameter(); + + void setName(const QString &name); + QString name() const; + + void setValue(const QVariant &value); + QVariant value() const; + +Q_SIGNALS: + void nameChanged(const QString &name); + void valueChanged(const QVariant &value); + +private: + QString name_; + QVariant value_; +}; + +class QDeclarativeGeoServiceProviderRequirements; + +class QDeclarativeGeoServiceProvider : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_ENUMS(RoutingFeature) + Q_ENUMS(GeocodingFeature) + Q_ENUMS(MappingFeature) + Q_ENUMS(PlacesFeature) + + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QStringList availableServiceProviders READ availableServiceProviders CONSTANT) + Q_PROPERTY(QQmlListProperty parameters READ parameters) + Q_PROPERTY(QDeclarativeGeoServiceProviderRequirements *required READ requirements) + Q_PROPERTY(QStringList locales READ locales WRITE setLocales NOTIFY localesChanged) + Q_PROPERTY(QStringList preferred READ preferred WRITE setPreferred NOTIFY preferredChanged) + Q_PROPERTY(bool allowExperimental READ allowExperimental WRITE setAllowExperimental NOTIFY allowExperimentalChanged) + Q_PROPERTY(bool isAttached READ isAttached NOTIFY attached) + + Q_CLASSINFO("DefaultProperty", "parameters") + Q_INTERFACES(QQmlParserStatus) + +public: + explicit QDeclarativeGeoServiceProvider(QObject *parent = 0); + ~QDeclarativeGeoServiceProvider(); + + enum RoutingFeature { + NoRoutingFeatures = QGeoServiceProvider::NoRoutingFeatures, + OnlineRoutingFeature = QGeoServiceProvider::OnlineRoutingFeature, + OfflineRoutingFeature = QGeoServiceProvider::OfflineRoutingFeature, + LocalizedRoutingFeature = QGeoServiceProvider::LocalizedRoutingFeature, + RouteUpdatesFeature = QGeoServiceProvider::RouteUpdatesFeature, + AlternativeRoutesFeature = QGeoServiceProvider::AlternativeRoutesFeature, + ExcludeAreasRoutingFeature = QGeoServiceProvider::ExcludeAreasRoutingFeature, + AnyRoutingFeatures = QGeoServiceProvider::AnyRoutingFeatures + }; + + enum GeocodingFeature { + NoGeocodingFeatures = QGeoServiceProvider::NoGeocodingFeatures, + OnlineGeocodingFeature = QGeoServiceProvider::OnlineGeocodingFeature, + OfflineGeocodingFeature = QGeoServiceProvider::OfflineGeocodingFeature, + ReverseGeocodingFeature = QGeoServiceProvider::ReverseGeocodingFeature, + LocalizedGeocodingFeature = QGeoServiceProvider::LocalizedGeocodingFeature, + AnyGeocodingFeatures = QGeoServiceProvider::AnyGeocodingFeatures + }; + + enum MappingFeature { + NoMappingFeatures = QGeoServiceProvider::NoMappingFeatures, + OnlineMappingFeature = QGeoServiceProvider::OnlineMappingFeature, + OfflineMappingFeature = QGeoServiceProvider::OfflineMappingFeature, + LocalizedMappingFeature = QGeoServiceProvider::LocalizedMappingFeature, + AnyMappingFeatures = QGeoServiceProvider::AnyMappingFeatures + }; + + enum PlacesFeature { + NoPlacesFeatures = QGeoServiceProvider::NoPlacesFeatures, + OnlinePlacesFeature = QGeoServiceProvider::OnlinePlacesFeature, + OfflinePlacesFeature = QGeoServiceProvider::OfflinePlacesFeature, + SavePlaceFeature = QGeoServiceProvider::SavePlaceFeature, + RemovePlaceFeature = QGeoServiceProvider::RemovePlaceFeature, + SaveCategoryFeature = QGeoServiceProvider::SaveCategoryFeature, + RemoveCategoryFeature = QGeoServiceProvider::RemoveCategoryFeature, + PlaceRecommendationsFeature = QGeoServiceProvider::PlaceRecommendationsFeature, + SearchSuggestionsFeature = QGeoServiceProvider::SearchSuggestionsFeature, + LocalizedPlacesFeature = QGeoServiceProvider::LocalizedPlacesFeature, + NotificationsFeature = QGeoServiceProvider::NotificationsFeature, + PlaceMatchingFeature = QGeoServiceProvider::PlaceMatchingFeature, + AnyPlacesFeatures = QGeoServiceProvider::AnyPlacesFeatures + }; + + Q_DECLARE_FLAGS(RoutingFeatures, RoutingFeature) + Q_FLAGS(RoutingFeatures) + + Q_DECLARE_FLAGS(GeocodingFeatures, GeocodingFeature) + Q_FLAGS(GeocodingFeatures) + + Q_DECLARE_FLAGS(MappingFeatures, MappingFeature) + Q_FLAGS(MappingFeatures) + + Q_DECLARE_FLAGS(PlacesFeatures, PlacesFeature) + Q_FLAGS(PlacesFeatures) + + // From QQmlParserStatus + virtual void classBegin() {} + virtual void componentComplete(); + + void setName(const QString &name); + QString name() const; + + QQmlListProperty parameters(); + QVariantMap parameterMap() const; + + QStringList availableServiceProviders(); + + QDeclarativeGeoServiceProviderRequirements *requirements() const; + + QStringList preferred() const; + void setPreferred(const QStringList &val); + + QGeoServiceProvider *sharedGeoServiceProvider() const; + + Q_INVOKABLE bool supportsRouting(const RoutingFeatures &feature = AnyRoutingFeatures) const; + Q_INVOKABLE bool supportsGeocoding(const GeocodingFeatures &feature = AnyGeocodingFeatures) const; + Q_INVOKABLE bool supportsMapping(const MappingFeatures &feature = AnyMappingFeatures) const; + Q_INVOKABLE bool supportsPlaces(const PlacesFeatures &feature = AnyPlacesFeatures) const; + + QStringList locales() const; + void setLocales(const QStringList &locales); + + bool isAttached() const; + + void setAllowExperimental(bool allow); + bool allowExperimental() const; + +Q_SIGNALS: + void nameChanged(const QString &name); + void localesChanged(); + void attached(); + void preferredChanged(const QStringList &preferences); + void allowExperimentalChanged(bool allow); + +private: + static void parameter_append(QQmlListProperty *prop, QDeclarativeGeoServiceProviderParameter *mapObject); + static int parameter_count(QQmlListProperty *prop); + static QDeclarativeGeoServiceProviderParameter *parameter_at(QQmlListProperty *prop, int index); + static void parameter_clear(QQmlListProperty *prop); + + QGeoServiceProvider *sharedProvider_; + QString name_; + QList parameters_; + QDeclarativeGeoServiceProviderRequirements *required_; + bool complete_; + bool experimental_; + QStringList locales_; + QStringList prefer_; + Q_DISABLE_COPY(QDeclarativeGeoServiceProvider) +}; + +class QDeclarativeGeoServiceProviderRequirements : public QObject +{ + Q_OBJECT + Q_PROPERTY(QDeclarativeGeoServiceProvider::MappingFeatures mapping + READ mappingRequirements WRITE setMappingRequirements + NOTIFY mappingRequirementsChanged) + Q_PROPERTY(QDeclarativeGeoServiceProvider::RoutingFeatures routing + READ routingRequirements WRITE setRoutingRequirements + NOTIFY routingRequirementsChanged) + Q_PROPERTY(QDeclarativeGeoServiceProvider::GeocodingFeatures geocoding + READ geocodingRequirements WRITE setGeocodingRequirements + NOTIFY geocodingRequirementsChanged) + Q_PROPERTY(QDeclarativeGeoServiceProvider::PlacesFeatures places + READ placesRequirements WRITE setPlacesRequirements + NOTIFY placesRequirementsChanged) + +public: + explicit QDeclarativeGeoServiceProviderRequirements(QObject *parent = 0); + ~QDeclarativeGeoServiceProviderRequirements(); + + QDeclarativeGeoServiceProvider::MappingFeatures mappingRequirements() const; + void setMappingRequirements(const QDeclarativeGeoServiceProvider::MappingFeatures &features); + + QDeclarativeGeoServiceProvider::RoutingFeatures routingRequirements() const; + void setRoutingRequirements(const QDeclarativeGeoServiceProvider::RoutingFeatures &features); + + QDeclarativeGeoServiceProvider::GeocodingFeatures geocodingRequirements() const; + void setGeocodingRequirements(const QDeclarativeGeoServiceProvider::GeocodingFeatures &features); + + QDeclarativeGeoServiceProvider::PlacesFeatures placesRequirements() const; + void setPlacesRequirements(const QDeclarativeGeoServiceProvider::PlacesFeatures &features); + + Q_INVOKABLE bool matches(const QGeoServiceProvider *provider) const; + +Q_SIGNALS: + void mappingRequirementsChanged(const QDeclarativeGeoServiceProvider::MappingFeatures &features); + void routingRequirementsChanged(const QDeclarativeGeoServiceProvider::RoutingFeatures &features); + void geocodingRequirementsChanged(const QDeclarativeGeoServiceProvider::GeocodingFeatures &features); + void placesRequirementsChanged(const QDeclarativeGeoServiceProvider::PlacesFeatures &features); + + void requirementsChanged(); + +private: + QDeclarativeGeoServiceProvider::MappingFeatures mapping_; + QDeclarativeGeoServiceProvider::RoutingFeatures routing_; + QDeclarativeGeoServiceProvider::GeocodingFeatures geocoding_; + QDeclarativeGeoServiceProvider::PlacesFeatures places_; + +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeGeoServiceProviderParameter) +QML_DECLARE_TYPE(QDeclarativeGeoServiceProviderRequirements) +QML_DECLARE_TYPE(QDeclarativeGeoServiceProvider) + +#endif diff --git a/src/imports/location/qdeclarativepolygonmapitem.cpp b/src/imports/location/qdeclarativepolygonmapitem.cpp new file mode 100644 index 0000000..3d98140 --- /dev/null +++ b/src/imports/location/qdeclarativepolygonmapitem.cpp @@ -0,0 +1,724 @@ +/**************************************************************************** + ** + ** Copyright (C) 2015 The Qt Company Ltd. + ** Contact: http://www.qt.io/licensing/ + ** + ** This file is part of the QtLocation module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL3$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see http://www.qt.io/terms-conditions. For further + ** information use the contact form at http://www.qt.io/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 3 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPLv3 included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 3 requirements + ** will be met: https://www.gnu.org/licenses/lgpl.html. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 2.0 or later as published by the Free + ** Software Foundation and appearing in the file LICENSE.GPL included in + ** the packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 2.0 requirements will be + ** met: http://www.gnu.org/licenses/gpl-2.0.html. + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include "qdeclarativepolygonmapitem_p.h" +#include "qgeocameracapabilities_p.h" +#include "qlocationutils_p.h" +#include "error_messages.h" +#include "locationvaluetypehelper_p.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "qdoublevector2d_p.h" + +/* poly2tri triangulator includes */ +#include "../../3rdparty/clip2tri/clip2tri.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype MapPolygon + \instantiates QDeclarativePolygonMapItem + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.5 + + \brief The MapPolygon type displays a polygon on a Map + + The MapPolygon type displays a polygon on a Map, specified in terms of an ordered list of + \l {QtPositioning::coordinate}{coordinates}. For best appearance and results, polygons should be + simple (not self-intersecting). + + The \l {QtPositioning::coordinate}{coordinates} on the path cannot be directly changed after + being added to the Polygon. Instead, copy the \l path into a var, modify the copy and reassign + the copy back to the \l path. + + \code + var path = mapPolygon.path; + path[0].latitude = 5; + mapPolygon.path = path; + \endcode + + Coordinates can also be added and removed at any time using the \l addCoordinate and + \l removeCoordinate methods. + + For drawing rectangles with "straight" edges (same latitude across one + edge, same latitude across the other), the \l MapRectangle type provides + a simpler, two-point API. + + By default, the polygon is displayed as a 1 pixel black border with no + fill. To change its appearance, use the \l color, \l border.color and + \l border.width properties. + + \note Since MapPolygons are geographic items, dragging a MapPolygon + (through the use of \l MouseArea) causes its vertices to be + recalculated in the geographic coordinate space. The edges retain the + same geographic lengths (latitude and longitude differences between the + vertices), but they remain straight. Apparent stretching of the item occurs + when dragged to a different latitude. + + \section2 Performance + + MapPolygons have a rendering cost that is O(n) with respect to the number + of vertices. This means that the per frame cost of having a Polygon on the + Map grows in direct proportion to the number of points on the Polygon. There + is an additional triangulation cost (approximately O(n log n)) which is + currently paid with each frame, but in future may be paid only upon adding + or removing points. + + Like the other map objects, MapPolygon is normally drawn without a smooth + appearance. Setting the \l {Item::opacity}{opacity} property will force the object to + be blended, which decreases performance considerably depending on the hardware in use. + + \section2 Example Usage + + The following snippet shows a MapPolygon being used to display a triangle, + with three vertices near Brisbane, Australia. The triangle is filled in + green, with a 1 pixel black border. + + \code + Map { + MapPolygon { + color: 'green' + path: [ + { latitude: -27, longitude: 153.0 }, + { latitude: -27, longitude: 154.1 }, + { latitude: -28, longitude: 153.5 } + ] + } + } + \endcode + + \image api-mappolygon.png +*/ + +struct Vertex +{ + QVector2D position; +}; + +QGeoMapPolygonGeometry::QGeoMapPolygonGeometry() +: assumeSimple_(false) +{ +} + +/*! + \internal +*/ +void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, + const QList &path) +{ + if (!sourceDirty_) + return; + + double minX = -1.0; + + // build the actual path + QDoubleVector2D origin; + QDoubleVector2D lastPoint; + srcPath_ = QPainterPath(); + + double unwrapBelowX = 0; + if (preserveGeometry_ ) + unwrapBelowX = map.coordinateToItemPosition(geoLeftBound_, false).x(); + + for (int i = 0; i < path.size(); ++i) { + const QGeoCoordinate &coord = path.at(i); + + if (!coord.isValid()) + continue; + + QDoubleVector2D point = map.coordinateToItemPosition(coord, false); + + // We can get NaN if the map isn't set up correctly, or the projection + // is faulty -- probably best thing to do is abort + if (!qIsFinite(point.x()) || !qIsFinite(point.y())) + return; + + // unwrap x to preserve geometry if moved to border of map + if (preserveGeometry_ && point.x() < unwrapBelowX + && !qFuzzyCompare(point.x(), unwrapBelowX) + && !qFuzzyCompare(geoLeftBound_.longitude(), coord.longitude())) + point.setX(unwrapBelowX + geoDistanceToScreenWidth(map, geoLeftBound_, coord)); + + if (i == 0) { + origin = point; + minX = point.x(); + srcOrigin_ = coord; + srcPath_.moveTo(point.toPointF() - origin.toPointF()); + lastPoint = point; + } else { + if (point.x() <= minX) + minX = point.x(); + const QDoubleVector2D diff = (point - lastPoint); + if (diff.x() * diff.x() + diff.y() * diff.y() >= 3.0) { + srcPath_.lineTo(point.toPointF() - origin.toPointF()); + lastPoint = point; + } + } + } + + srcPath_.closeSubpath(); + + if (!assumeSimple_) + srcPath_ = srcPath_.simplified(); + + sourceBounds_ = srcPath_.boundingRect(); + geoLeftBound_ = map.itemPositionToCoordinate(QDoubleVector2D(minX, 0), false); +} + +/*! + \internal +*/ +void QGeoMapPolygonGeometry::updateScreenPoints(const QGeoMap &map) +{ + if (!screenDirty_) + return; + + if (map.width() == 0 || map.height() == 0) { + clear(); + return; + } + + QDoubleVector2D origin = map.coordinateToItemPosition(srcOrigin_, false); + + // Create the viewport rect in the same coordinate system + // as the actual points + QRectF viewport(0, 0, map.width(), map.height()); + viewport.translate(-1 * origin.toPointF()); + + QPainterPath vpPath; + vpPath.addRect(viewport); + + QPainterPath ppi; + if (clipToViewport_) + ppi = srcPath_.intersected(vpPath); // get the clipped version of the path + else ppi = srcPath_; + + clear(); + + // a polygon requires at least 3 points; + if (ppi.elementCount() < 3) + return; + + // Intersection between the viewport and a concave polygon can create multiple polygons + // joined by a line at the viewport border, and poly2tri does not triangulate this very well + // so use the full src path if the resulting polygon is concave. + if (clipToViewport_) { + int changeInX = 0; + int changeInY = 0; + QPainterPath::Element e1 = ppi.elementAt(1); + QPainterPath::Element e = ppi.elementAt(0); + QVector2D edgeA(e1.x - e.x ,e1.y - e.y); + for (int i = 2; i <= ppi.elementCount(); ++i) { + e = ppi.elementAt(i % ppi.elementCount()); + if (e.x == e1.x && e.y == e1.y) + continue; + QVector2D edgeB(e.x - e1.x, e.y - e1.y); + if ((edgeA.x() < 0) == (edgeB.x() >= 0)) + changeInX++; + if ((edgeA.y() < 0) == (edgeB.y() >= 0)) + changeInY++; + edgeA = edgeB; + e1 = e; + } + if (changeInX > 2 || changeInY > 2) // polygon is concave + ppi = srcPath_; + } + + // translate the path into top-left-centric coordinates + QRectF bb = ppi.boundingRect(); + ppi.translate(-bb.left(), -bb.top()); + firstPointOffset_ = -1 * bb.topLeft(); + + ppi.closeSubpath(); + + screenOutline_ = ppi; + +#if 1 + std::vector> clipperPoints; + clipperPoints.push_back(std::vector()); + std::vector &curPts = clipperPoints.front(); + curPts.reserve(ppi.elementCount()); + for (int i = 0; i < ppi.elementCount(); ++i) { + const QPainterPath::Element e = ppi.elementAt(i); + if (e.isMoveTo() || i == ppi.elementCount() - 1 + || (qAbs(e.x - curPts.front().x) < 0.1 + && qAbs(e.y - curPts.front().y) < 0.1)) { + if (curPts.size() > 2) { + c2t::clip2tri *cdt = new c2t::clip2tri(); + std::vector outputTriangles; + cdt->triangulate(clipperPoints, outputTriangles, std::vector()); + for (size_t i = 0; i < outputTriangles.size(); ++i) { + screenVertices_ << QPointF(outputTriangles[i].x, outputTriangles[i].y); + } + delete cdt; + } + curPts.clear(); + curPts.reserve(ppi.elementCount() - i); + curPts.push_back( c2t::Point(e.x, e.y)); + } else if (e.isLineTo()) { + curPts.push_back( c2t::Point(e.x, e.y)); + } else { + qWarning("Unhandled element type in polygon painterpath"); + } + } +#else // Old qTriangulate()-based code. + QTriangleSet ts = qTriangulate(ppi); + qreal *vx = ts.vertices.data(); + + screenIndices_.reserve(ts.indices.size()); + screenVertices_.reserve(ts.vertices.size()); + + if (ts.indices.type() == QVertexIndexVector::UnsignedInt) { + const quint32 *ix = reinterpret_cast(ts.indices.data()); + for (int i = 0; i < (ts.indices.size()/3*3); ++i) + screenIndices_ << ix[i]; + } else { + const quint16 *ix = reinterpret_cast(ts.indices.data()); + for (int i = 0; i < (ts.indices.size()/3*3); ++i) + screenIndices_ << ix[i]; + } + for (int i = 0; i < (ts.vertices.size()/2*2); i += 2) + screenVertices_ << QPointF(vx[i], vx[i + 1]); +#endif + + screenBounds_ = ppi.boundingRect(); +} + +QDeclarativePolygonMapItem::QDeclarativePolygonMapItem(QQuickItem *parent) +: QDeclarativeGeoMapItemBase(parent), color_(Qt::transparent), dirtyMaterial_(true), + updatingGeometry_(false) +{ + setFlag(ItemHasContents, true); + QObject::connect(&border_, SIGNAL(colorChanged(QColor)), + this, SLOT(handleBorderUpdated())); + QObject::connect(&border_, SIGNAL(widthChanged(qreal)), + this, SLOT(handleBorderUpdated())); +} + +/*! + \internal +*/ +void QDeclarativePolygonMapItem::handleBorderUpdated() +{ + borderGeometry_.markSourceDirty(); + polishAndUpdate(); +} + +QDeclarativePolygonMapItem::~QDeclarativePolygonMapItem() +{ +} + +/*! + \qmlpropertygroup Location::MapPolygon::border + \qmlproperty int MapPolygon::border.width + \qmlproperty color MapPolygon::border.color + + This property is part of the border property group. The border property + group holds the width and color used to draw the border of the polygon. + + The width is in pixels and is independent of the zoom level of the map. + + The default values correspond to a black border with a width of 1 pixel. + For no line, use a width of 0 or a transparent color. +*/ + +QDeclarativeMapLineProperties *QDeclarativePolygonMapItem::border() +{ + return &border_; +} + +/*! + \internal +*/ +void QDeclarativePolygonMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) +{ + QDeclarativeGeoMapItemBase::setMap(quickMap,map); + if (map) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + polishAndUpdate(); + } +} + +/*! + \qmlproperty list MapPolygon::path + + This property holds the ordered list of coordinates which + define the polygon. + + \sa addCoordinate, removeCoordinate +*/ +QJSValue QDeclarativePolygonMapItem::path() const +{ + QQmlContext *context = QQmlEngine::contextForObject(parent()); + QQmlEngine *engine = context->engine(); + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); + + QV4::Scope scope(v4); + QV4::Scoped pathArray(scope, v4->newArrayObject(path_.length())); + for (int i = 0; i < path_.length(); ++i) { + const QGeoCoordinate &c = path_.at(i); + + QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(c))); + pathArray->putIndexed(i, cv); + } + + return QJSValue(v4, pathArray.asReturnedValue()); +} + +void QDeclarativePolygonMapItem::setPath(const QJSValue &value) +{ + if (!value.isArray()) + return; + + QList pathList; + quint32 length = value.property(QStringLiteral("length")).toUInt(); + for (quint32 i = 0; i < length; ++i) { + bool ok; + QGeoCoordinate c = parseCoordinate(value.property(i), &ok); + + if (!ok || !c.isValid()) { + qmlInfo(this) << "Unsupported path type"; + return; + } + + pathList.append(c); + } + + if (path_ == pathList) + return; + + path_ = pathList; + geoLeftBound_ = QDeclarativePolylineMapItem::getLeftBound(path_, deltaXs_, minX_); + geometry_.setPreserveGeometry(true, geoLeftBound_); + borderGeometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlmethod void MapPolygon::addCoordinate(coordinate) + + Adds a coordinate to the path. + + \sa removeCoordinate, path +*/ + +void QDeclarativePolygonMapItem::addCoordinate(const QGeoCoordinate &coordinate) +{ + path_.append(coordinate); + geoLeftBound_ = QDeclarativePolylineMapItem::getLeftBound(path_, deltaXs_, minX_, geoLeftBound_); + geometry_.setPreserveGeometry(true, geoLeftBound_); + borderGeometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlmethod void MapPolygon::removeCoordinate(coordinate) + + Removes \a coordinate from the path. If there are multiple instances of the + same coordinate, the one added last is removed. + + If \a coordinate is not in the path this method does nothing. + + \sa addCoordinate, path +*/ +void QDeclarativePolygonMapItem::removeCoordinate(const QGeoCoordinate &coordinate) +{ + int index = path_.lastIndexOf(coordinate); + if (index == -1) + return; + + path_.removeAt(index); + geoLeftBound_ = QDeclarativePolylineMapItem::getLeftBound(path_, deltaXs_, minX_); + geometry_.setPreserveGeometry(true, geoLeftBound_); + borderGeometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlproperty color MapPolygon::color + + This property holds the color used to fill the polygon. + + The default value is transparent. +*/ + +QColor QDeclarativePolygonMapItem::color() const +{ + return color_; +} + +void QDeclarativePolygonMapItem::setColor(const QColor &color) +{ + if (color_ == color) + return; + + color_ = color; + dirtyMaterial_ = true; + update(); + emit colorChanged(color_); +} + +/*! + \internal +*/ +QSGNode *QDeclarativePolygonMapItem::updateMapItemPaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) +{ + Q_UNUSED(data); + MapPolygonNode *node = static_cast(oldNode); + + if (!node) + node = new MapPolygonNode(); + + //TODO: update only material + if (geometry_.isScreenDirty() || borderGeometry_.isScreenDirty() || dirtyMaterial_) { + node->update(color_, border_.color(), &geometry_, &borderGeometry_); + geometry_.setPreserveGeometry(false); + borderGeometry_.setPreserveGeometry(false); + geometry_.markClean(); + borderGeometry_.markClean(); + dirtyMaterial_ = false; + } + return node; +} + +/*! + \internal +*/ +void QDeclarativePolygonMapItem::updatePolish() +{ + if (!map() || path_.count() == 0) + return; + + QScopedValueRollback rollback(updatingGeometry_); + updatingGeometry_ = true; + + geometry_.updateSourcePoints(*map(), path_); + geometry_.updateScreenPoints(*map()); + + QList closedPath = path_; + closedPath << closedPath.first(); + borderGeometry_.clear(); + borderGeometry_.updateSourcePoints(*map(), closedPath, geoLeftBound_); + + if (border_.color() != Qt::transparent && border_.width() > 0) + borderGeometry_.updateScreenPoints(*map(), border_.width()); + + QList geoms; + geoms << &geometry_ << &borderGeometry_; + QRectF combined = QGeoMapItemGeometry::translateToCommonOrigin(geoms); + + setWidth(combined.width()); + setHeight(combined.height()); + + setPositionOnMap(path_.at(0), -1 * geometry_.sourceBoundingBox().topLeft()); +} + +/*! + \internal +*/ +void QDeclarativePolygonMapItem::afterViewportChanged(const QGeoMapViewportChangeEvent &event) +{ + if (event.mapSize.width() <= 0 || event.mapSize.height() <= 0) + return; + + // if the scene is tilted, we must regenerate our geometry every frame + if (map()->cameraCapabilities().supportsTilting() + && (event.cameraData.tilt() > 0.1 + || event.cameraData.tilt() < -0.1)) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + + // if the scene is rolled, we must regen too + if (map()->cameraCapabilities().supportsRolling() + && (event.cameraData.roll() > 0.1 + || event.cameraData.roll() < -0.1)) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + + // otherwise, only regen on rotate, resize and zoom + if (event.bearingChanged || event.mapSizeChanged || event.zoomLevelChanged) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + geometry_.setPreserveGeometry(true, geometry_.geoLeftBound()); + borderGeometry_.setPreserveGeometry(true, borderGeometry_.geoLeftBound()); + geometry_.markScreenDirty(); + borderGeometry_.markScreenDirty(); + polishAndUpdate(); +} + +/*! + \internal +*/ +bool QDeclarativePolygonMapItem::contains(const QPointF &point) const +{ + return (geometry_.contains(point) || borderGeometry_.contains(point)); +} + +/*! + \internal +*/ +void QDeclarativePolygonMapItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + if (updatingGeometry_ || newGeometry.topLeft() == oldGeometry.topLeft()) { + QDeclarativeGeoMapItemBase::geometryChanged(newGeometry, oldGeometry); + return; + } + + QDoubleVector2D newPoint = QDoubleVector2D(x(),y()) + QDoubleVector2D(geometry_.firstPointOffset()); + QGeoCoordinate newCoordinate = map()->itemPositionToCoordinate(newPoint, false); + if (newCoordinate.isValid()) { + double firstLongitude = path_.at(0).longitude(); + double firstLatitude = path_.at(0).latitude(); + double minMaxLatitude = firstLatitude; + // prevent dragging over valid min and max latitudes + for (int i = 0; i < path_.count(); ++i) { + double newLatitude = path_.at(i).latitude() + + newCoordinate.latitude() - firstLatitude; + if (!QLocationUtils::isValidLat(newLatitude)) { + if (qAbs(newLatitude) > qAbs(minMaxLatitude)) { + minMaxLatitude = newLatitude; + } + } + } + // calculate offset needed to re-position the item within map border + double offsetLatitude = minMaxLatitude - QLocationUtils::clipLat(minMaxLatitude); + for (int i = 0; i < path_.count(); ++i) { + QGeoCoordinate coord = path_.at(i); + // handle dateline crossing + coord.setLongitude(QLocationUtils::wrapLong(coord.longitude() + + newCoordinate.longitude() - firstLongitude)); + coord.setLatitude(coord.latitude() + + newCoordinate.latitude() - firstLatitude - offsetLatitude); + + path_.replace(i, coord); + } + geoLeftBound_.setLongitude(QLocationUtils::wrapLong(geoLeftBound_.longitude() + + newCoordinate.longitude() - firstLongitude)); + geometry_.setPreserveGeometry(true, geoLeftBound_); + borderGeometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); + } + + // Not calling QDeclarativeGeoMapItemBase::geometryChanged() as it will be called from a nested + // call to this function. +} + +////////////////////////////////////////////////////////////////////// + +MapPolygonNode::MapPolygonNode() : + border_(new MapPolylineNode()), + geometry_(QSGGeometry::defaultAttributes_Point2D(), 0), + blocked_(true) +{ + geometry_.setDrawingMode(GL_TRIANGLES); + QSGGeometryNode::setMaterial(&fill_material_); + QSGGeometryNode::setGeometry(&geometry_); + + appendChildNode(border_); +} + +MapPolygonNode::~MapPolygonNode() +{ +} + +/*! + \internal +*/ +bool MapPolygonNode::isSubtreeBlocked() const +{ + return blocked_; +} + +/*! + \internal +*/ +void MapPolygonNode::update(const QColor &fillColor, const QColor &borderColor, + const QGeoMapItemGeometry *fillShape, + const QGeoMapItemGeometry *borderShape) +{ + /* Do the border update first */ + border_->update(borderColor, borderShape); + + /* If we have neither fill nor border with valid points, block the whole + * tree. We can't just block the fill without blocking the border too, so + * we're a little conservative here (maybe at the expense of rendering + * accuracy) */ + if (fillShape->size() == 0) { + if (borderShape->size() == 0) { + blocked_ = true; + return; + } else { + blocked_ = false; + } + } else { + blocked_ = false; + } + + QSGGeometry *fill = QSGGeometryNode::geometry(); + fillShape->allocateAndFill(fill); + markDirty(DirtyGeometry); + + if (fillColor != fill_material_.color()) { + fill_material_.setColor(fillColor); + setMaterial(&fill_material_); + markDirty(DirtyMaterial); + } +} +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativepolygonmapitem_p.h b/src/imports/location/qdeclarativepolygonmapitem_p.h new file mode 100644 index 0000000..19ac508 --- /dev/null +++ b/src/imports/location/qdeclarativepolygonmapitem_p.h @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPOLYGONMAPITEM +#define QDECLARATIVEPOLYGONMAPITEM + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeomapitembase_p.h" +#include "qdeclarativepolylinemapitem_p.h" +#include "qgeomapitemgeometry_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class MapPolygonNode; + +class QGeoMapPolygonGeometry : public QGeoMapItemGeometry +{ +public: + QGeoMapPolygonGeometry(); + + inline void setAssumeSimple(bool value) { assumeSimple_ = value; } + + void updateSourcePoints(const QGeoMap &map, + const QList &path); + + void updateScreenPoints(const QGeoMap &map); + +protected: + QPainterPath srcPath_; + bool assumeSimple_; +}; + +class QDeclarativePolygonMapItem : public QDeclarativeGeoMapItemBase +{ + Q_OBJECT + + Q_PROPERTY(QJSValue path READ path WRITE setPath NOTIFY pathChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + Q_PROPERTY(QDeclarativeMapLineProperties *border READ border CONSTANT) + +public: + explicit QDeclarativePolygonMapItem(QQuickItem *parent = 0); + ~QDeclarativePolygonMapItem(); + + virtual void setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) Q_DECL_OVERRIDE; + //from QuickItem + virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; + + Q_INVOKABLE void addCoordinate(const QGeoCoordinate &coordinate); + Q_INVOKABLE void removeCoordinate(const QGeoCoordinate &coordinate); + + QJSValue path() const; + void setPath(const QJSValue &value); + + QColor color() const; + void setColor(const QColor &color); + + QDeclarativeMapLineProperties *border(); + + bool contains(const QPointF &point) const Q_DECL_OVERRIDE; + +Q_SIGNALS: + void pathChanged(); + void colorChanged(const QColor &color); + +protected: + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void updatePolish() Q_DECL_OVERRIDE; + +protected Q_SLOTS: + void handleBorderUpdated(); + virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; + +private: + void pathPropertyChanged(); + + QDeclarativeMapLineProperties border_; + QList path_; + QGeoCoordinate geoLeftBound_; + QColor color_; + bool dirtyMaterial_; + QGeoMapPolygonGeometry geometry_; + QGeoMapPolylineGeometry borderGeometry_; + bool updatingGeometry_; + // for the left bound calculation + QVector deltaXs_; // longitude deltas from path_[0] + double minX_; // minimum value inside deltaXs_ +}; + +////////////////////////////////////////////////////////////////////// + +class MapPolygonNode : public QSGGeometryNode +{ + +public: + MapPolygonNode(); + ~MapPolygonNode(); + + void update(const QColor &fillColor, const QColor &borderColor, + const QGeoMapItemGeometry *fillShape, + const QGeoMapItemGeometry *borderShape); + + bool isSubtreeBlocked() const; + +private: + QSGFlatColorMaterial fill_material_; + MapPolylineNode *border_; + QSGGeometry geometry_; + bool blocked_; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativePolygonMapItem) + +#endif /* QDECLARATIVEPOLYGONMAPITEM_H_ */ diff --git a/src/imports/location/qdeclarativepolylinemapitem.cpp b/src/imports/location/qdeclarativepolylinemapitem.cpp new file mode 100644 index 0000000..3c29ad2 --- /dev/null +++ b/src/imports/location/qdeclarativepolylinemapitem.cpp @@ -0,0 +1,1013 @@ +/**************************************************************************** + ** + ** Copyright (C) 2015 The Qt Company Ltd. + ** Contact: http://www.qt.io/licensing/ + ** + ** This file is part of the QtLocation module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL3$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see http://www.qt.io/terms-conditions. For further + ** information use the contact form at http://www.qt.io/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 3 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPLv3 included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 3 requirements + ** will be met: https://www.gnu.org/licenses/lgpl.html. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 2.0 or later as published by the Free + ** Software Foundation and appearing in the file LICENSE.GPL included in + ** the packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 2.0 requirements will be + ** met: http://www.gnu.org/licenses/gpl-2.0.html. + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include "qdeclarativepolylinemapitem_p.h" +#include "qgeocameracapabilities_p.h" +#include "qlocationutils_p.h" +#include "error_messages.h" +#include "locationvaluetypehelper_p.h" +#include "qdoublevector2d_p.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype MapPolyline + \instantiates QDeclarativePolylineMapItem + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.0 + + \brief The MapPolyline type displays a polyline on a map. + + The MapPolyline type displays a polyline on a map, specified in terms of an ordered list of + \l {coordinate}{coordinates}. The \l {coordinate}{coordinates} on + the path cannot be directly changed after being added to the Polyline. Instead, copy the + \l path into a var, modify the copy and reassign the copy back to the \l path. + + \code + var path = mapPolyline.path; + path[0].latitude = 5; + mapPolyline.path = path; + \endcode + + Coordinates can also be added and removed at any time using the \l addCoordinate and + \l removeCoordinate methods. + + By default, the polyline is displayed as a 1-pixel thick black line. This + can be changed using the \l line.width and \l line.color properties. + + \section2 Performance + + MapPolylines have a rendering cost that is O(n) with respect to the number + of vertices. This means that the per frame cost of having a polyline on + the Map grows in direct proportion to the number of points in the polyline. + + Like the other map objects, MapPolyline is normally drawn without a smooth + appearance. Setting the \l {Item::opacity}{opacity} property will force the object to + be blended, which decreases performance considerably depending on the hardware in use. + + \note MapPolylines are implemented using the OpenGL GL_LINES + primitive. There have been occasional reports of issues and rendering + inconsistencies on some (particularly quite old) platforms. No workaround + is yet available for these issues. + + \section2 Example Usage + + The following snippet shows a MapPolyline with 4 points, making a shape + like the top part of a "question mark" (?), near Brisbane, Australia. + The line drawn is 3 pixels in width and green in color. + + \code + Map { + MapPolyline { + line.width: 3 + line.color: 'green' + path: [ + { latitude: -27, longitude: 153.0 }, + { latitude: -27, longitude: 154.1 }, + { latitude: -28, longitude: 153.5 }, + { latitude: -29, longitude: 153.5 } + ] + } + } + \endcode + + \image api-mappolyline.png +*/ + +QDeclarativeMapLineProperties::QDeclarativeMapLineProperties(QObject *parent) : + QObject(parent), + width_(1.0), + color_(Qt::black) +{ +} + +/*! + \internal +*/ +QColor QDeclarativeMapLineProperties::color() const +{ + return color_; +} + +/*! + \internal +*/ +void QDeclarativeMapLineProperties::setColor(const QColor &color) +{ + if (color_ == color) + return; + + color_ = color; + emit colorChanged(color_); +} + +/*! + \internal +*/ +qreal QDeclarativeMapLineProperties::width() const +{ + return width_; +} + +/*! + \internal +*/ +void QDeclarativeMapLineProperties::setWidth(qreal width) +{ + if (width_ == width) + return; + + width_ = width; + emit widthChanged(width_); +} + +struct Vertex +{ + QVector2D position; +}; + +QGeoMapPolylineGeometry::QGeoMapPolylineGeometry() +{ +} + +/*! + \internal +*/ +void QGeoMapPolylineGeometry::updateSourcePoints(const QGeoMap &map, + const QList &path, + const QGeoCoordinate geoLeftBound) +{ + bool foundValid = false; + double minX = -1.0; + double minY = -1.0; + double maxX = -1.0; + double maxY = -1.0; + + if (!sourceDirty_) + return; + + geoLeftBound_ = geoLeftBound; + + // clear the old data and reserve enough memory + srcPoints_.clear(); + srcPoints_.reserve(path.size() * 2); + srcPointTypes_.clear(); + srcPointTypes_.reserve(path.size()); + + QDoubleVector2D origin, lastPoint, lastAddedPoint; + + const double mapWidthHalf = map.width()/2.0; + double unwrapBelowX = 0; + if (preserveGeometry_) + unwrapBelowX = map.coordinateToItemPosition(geoLeftBound_, false).x(); + + for (int i = 0; i < path.size(); ++i) { + const QGeoCoordinate &coord = path.at(i); + + if (!coord.isValid()) + continue; + + QDoubleVector2D point = map.coordinateToItemPosition(coord, false); + + // We can get NaN if the map isn't set up correctly, or the projection + // is faulty -- probably best thing to do is abort + if (!qIsFinite(point.x()) || !qIsFinite(point.y())) + return; + + bool isPointLessThanUnwrapBelowX = (point.x() < unwrapBelowX); + bool isCoordNotLeftBound = !qFuzzyCompare(geoLeftBound_.longitude(), coord.longitude()); + bool isPointNotUnwrapBelowX = !qFuzzyCompare(point.x(), unwrapBelowX); + bool isPointNotMapWidthHalf = !qFuzzyCompare(mapWidthHalf, point.x()); + + // unwrap x to preserve geometry if moved to border of map + if (preserveGeometry_ && isPointLessThanUnwrapBelowX + && isCoordNotLeftBound + && isPointNotUnwrapBelowX + && isPointNotMapWidthHalf) { + double distance = geoDistanceToScreenWidth(map, geoLeftBound_, coord); + point.setX(unwrapBelowX + distance); + } + + if (!foundValid) { + foundValid = true; + srcOrigin_ = coord; // TODO: Make this consistent with the left bound + origin = point; + point = QDoubleVector2D(0,0); + + minX = point.x(); + maxX = minX; + minY = point.y(); + maxY = minY; + + srcPoints_ << point.x() << point.y(); + srcPointTypes_ << QPainterPath::MoveToElement; + lastAddedPoint = point; + } else { + point -= origin; + + minX = qMin(point.x(), minX); + minY = qMin(point.y(), minY); + maxX = qMax(point.x(), maxX); + maxY = qMax(point.y(), maxY); + + if ((point - lastAddedPoint).manhattanLength() > 3 || + i == path.size() - 1) { + srcPoints_ << point.x() << point.y(); + srcPointTypes_ << QPainterPath::LineToElement; + lastAddedPoint = point; + } + } + + lastPoint = point; + } + + sourceBounds_ = QRectF(QPointF(minX, minY), QPointF(maxX, maxY)); +} + +//////////////////////////////////////////////////////////////////////////// +/* Polyline clip */ + +enum ClipPointType { + InsidePoint = 0x00, + LeftPoint = 0x01, + RightPoint = 0x02, + BottomPoint = 0x04, + TopPoint = 0x08 +}; + +static inline int clipPointType(qreal x, qreal y, const QRectF &rect) +{ + int type = InsidePoint; + if (x < rect.left()) + type |= LeftPoint; + else if (x > rect.right()) + type |= RightPoint; + if (y < rect.top()) + type |= TopPoint; + else if (y > rect.bottom()) + type |= BottomPoint; + return type; +} + +static void clipSegmentToRect(qreal x0, qreal y0, qreal x1, qreal y1, + const QRectF &clipRect, + QVector &outPoints, + QVector &outTypes) +{ + int type0 = clipPointType(x0, y0, clipRect); + int type1 = clipPointType(x1, y1, clipRect); + bool accept = false; + + while (true) { + if (!(type0 | type1)) { + accept = true; + break; + } else if (type0 & type1) { + break; + } else { + qreal x = 0.0; + qreal y = 0.0; + int outsideType = type0 ? type0 : type1; + + if (outsideType & BottomPoint) { + x = x0 + (x1 - x0) * (clipRect.bottom() - y0) / (y1 - y0); + y = clipRect.bottom() - 0.1; + } else if (outsideType & TopPoint) { + x = x0 + (x1 - x0) * (clipRect.top() - y0) / (y1 - y0); + y = clipRect.top() + 0.1; + } else if (outsideType & RightPoint) { + y = y0 + (y1 - y0) * (clipRect.right() - x0) / (x1 - x0); + x = clipRect.right() - 0.1; + } else if (outsideType & LeftPoint) { + y = y0 + (y1 - y0) * (clipRect.left() - x0) / (x1 - x0); + x = clipRect.left() + 0.1; + } + + if (outsideType == type0) { + x0 = x; + y0 = y; + type0 = clipPointType(x0, y0, clipRect); + } else { + x1 = x; + y1 = y; + type1 = clipPointType(x1, y1, clipRect); + } + } + } + + if (accept) { + if (outPoints.size() >= 2) { + qreal lastX, lastY; + lastY = outPoints.at(outPoints.size() - 1); + lastX = outPoints.at(outPoints.size() - 2); + + if (!qFuzzyCompare(lastY, y0) || !qFuzzyCompare(lastX, x0)) { + outTypes << QPainterPath::MoveToElement; + outPoints << x0 << y0; + } + } else { + outTypes << QPainterPath::MoveToElement; + outPoints << x0 << y0; + } + + outTypes << QPainterPath::LineToElement; + outPoints << x1 << y1; + } +} + +static void clipPathToRect(const QVector &points, + const QVector &types, + const QRectF &clipRect, + QVector &outPoints, + QVector &outTypes) +{ + outPoints.clear(); + outPoints.reserve(points.size()); + outTypes.clear(); + outTypes.reserve(types.size()); + + qreal lastX, lastY; + for (int i = 0; i < types.size(); ++i) { + if (i > 0 && types[i] != QPainterPath::MoveToElement) { + qreal x = points[i * 2], y = points[i * 2 + 1]; + clipSegmentToRect(lastX, lastY, x, y, clipRect, outPoints, outTypes); + } + + lastX = points[i * 2]; + lastY = points[i * 2 + 1]; + } +} + +/*! + \internal +*/ +void QGeoMapPolylineGeometry::updateScreenPoints(const QGeoMap &map, + qreal strokeWidth) +{ + if (!screenDirty_) + return; + + QPointF origin = map.coordinateToItemPosition(srcOrigin_, false).toPointF(); + + if (!qIsFinite(origin.x()) || !qIsFinite(origin.y())) { + clear(); + return; + } + + // Create the viewport rect in the same coordinate system + // as the actual points + QRectF viewport(0, 0, map.width(), map.height()); + viewport.adjust(-strokeWidth, -strokeWidth, strokeWidth, strokeWidth); + viewport.translate(-1 * origin); + + // Perform clipping to the viewport limits + QVector points; + QVector types; + + if (clipToViewport_) { + clipPathToRect(srcPoints_, srcPointTypes_, viewport, points, types); + } else { + points = srcPoints_; + types = srcPointTypes_; + } + + QVectorPath vp(points.data(), types.size(), types.data()); + QTriangulatingStroker ts; + ts.process(vp, QPen(QBrush(Qt::black), strokeWidth), viewport, QPainter::Qt4CompatiblePainting); + + clear(); + + // Nothing is on the screen + if (ts.vertexCount() == 0) + return; + + // QTriangulatingStroker#vertexCount is actually the length of the array, + // not the number of vertices + screenVertices_.reserve(ts.vertexCount()); + + QRectF bb; + + QPointF pt; + const float *vs = ts.vertices(); + for (int i = 0; i < (ts.vertexCount()/2*2); i += 2) { + pt = QPointF(vs[i], vs[i + 1]); + screenVertices_ << pt; + + if (!qIsFinite(pt.x()) || !qIsFinite(pt.y())) + break; + + if (!bb.contains(pt)) { + if (pt.x() < bb.left()) + bb.setLeft(pt.x()); + + if (pt.x() > bb.right()) + bb.setRight(pt.x()); + + if (pt.y() < bb.top()) + bb.setTop(pt.y()); + + if (pt.y() > bb.bottom()) + bb.setBottom(pt.y()); + } + } + + screenBounds_ = bb; + this->translate( -1 * sourceBounds_.topLeft()); +} + +QDeclarativePolylineMapItem::QDeclarativePolylineMapItem(QQuickItem *parent) +: QDeclarativeGeoMapItemBase(parent), dirtyMaterial_(true), updatingGeometry_(false) +{ + setFlag(ItemHasContents, true); + QObject::connect(&line_, SIGNAL(colorChanged(QColor)), + this, SLOT(updateAfterLinePropertiesChanged())); + QObject::connect(&line_, SIGNAL(widthChanged(qreal)), + this, SLOT(updateAfterLinePropertiesChanged())); +} + +QDeclarativePolylineMapItem::~QDeclarativePolylineMapItem() +{ +} + +/*! + \internal +*/ +void QDeclarativePolylineMapItem::updateAfterLinePropertiesChanged() +{ + // mark dirty just in case we're a width change + geometry_.markSourceDirty(); + polishAndUpdate(); +} + +/*! + \internal +*/ +void QDeclarativePolylineMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) +{ + QDeclarativeGeoMapItemBase::setMap(quickMap,map); + if (map) { + geometry_.markSourceDirty(); + polishAndUpdate(); + } +} + +/*! + \qmlproperty list MapPolyline::path + + This property holds the ordered list of coordinates which + define the polyline. +*/ + +QJSValue QDeclarativePolylineMapItem::path() const +{ + QQmlContext *context = QQmlEngine::contextForObject(this); + if (!context) + return QJSValue(); + QQmlEngine *engine = context->engine(); + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); + + QV4::Scope scope(v4); + QV4::Scoped pathArray(scope, v4->newArrayObject(path_.length())); + for (int i = 0; i < path_.length(); ++i) { + const QGeoCoordinate &c = path_.at(i); + + QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(c))); + pathArray->putIndexed(i, cv); + } + + return QJSValue(v4, pathArray.asReturnedValue()); +} + +void QDeclarativePolylineMapItem::setPath(const QJSValue &value) +{ + if (!value.isArray()) + return; + + QList pathList; + quint32 length = value.property(QStringLiteral("length")).toUInt(); + for (quint32 i = 0; i < length; ++i) { + bool ok; + QGeoCoordinate c = parseCoordinate(value.property(i), &ok); + + if (!ok || !c.isValid()) { + qmlInfo(this) << "Unsupported path type"; + return; + } + + pathList.append(c); + } + + setPathFromGeoList(pathList); +} + +/*! + \internal +*/ +void QDeclarativePolylineMapItem::setPathFromGeoList(const QList &path) +{ + if (path_ == path) + return; + + path_ = path; + geoLeftBound_ = getLeftBound(path_, deltaXs_, minX_); + geometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlmethod int MapPolyline::pathLength() + + Returns the number of coordinates of the polyline. + + \since Qt Location 5.6 + + \sa path +*/ +int QDeclarativePolylineMapItem::pathLength() const +{ + return path_.size(); +} + +/*! + \qmlmethod void MapPolyline::addCoordinate(coordinate) + + Adds a coordinate to the end of the path. + + \sa insertCoordinate, removeCoordinate, path +*/ +void QDeclarativePolylineMapItem::addCoordinate(const QGeoCoordinate &coordinate) +{ + path_.append(coordinate); + geoLeftBound_ = getLeftBound(path_, deltaXs_, minX_, geoLeftBound_); + geometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlmethod void MapPolyline::insertCoordinate(index, coordinate) + + Inserts a \a coordinate to the path at the given \a index. + + \since Qt Location 5.6 + + \sa addCoordinate, removeCoordinate, path +*/ +void QDeclarativePolylineMapItem::insertCoordinate(int index, const QGeoCoordinate &coordinate) +{ + if (index < 0 || index > path_.size()) + return; + + path_.insert(index, coordinate); + geoLeftBound_ = getLeftBound(path_, deltaXs_, minX_); + geometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlmethod void MapPolyline::replaceCoordinate(index, coordinate) + + Replaces the coordinate in the current path at the given \a index + with the new \a coordinate. + + \since Qt Location 5.6 + + \sa addCoordinate, insertCoordinate, removeCoordinate, path +*/ +void QDeclarativePolylineMapItem::replaceCoordinate(int index, const QGeoCoordinate &coordinate) +{ + if (index < 0 || index >= path_.size()) + return; + + path_[index] = coordinate; + geoLeftBound_ = getLeftBound(path_, deltaXs_, minX_); + geometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlmethod coordinate MapPolyline::coordinateAt(index) + + Gets the coordinate of the polyline at the given \a index. + If the index is outside the path's bounds then an invalid + coordinate is returned. + + \since Qt Location 5.6 +*/ +QGeoCoordinate QDeclarativePolylineMapItem::coordinateAt(int index) const +{ + if (index < 0 || index >= path_.size()) + return QGeoCoordinate(); + + return path_.at(index); +} + +/*! + \qmlmethod coordinate MapPolyline::containsCoordinate(coordinate) + + Returns true if the given \a coordinate is part of the path. + + \since Qt Location 5.6 +*/ +bool QDeclarativePolylineMapItem::containsCoordinate(const QGeoCoordinate &coordinate) +{ + return path_.indexOf(coordinate) > -1; +} + +/*! + \qmlmethod void MapPolyline::removeCoordinate(coordinate) + + Removes \a coordinate from the path. If there are multiple instances of the + same coordinate, the one added last is removed. + + If \a coordinate is not in the path this method does nothing. + + \sa addCoordinate, insertCoordinate, path +*/ +void QDeclarativePolylineMapItem::removeCoordinate(const QGeoCoordinate &coordinate) +{ + int index = path_.lastIndexOf(coordinate); + removeCoordinate(index); +} + +/*! + \qmlmethod void MapPolyline::removeCoordinate(index) + + Removes a coordinate from the path at the given \a index. + + If \a index is invalid then this method does nothing. + + \since Qt Location 5.6 + + \sa addCoordinate, insertCoordinate, path +*/ +void QDeclarativePolylineMapItem::removeCoordinate(int index) +{ + if (index < 0 || index >= path_.size()) + return; + + path_.removeAt(index); + geoLeftBound_ = getLeftBound(path_, deltaXs_, minX_); + geometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlpropertygroup Location::MapPolyline::line + \qmlproperty int MapPolyline::line.width + \qmlproperty color MapPolyline::line.color + + This property is part of the line property group. The line + property group holds the width and color used to draw the line. + + The width is in pixels and is independent of the zoom level of the map. + The default values correspond to a black border with a width of 1 pixel. + + For no line, use a width of 0 or a transparent color. +*/ + +QDeclarativeMapLineProperties *QDeclarativePolylineMapItem::line() +{ + return &line_; +} + +QGeoCoordinate QDeclarativePolylineMapItem::computeLeftBound(const QList &path, + QVector &deltaXs, + double &minX) +{ + if (path.isEmpty()) { + minX = qInf(); + return QGeoCoordinate(); + } + deltaXs.resize(path.size()); + + deltaXs[0] = minX = 0.0; + int minId = 0; + + for (int i = 1; i < path.size(); i++) { + const QGeoCoordinate &geoFrom = path.at(i-1); + const QGeoCoordinate &geoTo = path.at(i); + double longiFrom = geoFrom.longitude(); + double longiTo = geoTo.longitude(); + double deltaLongi = longiTo - longiFrom; + if (qAbs(deltaLongi) > 180.0) { + if (longiTo > 0.0) + longiTo -= 360.0; + else + longiTo += 360.0; + deltaLongi = longiTo - longiFrom; + } + deltaXs[i] = deltaXs[i-1] + deltaLongi; + if (deltaXs[i] < minX) { + minX = deltaXs[i]; + minId = i; + } + } + return path.at(minId); +} + +QGeoCoordinate QDeclarativePolylineMapItem::updateLeftBound(const QList &path, + QVector &deltaXs, + double &minX, + QGeoCoordinate currentLeftBound) +{ + if (path.isEmpty()) { + deltaXs.clear(); + minX = qInf(); + return QGeoCoordinate(); + } else if (path.size() == 1) { + deltaXs.resize(1); + deltaXs[0] = minX = 0.0; + return path.last(); + } else if ( path.size() != deltaXs.size() + 1 ) { // something went wrong. This case should not happen + return computeLeftBound(path, deltaXs, minX); + } + + const QGeoCoordinate &geoFrom = path.at(path.size()-2); + const QGeoCoordinate &geoTo = path.last(); + double longiFrom = geoFrom.longitude(); + double longiTo = geoTo.longitude(); + double deltaLongi = longiTo - longiFrom; + if (qAbs(deltaLongi) > 180.0) { + if (longiTo > 0.0) + longiTo -= 360.0; + else + longiTo += 360.0; + deltaLongi = longiTo - longiFrom; + } + + deltaXs.push_back(deltaXs.last() + deltaLongi); + if (deltaXs.last() < minX) { + minX = deltaXs.last(); + return path.last(); + } else { + return currentLeftBound; + } +} + +QGeoCoordinate QDeclarativePolylineMapItem::getLeftBound(const QList &path, + QVector &deltaXs, + double &minX) +{ + return QDeclarativePolylineMapItem::computeLeftBound(path, deltaXs, minX); +} + +// Optimizing the common addCoordinate() path +QGeoCoordinate QDeclarativePolylineMapItem::getLeftBound(const QList &path, + QVector &deltaXs, + double &minX, + QGeoCoordinate currentLeftBound) +{ + return QDeclarativePolylineMapItem::updateLeftBound(path, deltaXs, minX, currentLeftBound); +} + +/*! + \internal +*/ +void QDeclarativePolylineMapItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + if (updatingGeometry_ || newGeometry.topLeft() == oldGeometry.topLeft()) { + QDeclarativeGeoMapItemBase::geometryChanged(newGeometry, oldGeometry); + return; + } + + QDoubleVector2D newPoint = QDoubleVector2D(x(),y()) + QDoubleVector2D(geometry_.firstPointOffset()); + QGeoCoordinate newCoordinate = map()->itemPositionToCoordinate(newPoint, false); + if (newCoordinate.isValid()) { + double firstLongitude = path_.at(0).longitude(); + double firstLatitude = path_.at(0).latitude(); + double minMaxLatitude = firstLatitude; + // prevent dragging over valid min and max latitudes + for (int i = 0; i < path_.count(); ++i) { + double newLatitude = path_.at(i).latitude() + + newCoordinate.latitude() - firstLatitude; + if (!QLocationUtils::isValidLat(newLatitude)) { + if (qAbs(newLatitude) > qAbs(minMaxLatitude)) { + minMaxLatitude = newLatitude; + } + } + } + // calculate offset needed to re-position the item within map border + double offsetLatitude = minMaxLatitude - QLocationUtils::clipLat(minMaxLatitude); + for (int i = 0; i < path_.count(); ++i) { + QGeoCoordinate coord = path_.at(i); + // handle dateline crossing + coord.setLongitude(QLocationUtils::wrapLong(coord.longitude() + + newCoordinate.longitude() - firstLongitude)); + coord.setLatitude(coord.latitude() + + newCoordinate.latitude() - firstLatitude - offsetLatitude); + path_.replace(i, coord); + } + + geoLeftBound_.setLongitude(QLocationUtils::wrapLong(geoLeftBound_.longitude() + + newCoordinate.longitude() - firstLongitude)); + geometry_.setPreserveGeometry(true, geoLeftBound_); + geometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); + } + + // Not calling QDeclarativeGeoMapItemBase::geometryChanged() as it will be called from a nested + // call to this function. +} + +/*! + \internal +*/ +void QDeclarativePolylineMapItem::afterViewportChanged(const QGeoMapViewportChangeEvent &event) +{ + if (event.mapSize.width() <= 0 || event.mapSize.height() <= 0) + return; + + // if the scene is tilted, we must regenerate our geometry every frame + if (map()->cameraCapabilities().supportsTilting() + && (event.cameraData.tilt() > 0.1 + || event.cameraData.tilt() < -0.1)) { + geometry_.markSourceDirty(); + } + + // if the scene is rolled, we must regen too + if (map()->cameraCapabilities().supportsRolling() + && (event.cameraData.roll() > 0.1 + || event.cameraData.roll() < -0.1)) { + geometry_.markSourceDirty(); + } + + // otherwise, only regen on rotate, resize and zoom + if (event.bearingChanged || event.mapSizeChanged || event.zoomLevelChanged) { + geometry_.markSourceDirty(); + } + geometry_.setPreserveGeometry(true, geometry_.geoLeftBound()); + geometry_.markScreenDirty(); + polishAndUpdate(); +} + +/*! + \internal +*/ +void QDeclarativePolylineMapItem::updatePolish() +{ + if (!map() || path_.count() == 0) + return; + + QScopedValueRollback rollback(updatingGeometry_); + updatingGeometry_ = true; + + geometry_.updateSourcePoints(*map(), path_, geoLeftBound_); + geometry_.updateScreenPoints(*map(), line_.width()); + + setWidth(geometry_.sourceBoundingBox().width()); + setHeight(geometry_.sourceBoundingBox().height()); + + setPositionOnMap(path_.at(0), -1 * geometry_.sourceBoundingBox().topLeft()); +} + +/*! + \internal +*/ +QSGNode *QDeclarativePolylineMapItem::updateMapItemPaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) +{ + Q_UNUSED(data); + + MapPolylineNode *node = static_cast(oldNode); + + if (!node) { + node = new MapPolylineNode(); + } + + //TODO: update only material + if (geometry_.isScreenDirty() || dirtyMaterial_ || !oldNode) { + node->update(line_.color(), &geometry_); + geometry_.setPreserveGeometry(false); + geometry_.markClean(); + dirtyMaterial_ = false; + } + return node; +} + +bool QDeclarativePolylineMapItem::contains(const QPointF &point) const +{ + QVector vertices = geometry_.vertices(); + QPolygonF tri; + for (int i = 0; i < vertices.size(); ++i) { + tri << vertices[i]; + if (tri.size() == 3) { + if (tri.containsPoint(point,Qt::OddEvenFill)) + return true; + tri.remove(0); + } + } + + return false; +} + +////////////////////////////////////////////////////////////////////// + +/*! + \internal +*/ +MapPolylineNode::MapPolylineNode() : + geometry_(QSGGeometry::defaultAttributes_Point2D(),0), + blocked_(true) +{ + geometry_.setDrawingMode(GL_TRIANGLE_STRIP); + QSGGeometryNode::setMaterial(&fill_material_); + QSGGeometryNode::setGeometry(&geometry_); +} + + +/*! + \internal +*/ +MapPolylineNode::~MapPolylineNode() +{ +} + +/*! + \internal +*/ +bool MapPolylineNode::isSubtreeBlocked() const +{ + return blocked_; +} + +/*! + \internal +*/ +void MapPolylineNode::update(const QColor &fillColor, + const QGeoMapItemGeometry *shape) +{ + if (shape->size() == 0) { + blocked_ = true; + return; + } else { + blocked_ = false; + } + + QSGGeometry *fill = QSGGeometryNode::geometry(); + shape->allocateAndFill(fill); + markDirty(DirtyGeometry); + + if (fillColor != fill_material_.color()) { + fill_material_.setColor(fillColor); + setMaterial(&fill_material_); + markDirty(DirtyMaterial); + } +} + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativepolylinemapitem_p.h b/src/imports/location/qdeclarativepolylinemapitem_p.h new file mode 100644 index 0000000..8c827b6 --- /dev/null +++ b/src/imports/location/qdeclarativepolylinemapitem_p.h @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPOLYLINEMAPITEM +#define QDECLARATIVEPOLYLINEMAPITEM + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeomapitembase_p.h" +#include "qgeomapitemgeometry_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class MapPolylineNode; + +class QDeclarativeMapLineProperties : public QObject +{ + Q_OBJECT + + Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + +public: + explicit QDeclarativeMapLineProperties(QObject *parent = 0); + + QColor color() const; + void setColor(const QColor &color); + + qreal width() const; + void setWidth(qreal width); + +Q_SIGNALS: + void widthChanged(qreal width); + void colorChanged(const QColor &color); + +private: + qreal width_; + QColor color_; +}; + +class QGeoMapPolylineGeometry : public QGeoMapItemGeometry +{ +public: + QGeoMapPolylineGeometry(); + + void updateSourcePoints(const QGeoMap &map, + const QList &path, + const QGeoCoordinate geoLeftBound); + + void updateScreenPoints(const QGeoMap &map, + qreal strokeWidth); + +private: + QVector srcPoints_; + QVector srcPointTypes_; + + +}; + +class QDeclarativePolylineMapItem : public QDeclarativeGeoMapItemBase +{ + Q_OBJECT + + Q_PROPERTY(QJSValue path READ path WRITE setPath NOTIFY pathChanged) + Q_PROPERTY(QDeclarativeMapLineProperties *line READ line CONSTANT) + +public: + explicit QDeclarativePolylineMapItem(QQuickItem *parent = 0); + ~QDeclarativePolylineMapItem(); + + virtual void setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) Q_DECL_OVERRIDE; + //from QuickItem + virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; + + Q_INVOKABLE int pathLength() const; + Q_INVOKABLE void addCoordinate(const QGeoCoordinate &coordinate); + Q_INVOKABLE void insertCoordinate(int index, const QGeoCoordinate &coordinate); + Q_INVOKABLE void replaceCoordinate(int index, const QGeoCoordinate &coordinate); + Q_INVOKABLE QGeoCoordinate coordinateAt(int index) const; + Q_INVOKABLE bool containsCoordinate(const QGeoCoordinate &coordinate); + Q_INVOKABLE void removeCoordinate(const QGeoCoordinate &coordinate); + Q_INVOKABLE void removeCoordinate(int index); + + QJSValue path() const; + virtual void setPath(const QJSValue &value); + + bool contains(const QPointF &point) const Q_DECL_OVERRIDE; + + QDeclarativeMapLineProperties *line(); + + static QGeoCoordinate computeLeftBound(const QList &path, QVector &deltaXs, double &minX); + static QGeoCoordinate updateLeftBound(const QList &path, QVector &deltaXs, double &minX, QGeoCoordinate currentLeftBound); + static QGeoCoordinate getLeftBound(const QList &path, QVector &deltaXs, double &minX); + static QGeoCoordinate getLeftBound(const QList &path, QVector &deltaXs, double &minX, QGeoCoordinate currentLeftBound); + +Q_SIGNALS: + void pathChanged(); + +protected: + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void setPathFromGeoList(const QList &path); + void updatePolish() Q_DECL_OVERRIDE; + +protected Q_SLOTS: + void updateAfterLinePropertiesChanged(); + virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; + +private: + void pathPropertyChanged(); + + QDeclarativeMapLineProperties line_; + QList path_; + QGeoCoordinate geoLeftBound_; + QColor color_; + bool dirtyMaterial_; + QGeoMapPolylineGeometry geometry_; + bool updatingGeometry_; + // for the left bound calculation + QVector deltaXs_; // longitude deltas from path_[0] + double minX_; // minimum value inside deltaXs_ +}; + +////////////////////////////////////////////////////////////////////// + +class MapPolylineNode : public QSGGeometryNode +{ + +public: + MapPolylineNode(); + ~MapPolylineNode(); + + void update(const QColor &fillColor, const QGeoMapItemGeometry *shape); + bool isSubtreeBlocked() const; + +private: + QSGFlatColorMaterial fill_material_; + QSGGeometry geometry_; + bool blocked_; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeMapLineProperties) +QML_DECLARE_TYPE(QDeclarativePolylineMapItem) + +#endif /* QDECLARATIVEPOLYLINEMAPITEM_H_ */ diff --git a/src/imports/location/qdeclarativerectanglemapitem.cpp b/src/imports/location/qdeclarativerectanglemapitem.cpp new file mode 100644 index 0000000..f50d034 --- /dev/null +++ b/src/imports/location/qdeclarativerectanglemapitem.cpp @@ -0,0 +1,452 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativerectanglemapitem_p.h" +#include "qdeclarativepolygonmapitem_p.h" +#include "qgeocameracapabilities_p.h" +#include "qlocationutils_p.h" +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype MapRectangle + \instantiates QDeclarativeRectangleMapItem + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.5 + + \brief The MapRectangle type displays a rectangle on a Map. + + The MapRectangle type displays a rectangle on a Map. Rectangles are a + special case of Polygon with exactly 4 vertices and 4 "straight" edges. In + this case, "straight" means that the top-left point has the same latitude + as the top-right point (the top edge), and the bottom-left point has the + same latitude as the bottom-right point (the bottom edge). Similarly, the + points on the left side have the same longitude, and the points on the + right side have the same longitude. + + To specify the rectangle, it requires a \l topLeft and \l bottomRight point, + both given by a \l {coordinate}. + + By default, the rectangle is displayed with transparent fill and a 1-pixel + thick black border. This can be changed using the \l color, \l border.color + and \l border.width properties. + + \note Similar to the \l MapPolygon type, MapRectangles are geographic + items, thus dragging a MapRectangle causes its vertices to be recalculated + in the geographic coordinate space. Apparent stretching of the item + occurs when dragged to the a different latitude, however, its edges + remain straight. + + \section2 Performance + + MapRectangles have a rendering cost identical to a MapPolygon with 4 + vertices. + + Like the other map objects, MapRectangle is normally drawn without a smooth + appearance. Setting the \l opacity property will force the object to be + blended, which decreases performance considerably depending on the hardware + in use. + + \section2 Example Usage + + The following snippet shows a map containing a MapRectangle, spanning + from (-27, 153) to (-28, 153.5), near Brisbane, Australia. The rectangle + is filled in green, with a 2 pixel black border. + + \code + Map { + MapRectangle { + color: 'green' + border.width: 2 + topLeft { + latitude: -27 + longitude: 153 + } + bottomRight { + latitude: -28 + longitude: 153.5 + } + } + } + \endcode + + \image api-maprectangle.png +*/ + +struct Vertex +{ + QVector2D position; +}; + +QGeoMapRectangleGeometry::QGeoMapRectangleGeometry() +{ +} + +/*! + \internal +*/ +void QGeoMapRectangleGeometry::updatePoints(const QGeoMap &map, + const QGeoCoordinate &topLeft, + const QGeoCoordinate &bottomRight) +{ + if (!screenDirty_ && !sourceDirty_) + return; + + QDoubleVector2D tl = map.coordinateToItemPosition(topLeft, false); + QDoubleVector2D br = map.coordinateToItemPosition(bottomRight, false); + + // We can get NaN if the map isn't set up correctly, or the projection + // is faulty -- probably best thing to do is abort + if (!qIsFinite(tl.x()) || !qIsFinite(tl.y())) + return; + if (!qIsFinite(br.x()) || !qIsFinite(br.y())) + return; + + if ( preserveGeometry_ ) { + double unwrapBelowX = map.coordinateToItemPosition(geoLeftBound_, false).x(); + if (br.x() < unwrapBelowX) + br.setX(tl.x() + screenBounds_.width()); + } + + QRectF re(tl.toPointF(), br.toPointF()); + re.translate(-1 * tl.toPointF()); + + clear(); + screenVertices_.reserve(6); + + screenVertices_ << re.topLeft(); + screenVertices_ << re.topRight(); + screenVertices_ << re.bottomLeft(); + + screenVertices_ << re.topRight(); + screenVertices_ << re.bottomLeft(); + screenVertices_ << re.bottomRight(); + + firstPointOffset_ = QPointF(0,0); + srcOrigin_ = topLeft; + screenBounds_ = re; + + screenOutline_ = QPainterPath(); + screenOutline_.addRect(re); + + geoLeftBound_ = topLeft; +} + +QDeclarativeRectangleMapItem::QDeclarativeRectangleMapItem(QQuickItem *parent) +: QDeclarativeGeoMapItemBase(parent), color_(Qt::transparent), dirtyMaterial_(true), + updatingGeometry_(false) +{ + setFlag(ItemHasContents, true); + QObject::connect(&border_, SIGNAL(colorChanged(QColor)), + this, SLOT(markSourceDirtyAndUpdate())); + QObject::connect(&border_, SIGNAL(widthChanged(qreal)), + this, SLOT(markSourceDirtyAndUpdate())); +} + +QDeclarativeRectangleMapItem::~QDeclarativeRectangleMapItem() +{ +} + +/*! + \internal +*/ +void QDeclarativeRectangleMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) +{ + QDeclarativeGeoMapItemBase::setMap(quickMap,map); + if (map) + markSourceDirtyAndUpdate(); +} + +/*! + \qmlpropertygroup Location::MapRectangle::border + \qmlproperty int MapRectangle::border.width + \qmlproperty color MapRectangle::border.color + + This property is part of the border property group. The border property group + holds the width and color used to draw the border of the rectangle. + The width is in pixels and is independent of the zoom level of the map. + + The default values correspond to a black border with a width of 1 pixel. + For no line, use a width of 0 or a transparent color. +*/ +QDeclarativeMapLineProperties *QDeclarativeRectangleMapItem::border() +{ + return &border_; +} + +/*! + \qmlproperty coordinate MapRectangle::topLeft + + This property holds the top-left coordinate of the MapRectangle which + can be used to retrieve its longitude, latitude and altitude. +*/ +void QDeclarativeRectangleMapItem::setTopLeft(const QGeoCoordinate &topLeft) +{ + if (topLeft_ == topLeft) + return; + + topLeft_ = topLeft; + + markSourceDirtyAndUpdate(); + emit topLeftChanged(topLeft_); +} + +QGeoCoordinate QDeclarativeRectangleMapItem::topLeft() +{ + return topLeft_; +} + +/*! + \internal +*/ +void QDeclarativeRectangleMapItem::markSourceDirtyAndUpdate() +{ + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + polishAndUpdate(); +} + +/*! + \qmlproperty coordinate MapRectangle::bottomRight + + This property holds the bottom-right coordinate of the MapRectangle which + can be used to retrieve its longitude, latitude and altitude. +*/ +void QDeclarativeRectangleMapItem::setBottomRight(const QGeoCoordinate &bottomRight) +{ + if (bottomRight_ == bottomRight) + return; + + bottomRight_ = bottomRight; + + markSourceDirtyAndUpdate(); + emit bottomRightChanged(bottomRight_); +} + +QGeoCoordinate QDeclarativeRectangleMapItem::bottomRight() +{ + return bottomRight_; +} + +/*! + \qmlproperty color MapRectangle::color + + This property holds the fill color of the rectangle. For no fill, use + a transparent color. +*/ +QColor QDeclarativeRectangleMapItem::color() const +{ + return color_; +} + +void QDeclarativeRectangleMapItem::setColor(const QColor &color) +{ + if (color_ == color) + return; + color_ = color; + dirtyMaterial_ = true; + polishAndUpdate(); + emit colorChanged(color_); +} + +/*! + \qmlproperty real MapRectangle::opacity + + This property holds the opacity of the item. Opacity is specified as a + number between 0 (fully transparent) and 1 (fully opaque). The default is 1. + + An item with 0 opacity will still receive mouse events. To stop mouse events, set the + visible property of the item to false. +*/ + +/*! + \internal +*/ +QSGNode *QDeclarativeRectangleMapItem::updateMapItemPaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) +{ + Q_UNUSED(data); + + MapPolygonNode *node = static_cast(oldNode); + + if (!node) { + node = new MapPolygonNode(); + } + + //TODO: update only material + if (geometry_.isScreenDirty() || borderGeometry_.isScreenDirty() || dirtyMaterial_) { + node->update(color_, border_.color(), &geometry_, &borderGeometry_); + geometry_.setPreserveGeometry(false); + borderGeometry_.setPreserveGeometry(false); + geometry_.markClean(); + borderGeometry_.markClean(); + dirtyMaterial_ = false; + } + return node; +} + +/*! + \internal +*/ +void QDeclarativeRectangleMapItem::updatePolish() +{ + if (!map() || !topLeft().isValid() || !bottomRight().isValid()) + return; + + QScopedValueRollback rollback(updatingGeometry_); + updatingGeometry_ = true; + + geometry_.updatePoints(*map(), topLeft_, bottomRight_); + + QList pathClosed; + pathClosed << topLeft_; + pathClosed << QGeoCoordinate(topLeft_.latitude(), bottomRight_.longitude()); + pathClosed << bottomRight_; + pathClosed << QGeoCoordinate(bottomRight_.latitude(), topLeft_.longitude()); + pathClosed << pathClosed.first(); + + if (border_.color() != Qt::transparent && border_.width() > 0) { + borderGeometry_.updateSourcePoints(*map(), pathClosed, topLeft_); + borderGeometry_.updateScreenPoints(*map(), border_.width()); + + QList geoms; + geoms << &geometry_ << &borderGeometry_; + QRectF combined = QGeoMapItemGeometry::translateToCommonOrigin(geoms); + + setWidth(combined.width()); + setHeight(combined.height()); + } else { + borderGeometry_.clear(); + + setWidth(geometry_.screenBoundingBox().width()); + setHeight(geometry_.screenBoundingBox().height()); + } + + setPositionOnMap(pathClosed.at(0), geometry_.firstPointOffset()); +} + +/*! + \internal +*/ +void QDeclarativeRectangleMapItem::afterViewportChanged(const QGeoMapViewportChangeEvent &event) +{ + if (event.mapSize.width() <= 0 || event.mapSize.height() <= 0) + return; + + // if the scene is tilted, we must regenerate our geometry every frame + if (map()->cameraCapabilities().supportsTilting() + && (event.cameraData.tilt() > 0.1 + || event.cameraData.tilt() < -0.1)) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + + // if the scene is rolled, we must regen too + if (map()->cameraCapabilities().supportsRolling() + && (event.cameraData.roll() > 0.1 + || event.cameraData.roll() < -0.1)) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + + // otherwise, only regen on rotate, resize and zoom + if (event.bearingChanged || event.mapSizeChanged || event.zoomLevelChanged) { + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); + } + geometry_.setPreserveGeometry(true, topLeft_); + borderGeometry_.setPreserveGeometry(true, topLeft_); + geometry_.markScreenDirty(); + borderGeometry_.markScreenDirty(); + polishAndUpdate(); +} + +/*! + \internal +*/ +bool QDeclarativeRectangleMapItem::contains(const QPointF &point) const +{ + return (geometry_.contains(point) || borderGeometry_.contains(point)); +} + +/*! + \internal +*/ +void QDeclarativeRectangleMapItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + if (updatingGeometry_ || newGeometry.topLeft() == oldGeometry.topLeft()) { + QDeclarativeGeoMapItemBase::geometryChanged(newGeometry, oldGeometry); + return; + } + + QDoubleVector2D newTopLeftPoint = QDoubleVector2D(x(),y()); + QGeoCoordinate newTopLeft = map()->itemPositionToCoordinate(newTopLeftPoint, false); + if (newTopLeft.isValid()) { + // calculate new geo width while checking for dateline crossing + const double lonW = bottomRight_.longitude() > topLeft_.longitude() ? + bottomRight_.longitude() - topLeft_.longitude() : + bottomRight_.longitude() + 360 - topLeft_.longitude(); + const double latH = qAbs(bottomRight_.latitude() - topLeft_.latitude()); + QGeoCoordinate newBottomRight; + // prevent dragging over valid min and max latitudes + if (QLocationUtils::isValidLat(newTopLeft.latitude() - latH)) { + newBottomRight.setLatitude(newTopLeft.latitude() - latH); + } else { + newBottomRight.setLatitude(QLocationUtils::clipLat(newTopLeft.latitude() - latH)); + newTopLeft.setLatitude(newBottomRight.latitude() + latH); + } + // handle dateline crossing + newBottomRight.setLongitude(QLocationUtils::wrapLong(newTopLeft.longitude() + lonW)); + newBottomRight.setAltitude(newTopLeft.altitude()); + topLeft_ = newTopLeft; + bottomRight_ = newBottomRight; + geometry_.setPreserveGeometry(true, newTopLeft); + borderGeometry_.setPreserveGeometry(true, newTopLeft); + markSourceDirtyAndUpdate(); + emit topLeftChanged(topLeft_); + emit bottomRightChanged(bottomRight_); + } + + // Not calling QDeclarativeGeoMapItemBase::geometryChanged() as it will be called from a nested + // call to this function. +} + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativerectanglemapitem_p.h b/src/imports/location/qdeclarativerectanglemapitem_p.h new file mode 100644 index 0000000..fb9936b --- /dev/null +++ b/src/imports/location/qdeclarativerectanglemapitem_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVERECTANGLEMAPITEM_H_ +#define QDECLARATIVERECTANGLEMAPITEM_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeomapitembase_p.h" +#include "qgeomapitemgeometry_p.h" +#include "qdeclarativepolylinemapitem_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMapRectangleGeometry : public QGeoMapItemGeometry +{ +public: + QGeoMapRectangleGeometry(); + + void updatePoints(const QGeoMap &map, + const QGeoCoordinate &topLeft, + const QGeoCoordinate &bottomRight); +}; + +class MapRectangleNode; + +class QDeclarativeRectangleMapItem: public QDeclarativeGeoMapItemBase +{ + Q_OBJECT + + Q_PROPERTY(QGeoCoordinate topLeft READ topLeft WRITE setTopLeft NOTIFY topLeftChanged) + Q_PROPERTY(QGeoCoordinate bottomRight READ bottomRight WRITE setBottomRight NOTIFY bottomRightChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + Q_PROPERTY(QDeclarativeMapLineProperties *border READ border) + +public: + explicit QDeclarativeRectangleMapItem(QQuickItem *parent = 0); + ~QDeclarativeRectangleMapItem(); + + virtual void setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) Q_DECL_OVERRIDE; + //from QuickItem + virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; + + QGeoCoordinate topLeft(); + void setTopLeft(const QGeoCoordinate ¢er); + + QGeoCoordinate bottomRight(); + void setBottomRight(const QGeoCoordinate ¢er); + + QColor color() const; + void setColor(const QColor &color); + + QDeclarativeMapLineProperties *border(); + + bool contains(const QPointF &point) const Q_DECL_OVERRIDE; + +Q_SIGNALS: + void topLeftChanged(const QGeoCoordinate &topLeft); + void bottomRightChanged(const QGeoCoordinate &bottomRight); + void colorChanged(const QColor &color); + +protected: + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void updatePolish() Q_DECL_OVERRIDE; + +protected Q_SLOTS: + void markSourceDirtyAndUpdate(); + virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; + +private: + QGeoCoordinate topLeft_; + QGeoCoordinate bottomRight_; + QDeclarativeMapLineProperties border_; + QColor color_; + bool dirtyMaterial_; + QGeoMapRectangleGeometry geometry_; + QGeoMapPolylineGeometry borderGeometry_; + bool updatingGeometry_; +}; + +////////////////////////////////////////////////////////////////////// + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeRectangleMapItem) + +#endif /* QDECLARATIVERECTANGLEMAPITEM_H_ */ diff --git a/src/imports/location/qdeclarativeroutemapitem.cpp b/src/imports/location/qdeclarativeroutemapitem.cpp new file mode 100644 index 0000000..19930cc --- /dev/null +++ b/src/imports/location/qdeclarativeroutemapitem.cpp @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qdeclarativeroutemapitem_p.h" +#include "qdeclarativepolylinemapitem_p.h" +#include "qgeocameracapabilities_p.h" +#include "qdeclarativegeoroute_p.h" + +#include +#include + +/*! + \qmltype MapRoute + \instantiates QDeclarativeRouteMapItem + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.0 + + \brief The MapRoute type displays a Route on a Map. + + The MapRoute type displays a Route obtained through a RouteModel or + other means, on the Map as a Polyline following the path of the Route. + + MapRoute is really a \l MapPolyline, but with the path specified using the + \l route property instead of directly in \l {coordinate}{coordinates}. + + By default, the route is displayed as a 1-pixel thick black line. This can + be changed using the \l line.width and \l line.color properties. + + \section2 Performance + + For notes about the performance on MapRoute, refer to the documentation for + \l MapPolyline. + + \section2 Example Usage + + Here is how to draw a \l{Route}{route} on a \l{Map}{map}: + + \snippet declarative/maps.qml QtQuick import + \snippet declarative/maps.qml QtLocation import + \codeline + \snippet declarative/maps.qml MapRoute +*/ + +/*! + \qmlpropertygroup Location::MapRoute::line + \qmlproperty int MapRoute::line.width + \qmlproperty color MapRoute::line.color + + This property is part of the line property group. The line + property group holds the width and color used to draw the line. + + The width is in pixels and is independent of the zoom level of the map. + The default values correspond to a black border with a width of 1 pixel. + + For no line, use a width of 0 or a transparent color. +*/ + + +QDeclarativeRouteMapItem::QDeclarativeRouteMapItem(QQuickItem *parent) +: QDeclarativePolylineMapItem(parent), route_(0) +{ + setFlag(ItemHasContents, true); +} + +QDeclarativeRouteMapItem::~QDeclarativeRouteMapItem() +{ +} + +/*! + \qmlproperty Route MapRoute::route + + This property holds the route to be drawn which can be used + to represent one geographical route. +*/ +QDeclarativeGeoRoute *QDeclarativeRouteMapItem::route() const +{ + return route_; +} + +void QDeclarativeRouteMapItem::setRoute(QDeclarativeGeoRoute *route) +{ + if (route_ == route) + return; + + route_ = route; + + connect(route_, SIGNAL(pathChanged()), this, SLOT(updateRoutePath())); + + if (route_) + setPathFromGeoList(route_->routePath()); + + emit routeChanged(route_); +} + +void QDeclarativeRouteMapItem::updateRoutePath() +{ + setPathFromGeoList(route_->routePath()); +} + +/*! + \internal void QDeclarativeRouteMapItem::setPath(const QJSValue &value) + + Used to disable path property on the RouteMapItem + */ +void QDeclarativeRouteMapItem::setPath(const QJSValue &value) +{ + Q_UNUSED(value); + qWarning() << "Can not set the path on QDeclarativeRouteMapItem." + << "Please use the route property instead."; +} diff --git a/src/imports/location/qdeclarativeroutemapitem_p.h b/src/imports/location/qdeclarativeroutemapitem_p.h new file mode 100644 index 0000000..3acac3c --- /dev/null +++ b/src/imports/location/qdeclarativeroutemapitem_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEROUTEMAPITEM_H_ +#define QDECLARATIVEROUTEMAPITEM_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativegeomapitembase_p.h" +#include "qdeclarativegeomap_p.h" +#include "qdeclarativepolylinemapitem_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoRoute; + +class QDeclarativeRouteMapItem : public QDeclarativePolylineMapItem +{ + Q_OBJECT + + Q_PROPERTY(QDeclarativeGeoRoute *route READ route WRITE setRoute NOTIFY routeChanged) + +public: + explicit QDeclarativeRouteMapItem(QQuickItem *parent = 0); + ~QDeclarativeRouteMapItem(); + + QDeclarativeGeoRoute *route() const; + void setRoute(QDeclarativeGeoRoute *route); + +Q_SIGNALS: + void routeChanged(const QDeclarativeGeoRoute *route); + +private slots: + void updateRoutePath(); + +protected: + void setPath(const QJSValue &value) Q_DECL_OVERRIDE; + +private: + QDeclarativeGeoRoute *route_; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeRouteMapItem) + +#endif /* QDECLARATIVEROUTEMAPITEM_H_ */ diff --git a/src/imports/location/qgeomapitemgeometry.cpp b/src/imports/location/qgeomapitemgeometry.cpp new file mode 100644 index 0000000..e9c490d --- /dev/null +++ b/src/imports/location/qgeomapitemgeometry.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomapitemgeometry_p.h" +#include "qdeclarativegeomap_p.h" +#include "qlocationutils_p.h" +#include +#include "qdoublevector2d_p.h" + +QT_BEGIN_NAMESPACE + +QGeoMapItemGeometry::QGeoMapItemGeometry() +: sourceDirty_(true), screenDirty_(true), clipToViewport_(true), preserveGeometry_(false) +{ +} + +/*! + \internal +*/ +void QGeoMapItemGeometry::translate(const QPointF &offset) +{ + for (int i = 0; i < screenVertices_.size(); ++i) + screenVertices_[i] += offset; + + firstPointOffset_ += offset; + screenOutline_.translate(offset); + screenBounds_.translate(offset); +} + +/*! + \internal +*/ +void QGeoMapItemGeometry::allocateAndFill(QSGGeometry *geom) const +{ + const QVector &vx = screenVertices_; + const QVector &ix = screenIndices_; + + if (isIndexed()) { + geom->allocate(vx.size(), ix.size()); + if (geom->indexType() == GL_UNSIGNED_SHORT) { + quint16 *its = geom->indexDataAsUShort(); + for (int i = 0; i < ix.size(); ++i) + its[i] = ix[i]; + } else if (geom->indexType() == GL_UNSIGNED_INT) { + quint32 *its = geom->indexDataAsUInt(); + for (int i = 0; i < ix.size(); ++i) + its[i] = ix[i]; + } + } else { + geom->allocate(vx.size()); + } + + QSGGeometry::Point2D *pts = geom->vertexDataAsPoint2D(); + for (int i = 0; i < vx.size(); ++i) + pts[i].set(vx[i].x(), vx[i].y()); +} + +/*! + \internal +*/ +QRectF QGeoMapItemGeometry::translateToCommonOrigin(const QList &geoms) +{ + QGeoCoordinate origin = geoms.at(0)->origin(); + + QPainterPath brects; + + // first get max offset + QPointF maxOffset = geoms.at(0)->firstPointOffset(); + foreach (QGeoMapItemGeometry *g, geoms) { + Q_ASSERT(g->origin() == origin); + QPointF o = g->firstPointOffset(); + maxOffset.setX(qMax(o.x(), maxOffset.x())); + maxOffset.setY(qMax(o.y(), maxOffset.y())); + } + + // then translate everything + foreach (QGeoMapItemGeometry *g, geoms) { + g->translate(maxOffset - g->firstPointOffset()); + brects.addRect(g->sourceBoundingBox()); + } + + return brects.boundingRect(); +} + +/*! + \internal +*/ +double QGeoMapItemGeometry::geoDistanceToScreenWidth(const QGeoMap &map, + const QGeoCoordinate &fromCoord, + const QGeoCoordinate &toCoord) +{ + // Do not wrap around half the globe + Q_ASSERT(!qFuzzyCompare(fromCoord.longitude(), toCoord.longitude())); + + QGeoCoordinate mapMid = map.itemPositionToCoordinate(QDoubleVector2D(map.width()/2.0, 0)); + double halfGeoDist = toCoord.longitude() - fromCoord.longitude(); + if (toCoord.longitude() < fromCoord.longitude()) + halfGeoDist += 360; + halfGeoDist /= 2.0; + QGeoCoordinate geoDelta = QGeoCoordinate(0, + QLocationUtils::wrapLong(mapMid.longitude() + halfGeoDist)); + QDoubleVector2D halfScreenDist = map.coordinateToItemPosition(geoDelta, false) + - QDoubleVector2D(map.width()/2.0, 0); + return halfScreenDist.x() * 2.0; +} + +QT_END_NAMESPACE diff --git a/src/imports/location/qgeomapitemgeometry_p.h b/src/imports/location/qgeomapitemgeometry_p.h new file mode 100644 index 0000000..36b670f --- /dev/null +++ b/src/imports/location/qgeomapitemgeometry_p.h @@ -0,0 +1,148 @@ +/**************************************************************************** + ** + ** Copyright (C) 2015 The Qt Company Ltd. + ** Contact: http://www.qt.io/licensing/ + ** + ** This file is part of the QtLocation module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL3$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see http://www.qt.io/terms-conditions. For further + ** information use the contact form at http://www.qt.io/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 3 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPLv3 included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 3 requirements + ** will be met: https://www.gnu.org/licenses/lgpl.html. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 2.0 or later as published by the Free + ** Software Foundation and appearing in the file LICENSE.GPL included in + ** the packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 2.0 requirements will be + ** met: http://www.gnu.org/licenses/gpl-2.0.html. + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#ifndef QGEOMAPITEMGEOMETRY_H +#define QGEOMAPITEMGEOMETRY_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QSGGeometry; +class QGeoMap; + +class QGeoMapItemGeometry +{ +public: + QGeoMapItemGeometry(); + + inline bool isSourceDirty() const { return sourceDirty_; } + inline bool isScreenDirty() const { return screenDirty_; } + inline void markSourceDirty() { sourceDirty_ = true; screenDirty_ = true; } + inline void markScreenDirty() { screenDirty_ = true; clipToViewport_ = true; } + inline void markFullScreenDirty() { screenDirty_ = true; clipToViewport_ = false;} + inline void markClean() { screenDirty_ = (sourceDirty_ = false); clipToViewport_ = true;} + + inline void setPreserveGeometry(bool value, QGeoCoordinate geoLeftBound = QGeoCoordinate()) + { + preserveGeometry_ = value; + if (preserveGeometry_) + geoLeftBound_ = geoLeftBound; + } + inline QGeoCoordinate geoLeftBound() { return geoLeftBound_; } + + inline QRectF sourceBoundingBox() const { return sourceBounds_; } + inline QRectF screenBoundingBox() const { return screenBounds_; } + + inline QPointF firstPointOffset() const { return firstPointOffset_; } + void translate(const QPointF &offset); + + inline const QGeoCoordinate &origin() const { return srcOrigin_; } + + inline bool contains(const QPointF &screenPoint) const { + return screenOutline_.contains(screenPoint); + } + + inline QVector2D vertex(quint32 index) const { + return QVector2D(screenVertices_[index]); + } + + inline QVector vertices() const { return screenVertices_; } + inline QVector indices() const { return screenIndices_; } + + inline bool isIndexed() const { return (!screenIndices_.isEmpty()); } + + /* Size is # of triangles */ + inline quint32 size() const + { + if (isIndexed()) + return screenIndices_.size() / 3; + else + return screenVertices_.size() / 3; + } + + inline void clear() { firstPointOffset_ = QPointF(0,0); + screenVertices_.clear(); screenIndices_.clear(); } + + void allocateAndFill(QSGGeometry *geom) const; + + double geoDistanceToScreenWidth(const QGeoMap &map, + const QGeoCoordinate &fromCoord, + const QGeoCoordinate &toCoord); + + static QRectF translateToCommonOrigin(const QList &geoms); + + +protected: + bool sourceDirty_; + bool screenDirty_; + bool clipToViewport_; + bool preserveGeometry_; + QGeoCoordinate geoLeftBound_; + + QPointF firstPointOffset_; + + QPainterPath screenOutline_; + + QRectF sourceBounds_; + QRectF screenBounds_; + + QGeoCoordinate srcOrigin_; + + QVector screenVertices_; + QVector screenIndices_; +}; + +QT_END_NAMESPACE + +#endif // QGEOMAPITEMGEOMETRY_H diff --git a/src/imports/location/qmldir b/src/imports/location/qmldir new file mode 100644 index 0000000..37ecf66 --- /dev/null +++ b/src/imports/location/qmldir @@ -0,0 +1,4 @@ +module QtLocation +plugin declarative_location +classname QtLocationDeclarativeModule +typeinfo plugins.qmltypes diff --git a/src/imports/location/qquickgeomapgesturearea.cpp b/src/imports/location/qquickgeomapgesturearea.cpp new file mode 100644 index 0000000..1a3b3c1 --- /dev/null +++ b/src/imports/location/qquickgeomapgesturearea.cpp @@ -0,0 +1,1286 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickgeomapgesturearea_p.h" +#include "qdeclarativegeomap_p.h" +#include "error_messages.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "math.h" +#include "qgeomap_p.h" +#include "qdoublevector2d_p.h" + +#define QML_MAP_FLICK_DEFAULTMAXVELOCITY 2500 +#define QML_MAP_FLICK_MINIMUMDECELERATION 500 +#define QML_MAP_FLICK_DEFAULTDECELERATION 2500 +#define QML_MAP_FLICK_MAXIMUMDECELERATION 10000 + +#define QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD 50 +// FlickThreshold determines how far the "mouse" must have moved +// before we perform a flick. +static const int FlickThreshold = 20; +// Really slow flicks can be annoying. +const qreal MinimumFlickVelocity = 75.0; + +QT_BEGIN_NAMESPACE + + +/*! + \qmltype MapPinchEvent + \instantiates QGeoMapPinchEvent + \inqmlmodule QtLocation + + \brief MapPinchEvent type provides basic information about pinch event. + + MapPinchEvent type provides basic information about pinch event. They are + present in handlers of MapPinch (for example pinchStarted/pinchUpdated). Events are only + guaranteed to be valid for the duration of the handler. + + Except for the \l accepted property, all properties are read-only. + + \section2 Example Usage + + The following example enables the pinch gesture on a map and reacts to the + finished event. + + \code + Map { + id: map + gesture.enabled: true + gesture.onPinchFinished:{ + var coordinate1 = map.toCoordinate(gesture.point1) + var coordinate2 = map.toCoordinate(gesture.point2) + console.log("Pinch started at:") + console.log(" Points (" + gesture.point1.x + ", " + gesture.point1.y + ") - (" + gesture.point2.x + ", " + gesture.point2.y + ")") + console.log(" Coordinates (" + coordinate1.latitude + ", " + coordinate1.longitude + ") - (" + coordinate2.latitude + ", " + coordinate2.longitude + ")") + } + } + \endcode + + \ingroup qml-QtLocation5-maps + \since Qt Location 5.0 +*/ + +/*! + \qmlproperty QPoint QtLocation::MapPinchEvent::center + + This read-only property holds the current center point. +*/ + +/*! + \qmlproperty real QtLocation::MapPinchEvent::angle + + This read-only property holds the current angle between the two points in + the range -180 to 180. Positive values for the angles mean counter-clockwise + while negative values mean the clockwise direction. Zero degrees is at the + 3 o'clock position. +*/ + +/*! + \qmlproperty QPoint QtLocation::MapPinchEvent::point1 + \qmlproperty QPoint QtLocation::MapPinchEvent::point2 + + These read-only properties hold the actual touch points generating the pinch. + The points are not in any particular order. +*/ + +/*! + \qmlproperty int QtLocation::MapPinchEvent::pointCount + + This read-only property holds the number of points currently touched. + The MapPinch will not react until two touch points have initiated a gesture, + but will remain active until all touch points have been released. +*/ + +/*! + \qmlproperty bool QtLocation::MapPinchEvent::accepted + + Setting this property to false in the \c MapPinch::onPinchStarted handler + will result in no further pinch events being generated, and the gesture + ignored. +*/ + +/*! + \qmltype MapGestureArea + \instantiates QQuickGeoMapGestureArea + + \inqmlmodule QtLocation + + \brief The MapGestureArea type provides Map gesture interaction. + + MapGestureArea objects are used as part of a Map, to provide for panning, + flicking and pinch-to-zoom gesture used on touch displays. + + A MapGestureArea is automatically created with a new Map and available with + the \l{Map::gesture}{gesture} property. This is the only way + to create a MapGestureArea, and once created this way cannot be destroyed + without its parent Map. + + The two most commonly used properties of the MapGestureArea are the \l enabled + and \l acceptedGestures properties. Both of these must be set before a + MapGestureArea will have any effect upon interaction with the Map. + The \l flickDeceleration property controls how quickly the map pan slows after contact + is released while panning the map. + + \section2 Performance + + The MapGestureArea, when enabled, must process all incoming touch events in + order to track the shape and size of the "pinch". The overhead added on + touch events can be considered constant time. + + \section2 Example Usage + + The following example enables the pinch and pan gestures on the map, but not flicking. So the + map scrolling will halt immediately on releasing the mouse button / touch. + + \code + Map { + gesture.enabled: true + gesture.acceptedGestures: MapGestureArea.PinchGesture | MapGestureArea.PanGesture + } + \endcode + + \ingroup qml-QtLocation5-maps + \since Qt Location 5.0 +*/ + +/*! + \qmlproperty bool QtLocation::MapGestureArea::enabled + + This property holds whether the gestures are enabled. +*/ + +/*! + \qmlproperty bool QtLocation::MapGestureArea::pinchActive + + This read-only property holds whether pinch gesture is active. +*/ + +/*! + \qmlproperty bool QtLocation::MapGestureArea::panActive + + This read-only property holds whether pan gesture is active. + + \note Change notifications for this property were introduced in Qt 5.5. +*/ + +/*! + \qmlproperty real QtLocation::MapGestureArea::maximumZoomLevelChange + + This property holds the maximum zoom level change per pinch, essentially + meant to be used for setting the zoom sensitivity. + + It is an indicative measure calculated from the dimensions of the + map area, roughly corresponding how much zoom level could change with + maximum pinch zoom. Default value is 4.0, maximum value is 10.0 +*/ + +/*! + \qmlproperty real MapGestureArea::flickDeceleration + + This property holds the rate at which a flick will decelerate. + + The default value is 2500. +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::pinchStarted(PinchEvent event) + + This signal is emitted when a pinch gesture is started. + + The corresponding handler is \c onPinchStarted. + + \sa pinchUpdated, pinchFinished +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::pinchUpdated(PinchEvent event) + + This signal is emitted as the user's fingers move across the map, + after the \l pinchStarted signal is emitted. + + The corresponding handler is \c onPinchUpdated. + + \sa pinchStarted, pinchFinished +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::pinchFinished(PinchEvent event) + + This signal is emitted at the end of a pinch gesture. + + The corresponding handler is \c onPinchFinished. + + \sa pinchStarted, pinchUpdated +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::panStarted() + + This signal is emitted when the map begins to move due to user + interaction. Typically this means that the user is dragging a finger - + or a mouse with one of more mouse buttons pressed - on the map. + + The corresponding handler is \c onPanStarted. +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::panFinished() + + This signal is emitted when the map stops moving due to user + interaction. If a flick was generated, this signal is + emitted before flick starts. If a flick was not + generated, this signal is emitted when the + user stops dragging - that is a mouse or touch release. + + The corresponding handler is \c onPanFinished. + +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::flickStarted() + + This signal is emitted when the map is flicked. A flick + starts from the point where the mouse or touch was released, + while still in motion. + + The corresponding handler is \c onFlichStarted. +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::flickFinished() + + This signal is emitted when the map stops moving due to a flick. + + The corresponding handler is \c onFlickFinished. +*/ + +QQuickGeoMapGestureArea::QQuickGeoMapGestureArea(QDeclarativeGeoMap *map) + : QQuickItem(map), + m_map(0), + m_declarativeMap(map), + m_enabled(true), + m_acceptedGestures(PinchGesture | PanGesture | FlickGesture), + m_preventStealing(false), + m_panEnabled(true) +{ + m_flick.m_enabled = true, + m_flick.m_maxVelocity = QML_MAP_FLICK_DEFAULTMAXVELOCITY; + m_flick.m_deceleration = QML_MAP_FLICK_DEFAULTDECELERATION; + m_flick.m_animation = 0; + m_touchPointState = touchPoints0; + m_pinchState = pinchInactive; + m_flickState = flickInactive; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setMap(QGeoMap *map) +{ + if (m_map || !map) + return; + + m_map = map; + m_flick.m_animation = new QQuickGeoCoordinateAnimation(this); + m_flick.m_animation->setTargetObject(m_declarativeMap); + m_flick.m_animation->setProperty(QStringLiteral("center")); + m_flick.m_animation->setEasing(QEasingCurve(QEasingCurve::OutQuad)); + connect(m_flick.m_animation, &QQuickAbstractAnimation::stopped, this, &QQuickGeoMapGestureArea::handleFlickAnimationStopped); +} + +/*! + \qmlproperty bool QtQuick::MapGestureArea::preventStealing + This property holds whether the mouse events may be stolen from this + MapGestureArea. + + If a Map is placed within an item that filters child mouse + and touch events, such as Flickable, the mouse and touch events + may be stolen from the MapGestureArea if a gesture is recognized + by the parent item, e.g. a flick gesture. If preventStealing is + set to true, no item will steal the mouse and touch events. + + Note that setting preventStealing to true once an item has started + stealing events will have no effect until the next press event. + + By default this property is false. +*/ + +bool QQuickGeoMapGestureArea::preventStealing() const +{ + return m_preventStealing; +} + +void QQuickGeoMapGestureArea::setPreventStealing(bool prevent) +{ + if (prevent != m_preventStealing) { + m_preventStealing = prevent; + m_declarativeMap->setKeepMouseGrab(m_preventStealing && m_enabled); + m_declarativeMap->setKeepTouchGrab(m_preventStealing && m_enabled); + emit preventStealingChanged(); + } +} + +QQuickGeoMapGestureArea::~QQuickGeoMapGestureArea() +{ +} + +/*! + \qmlproperty enumeration QtLocation::MapGestureArea::acceptedGestures + + This property holds the gestures that will be active. By default + the zoom, pan and flick gestures are enabled. + + \list + \li MapGestureArea.NoGesture - Don't support any additional gestures (value: 0x0000). + \li MapGestureArea.PinchGesture - Support the map pinch gesture (value: 0x0001). + \li MapGestureArea.PanGesture - Support the map pan gesture (value: 0x0002). + \li MapGestureArea.FlickGesture - Support the map flick gesture (value: 0x0004). + \endlist +*/ + +QQuickGeoMapGestureArea::AcceptedGestures QQuickGeoMapGestureArea::acceptedGestures() const +{ + return m_acceptedGestures; +} + + +void QQuickGeoMapGestureArea::setAcceptedGestures(AcceptedGestures acceptedGestures) +{ + if (acceptedGestures == m_acceptedGestures) + return; + m_acceptedGestures = acceptedGestures; + + setPanEnabled(acceptedGestures & PanGesture); + setFlickEnabled(acceptedGestures & FlickGesture); + setPinchEnabled(acceptedGestures & PinchGesture); + + emit acceptedGesturesChanged(); +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::isPinchActive() const +{ + return m_pinchState == pinchActive; +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::isPanActive() const +{ + return m_flickState == panActive || m_flickState == flickActive; +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::enabled() const +{ + return m_enabled; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setEnabled(bool enabled) +{ + if (enabled == m_enabled) + return; + m_enabled = enabled; + + if (enabled) { + setPanEnabled(m_acceptedGestures & PanGesture); + setFlickEnabled(m_acceptedGestures & FlickGesture); + setPinchEnabled(m_acceptedGestures & PinchGesture); + } else { + setPanEnabled(false); + setFlickEnabled(false); + setPinchEnabled(false); + } + + emit enabledChanged(); +} + + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::pinchEnabled() const +{ + return m_pinch.m_enabled; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setPinchEnabled(bool enabled) +{ + if (enabled == m_pinch.m_enabled) + return; + m_pinch.m_enabled = enabled; +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::panEnabled() const +{ + return m_panEnabled; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setPanEnabled(bool enabled) +{ + if (enabled == m_flick.m_enabled) + return; + m_panEnabled = enabled; + + // unlike the pinch, the pan existing functionality is to stop immediately + if (!enabled) + stopPan(); +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::flickEnabled() const +{ + return m_flick.m_enabled; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setFlickEnabled(bool enabled) +{ + if (enabled == m_flick.m_enabled) + return; + m_flick.m_enabled = enabled; + // unlike the pinch, the flick existing functionality is to stop immediately + if (!enabled) { + stopFlick(); + } +} + +/*! + \internal + Used internally to set the minimum zoom level of the gesture area. + The caller is responsible to only send values that are valid + for the map plugin. Negative values are ignored. + */ +void QQuickGeoMapGestureArea::setMinimumZoomLevel(qreal min) +{ + if (min >= 0) + m_pinch.m_zoom.m_minimum = min; +} + +/*! + \internal + */ +qreal QQuickGeoMapGestureArea::minimumZoomLevel() const +{ + return m_pinch.m_zoom.m_minimum; +} + +/*! + \internal + Used internally to set the maximum zoom level of the gesture area. + The caller is responsible to only send values that are valid + for the map plugin. Negative values are ignored. + */ +void QQuickGeoMapGestureArea::setMaximumZoomLevel(qreal max) +{ + if (max >= 0) + m_pinch.m_zoom.m_maximum = max; +} + +/*! + \internal + */ +qreal QQuickGeoMapGestureArea::maximumZoomLevel() const +{ + return m_pinch.m_zoom.m_maximum; +} + +/*! + \internal +*/ +qreal QQuickGeoMapGestureArea::maximumZoomLevelChange() const +{ + return m_pinch.m_zoom.maximumChange; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setMaximumZoomLevelChange(qreal maxChange) +{ + if (maxChange == m_pinch.m_zoom.maximumChange || maxChange < 0.1 || maxChange > 10.0) + return; + m_pinch.m_zoom.maximumChange = maxChange; + emit maximumZoomLevelChangeChanged(); +} + +/*! + \internal +*/ +qreal QQuickGeoMapGestureArea::flickDeceleration() const +{ + return m_flick.m_deceleration; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setFlickDeceleration(qreal deceleration) +{ + if (deceleration < QML_MAP_FLICK_MINIMUMDECELERATION) + deceleration = QML_MAP_FLICK_MINIMUMDECELERATION; + else if (deceleration > QML_MAP_FLICK_MAXIMUMDECELERATION) + deceleration = QML_MAP_FLICK_MAXIMUMDECELERATION; + if (deceleration == m_flick.m_deceleration) + return; + m_flick.m_deceleration = deceleration; + emit flickDecelerationChanged(); +} + +/*! + \internal +*/ +QTouchEvent::TouchPoint* createTouchPointFromMouseEvent(QMouseEvent *event, Qt::TouchPointState state) +{ + // this is only partially filled. But since it is only partially used it works + // more robust would be to store a list of QPointFs rather than TouchPoints + QTouchEvent::TouchPoint* newPoint = new QTouchEvent::TouchPoint(); + newPoint->setPos(event->localPos()); + newPoint->setScenePos(event->windowPos()); + newPoint->setScreenPos(event->screenPos()); + newPoint->setState(state); + newPoint->setId(0); + return newPoint; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleMousePressEvent(QMouseEvent *event) +{ + m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointPressed)); + if (m_touchPoints.isEmpty()) update(); + event->accept(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleMouseMoveEvent(QMouseEvent *event) +{ + m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointMoved)); + if (m_touchPoints.isEmpty()) update(); + event->accept(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleMouseReleaseEvent(QMouseEvent *event) +{ + if (!m_mousePoint.isNull()) { + //this looks super ugly , however is required in case we do not get synthesized MouseReleaseEvent + //and we reset the point already in handleTouchUngrabEvent + m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointReleased)); + if (m_touchPoints.isEmpty()) update(); + } + event->accept(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleMouseUngrabEvent() +{ + + if (m_touchPoints.isEmpty() && !m_mousePoint.isNull()) { + m_mousePoint.reset(); + update(); + } else { + m_mousePoint.reset(); + } +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleTouchUngrabEvent() +{ + m_touchPoints.clear(); + //this is needed since in some cases mouse release is not delivered + //(second touch point brakes mouse synthesized events) + m_mousePoint.reset(); + update(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleTouchEvent(QTouchEvent *event) +{ + m_touchPoints.clear(); + for (int i = 0; i < event->touchPoints().count(); ++i) + m_touchPoints << event->touchPoints().at(i); + if (event->touchPoints().count() >= 2) + event->accept(); + else + event->ignore(); + update(); +} + +void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) +{ + if (!m_map) + return; + + QGeoCoordinate wheelGeoPos = m_map->itemPositionToCoordinate(QDoubleVector2D(event->posF()), false); + QPointF preZoomPoint = m_map->coordinateToItemPosition(wheelGeoPos, false).toPointF(); + + double zoomLevelDelta = event->angleDelta().y() * qreal(0.001); + m_declarativeMap->setZoomLevel(m_declarativeMap->zoomLevel() + zoomLevelDelta); + QPointF postZoomPoint = m_map->coordinateToItemPosition(wheelGeoPos, false).toPointF(); + + if (preZoomPoint != postZoomPoint) + { + qreal dx = postZoomPoint.x() - preZoomPoint.x(); + qreal dy = postZoomPoint.y() - preZoomPoint.y(); + QPointF mapCenterPoint(m_map->width() / 2.0 + dx, m_map->height() / 2.0 + dy); + + QGeoCoordinate mapCenterCoordinate = m_map->itemPositionToCoordinate(QDoubleVector2D(mapCenterPoint), false); + m_declarativeMap->setCenter(mapCenterCoordinate); + } + event->accept(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::clearTouchData() +{ + m_velocityX = 0; + m_velocityY = 0; + m_sceneCenter.setX(0); + m_sceneCenter.setY(0); + m_touchCenterCoord.setLongitude(0); + m_touchCenterCoord.setLatitude(0); + m_startCoord.setLongitude(0); + m_startCoord.setLatitude(0); +} + + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updateVelocityList(const QPointF &pos) +{ + // Take velocity samples every sufficient period of time, used later to determine the flick + // duration and speed (when mouse is released). + qreal elapsed = qreal(m_lastPosTime.elapsed()); + + if (elapsed >= QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD) { + elapsed /= 1000.; + int dyFromLastPos = pos.y() - m_lastPos.y(); + int dxFromLastPos = pos.x() - m_lastPos.x(); + m_lastPos = pos; + m_lastPosTime.restart(); + qreal velX = qreal(dxFromLastPos) / elapsed; + qreal velY = qreal(dyFromLastPos) / elapsed; + m_velocityX = qBound(-m_flick.m_maxVelocity, velX, m_flick.m_maxVelocity); + m_velocityY = qBound(-m_flick.m_maxVelocity, velY, m_flick.m_maxVelocity); + } +} + +/*! + \internal +*/ + +bool QQuickGeoMapGestureArea::isActive() const +{ + return isPanActive() || isPinchActive(); +} + +/*! + \internal +*/ +// simplify the gestures by using a state-machine format (easy to move to a future state machine) +void QQuickGeoMapGestureArea::update() +{ + if (!m_map) + return; + + // First state machine is for the number of touch points + + //combine touch with mouse event + m_allPoints.clear(); + m_allPoints << m_touchPoints; + if (m_allPoints.isEmpty() && !m_mousePoint.isNull()) + m_allPoints << *m_mousePoint.data(); + + touchPointStateMachine(); + + // Parallel state machine for pinch + if (isPinchActive() || (m_enabled && m_pinch.m_enabled && (m_acceptedGestures & (PinchGesture)))) + pinchStateMachine(); + + // Parallel state machine for pan (since you can pan at the same time as pinching) + // The stopPan function ensures that pan stops immediately when disabled, + // but the line below allows pan continue its current gesture if you disable + // the whole gesture (enabled_ flag), this keeps the enabled_ consistent with the pinch + if (isPanActive() || (m_enabled && m_flick.m_enabled && (m_acceptedGestures & (PanGesture | FlickGesture)))) + panStateMachine(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::touchPointStateMachine() +{ + // Transitions: + switch (m_touchPointState) { + case touchPoints0: + if (m_allPoints.count() == 1) { + clearTouchData(); + startOneTouchPoint(); + m_touchPointState = touchPoints1; + } else if (m_allPoints.count() >= 2) { + clearTouchData(); + startTwoTouchPoints(); + m_touchPointState = touchPoints2; + } + break; + case touchPoints1: + if (m_allPoints.count() == 0) { + m_touchPointState = touchPoints0; + } else if (m_allPoints.count() == 2) { + m_touchCenterCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(m_sceneCenter), false); + startTwoTouchPoints(); + m_touchPointState = touchPoints2; + } + break; + case touchPoints2: + if (m_allPoints.count() == 0) { + m_touchPointState = touchPoints0; + } else if (m_allPoints.count() == 1) { + m_touchCenterCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(m_sceneCenter), false); + startOneTouchPoint(); + m_touchPointState = touchPoints1; + } + break; + }; + + // Update + switch (m_touchPointState) { + case touchPoints0: + break; // do nothing if no touch points down + case touchPoints1: + updateOneTouchPoint(); + break; + case touchPoints2: + updateTwoTouchPoints(); + break; + } +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::startOneTouchPoint() +{ + m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); + m_lastPos = m_sceneStartPoint1; + m_lastPosTime.start(); + QGeoCoordinate startCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(m_sceneStartPoint1), false); + // ensures a smooth transition for panning + m_startCoord.setLongitude(m_startCoord.longitude() + startCoord.longitude() - + m_touchCenterCoord.longitude()); + m_startCoord.setLatitude(m_startCoord.latitude() + startCoord.latitude() - + m_touchCenterCoord.latitude()); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updateOneTouchPoint() +{ + m_sceneCenter = mapFromScene(m_allPoints.at(0).scenePos()); + updateVelocityList(m_sceneCenter); +} + + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::startTwoTouchPoints() +{ + m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); + m_sceneStartPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + QPointF startPos = (m_sceneStartPoint1 + m_sceneStartPoint2) * 0.5; + m_lastPos = startPos; + m_lastPosTime.start(); + QGeoCoordinate startCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(startPos), false); + m_startCoord.setLongitude(m_startCoord.longitude() + startCoord.longitude() - + m_touchCenterCoord.longitude()); + m_startCoord.setLatitude(m_startCoord.latitude() + startCoord.latitude() - + m_touchCenterCoord.latitude()); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updateTwoTouchPoints() +{ + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); + QPointF p2 = mapFromScene(m_allPoints.at(1).scenePos()); + qreal dx = p1.x() - p2.x(); + qreal dy = p1.y() - p2.y(); + m_distanceBetweenTouchPoints = sqrt(dx * dx + dy * dy); + m_sceneCenter = (p1 + p2) / 2; + updateVelocityList(m_sceneCenter); + + m_twoTouchAngle = QLineF(p1, p2).angle(); + if (m_twoTouchAngle > 180) + m_twoTouchAngle -= 360; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::pinchStateMachine() +{ + PinchState lastState = m_pinchState; + // Transitions: + switch (m_pinchState) { + case pinchInactive: + if (m_allPoints.count() >= 2) { + if (canStartPinch()) { + m_declarativeMap->setKeepMouseGrab(true); + m_declarativeMap->setKeepTouchGrab(true); + startPinch(); + m_pinchState = pinchActive; + } else { + m_pinchState = pinchInactiveTwoPoints; + } + } + break; + case pinchInactiveTwoPoints: + if (m_allPoints.count() <= 1) { + m_pinchState = pinchInactive; + } else { + if (canStartPinch()) { + m_declarativeMap->setKeepMouseGrab(true); + m_declarativeMap->setKeepTouchGrab(true); + startPinch(); + m_pinchState = pinchActive; + } + } + break; + case pinchActive: + if (m_allPoints.count() <= 1) { + m_pinchState = pinchInactive; + m_declarativeMap->setKeepMouseGrab(m_preventStealing); + m_declarativeMap->setKeepTouchGrab(m_preventStealing); + endPinch(); + } + break; + } + // This line implements an exclusive state machine, where the transitions and updates don't + // happen on the same frame + if (m_pinchState != lastState) { + emit pinchActiveChanged(); + return; + } + + // Update + switch (m_pinchState) { + case pinchInactive: + case pinchInactiveTwoPoints: + break; // do nothing + case pinchActive: + updatePinch(); + break; + } +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::canStartPinch() +{ + const int startDragDistance = qApp->styleHints()->startDragDistance(); + + if (m_allPoints.count() >= 2) { + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); + QPointF p2 = mapFromScene(m_allPoints.at(1).scenePos()); + if (qAbs(p1.x()-m_sceneStartPoint1.x()) > startDragDistance + || qAbs(p1.y()-m_sceneStartPoint1.y()) > startDragDistance + || qAbs(p2.x()-m_sceneStartPoint2.x()) > startDragDistance + || qAbs(p2.y()-m_sceneStartPoint2.y()) > startDragDistance) { + m_pinch.m_event.setCenter(mapFromScene(m_sceneCenter)); + m_pinch.m_event.setAngle(m_twoTouchAngle); + m_pinch.m_event.setPoint1(p1); + m_pinch.m_event.setPoint2(p2); + m_pinch.m_event.setPointCount(m_allPoints.count()); + m_pinch.m_event.setAccepted(true); + emit pinchStarted(&m_pinch.m_event); + return m_pinch.m_event.accepted(); + } + } + return false; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::startPinch() +{ + m_pinch.m_startDist = m_distanceBetweenTouchPoints; + m_pinch.m_zoom.m_previous = m_declarativeMap->zoomLevel(); + m_pinch.m_lastAngle = m_twoTouchAngle; + + m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); + m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + + m_pinch.m_zoom.m_start = m_declarativeMap->zoomLevel(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updatePinch() +{ + // Calculate the new zoom level if we have distance ( >= 2 touchpoints), otherwise stick with old. + qreal newZoomLevel = m_pinch.m_zoom.m_previous; + if (m_distanceBetweenTouchPoints) { + newZoomLevel = + // How much further/closer the current touchpoints are (in pixels) compared to pinch start + ((m_distanceBetweenTouchPoints - m_pinch.m_startDist) * + // How much one pixel corresponds in units of zoomlevel (and multiply by above delta) + (m_pinch.m_zoom.maximumChange / ((width() + height()) / 2))) + + // Add to starting zoom level. Sign of (dist-pinchstartdist) takes care of zoom in / out + m_pinch.m_zoom.m_start; + } + qreal da = m_pinch.m_lastAngle - m_twoTouchAngle; + if (da > 180) + da -= 360; + else if (da < -180) + da += 360; + m_pinch.m_event.setCenter(mapFromScene(m_sceneCenter)); + m_pinch.m_event.setAngle(m_twoTouchAngle); + + m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); + m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + m_pinch.m_event.setPoint1(m_pinch.m_lastPoint1); + m_pinch.m_event.setPoint2(m_pinch.m_lastPoint2); + m_pinch.m_event.setPointCount(m_allPoints.count()); + m_pinch.m_event.setAccepted(true); + + m_pinch.m_lastAngle = m_twoTouchAngle; + emit pinchUpdated(&m_pinch.m_event); + + if (m_acceptedGestures & PinchGesture) { + // Take maximum and minimumzoomlevel into account + qreal perPinchMinimumZoomLevel = qMax(m_pinch.m_zoom.m_start - m_pinch.m_zoom.maximumChange, m_pinch.m_zoom.m_minimum); + qreal perPinchMaximumZoomLevel = qMin(m_pinch.m_zoom.m_start + m_pinch.m_zoom.maximumChange, m_pinch.m_zoom.m_maximum); + newZoomLevel = qMin(qMax(perPinchMinimumZoomLevel, newZoomLevel), perPinchMaximumZoomLevel); + m_declarativeMap->setZoomLevel(newZoomLevel); + m_pinch.m_zoom.m_previous = newZoomLevel; + } +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::endPinch() +{ + QPointF p1 = mapFromScene(m_pinch.m_lastPoint1); + QPointF p2 = mapFromScene(m_pinch.m_lastPoint2); + m_pinch.m_event.setCenter((p1 + p2) / 2); + m_pinch.m_event.setAngle(m_pinch.m_lastAngle); + m_pinch.m_event.setPoint1(p1); + m_pinch.m_event.setPoint2(p2); + m_pinch.m_event.setAccepted(true); + m_pinch.m_event.setPointCount(0); + emit pinchFinished(&m_pinch.m_event); + m_pinch.m_startDist = 0; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::panStateMachine() +{ + FlickState lastState = m_flickState; + + // Transitions + switch (m_flickState) { + case flickInactive: + if (canStartPan()) { + // Update startCoord_ to ensure smooth start for panning when going over startDragDistance + QGeoCoordinate newStartCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(m_sceneCenter), false); + m_startCoord.setLongitude(newStartCoord.longitude()); + m_startCoord.setLatitude(newStartCoord.latitude()); + m_declarativeMap->setKeepMouseGrab(true); + m_flickState = panActive; + } + break; + case panActive: + if (m_allPoints.count() == 0) { + if (!tryStartFlick()) + { + m_flickState = flickInactive; + // mark as inactive for use by camera + if (m_pinchState == pinchInactive) { + m_declarativeMap->setKeepMouseGrab(m_preventStealing); + m_map->prefetchData(); + } + emit panFinished(); + } else { + m_flickState = flickActive; + emit panFinished(); + emit flickStarted(); + } + } + break; + case flickActive: + if (m_allPoints.count() > 0) { // re touched before movement ended + stopFlick(); + m_declarativeMap->setKeepMouseGrab(true); + m_flickState = panActive; + } + break; + } + + if (m_flickState != lastState) + emit panActiveChanged(); + + // Update + switch (m_flickState) { + case flickInactive: // do nothing + break; + case panActive: + updatePan(); + // this ensures 'panStarted' occurs after the pan has actually started + if (lastState != panActive) + emit panStarted(); + break; + case flickActive: + break; + } +} +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::canStartPan() +{ + if (m_allPoints.count() == 0 || (m_acceptedGestures & PanGesture) == 0) + return false; + + // Check if thresholds for normal panning are met. + // (normal panning vs flicking: flicking will start from mouse release event). + const int startDragDistance = qApp->styleHints()->startDragDistance() * 2; + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); + int dyFromPress = int(p1.y() - m_sceneStartPoint1.y()); + int dxFromPress = int(p1.x() - m_sceneStartPoint1.x()); + if ((qAbs(dyFromPress) >= startDragDistance || qAbs(dxFromPress) >= startDragDistance)) + return true; + return false; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updatePan() +{ + QPointF startPoint = m_map->coordinateToItemPosition(m_startCoord, false).toPointF(); + int dx = static_cast(m_sceneCenter.x() - startPoint.x()); + int dy = static_cast(m_sceneCenter.y() - startPoint.y()); + QPointF mapCenterPoint; + mapCenterPoint.setY(m_map->height() / 2.0 - dy); + mapCenterPoint.setX(m_map->width() / 2.0 - dx); + QGeoCoordinate animationStartCoordinate = m_map->itemPositionToCoordinate(QDoubleVector2D(mapCenterPoint), false); + m_declarativeMap->setCenter(animationStartCoordinate); +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::tryStartFlick() +{ + if ((m_acceptedGestures & FlickGesture) == 0) + return false; + // if we drag then pause before release we should not cause a flick. + qreal velocityX = 0.0; + qreal velocityY = 0.0; + if (m_lastPosTime.elapsed() < QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD) { + velocityY = m_velocityY; + velocityX = m_velocityX; + } + int flickTimeY = 0; + int flickTimeX = 0; + int flickPixelsX = 0; + int flickPixelsY = 0; + if (qAbs(velocityY) > MinimumFlickVelocity && qAbs(m_sceneCenter.y() - m_sceneStartPoint1.y()) > FlickThreshold) { + // calculate Y flick animation values + qreal acceleration = m_flick.m_deceleration; + if ((velocityY > 0.0f) == (m_flick.m_deceleration > 0.0f)) + acceleration = acceleration * -1.0f; + flickTimeY = static_cast(-1000 * velocityY / acceleration); + flickPixelsY = (flickTimeY * velocityY) / (1000.0 * 2); + } + if (qAbs(velocityX) > MinimumFlickVelocity && qAbs(m_sceneCenter.x() - m_sceneStartPoint1.x()) > FlickThreshold) { + // calculate X flick animation values + qreal acceleration = m_flick.m_deceleration; + if ((velocityX > 0.0f) == (m_flick.m_deceleration > 0.0f)) + acceleration = acceleration * -1.0f; + flickTimeX = static_cast(-1000 * velocityX / acceleration); + flickPixelsX = (flickTimeX * velocityX) / (1000.0 * 2); + } + int flickTime = qMax(flickTimeY, flickTimeX); + if (flickTime > 0) { + startFlick(flickPixelsX, flickPixelsY, flickTime); + return true; + } + return false; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::startFlick(int dx, int dy, int timeMs) +{ + if (!m_flick.m_animation) + return; + if (timeMs < 0) + return; + + QGeoCoordinate animationStartCoordinate = m_declarativeMap->center(); + + if (m_flick.m_animation->isRunning()) + m_flick.m_animation->stop(); + QGeoCoordinate animationEndCoordinate = m_declarativeMap->center(); + m_flick.m_animation->setDuration(timeMs); + + double zoom = pow(2.0, m_declarativeMap->zoomLevel()); + double longitude = animationStartCoordinate.longitude() - (dx / zoom); + double latitude = animationStartCoordinate.latitude() + (dy / zoom); + + if (dx > 0) + m_flick.m_animation->setDirection(QQuickGeoCoordinateAnimation::East); + else + m_flick.m_animation->setDirection(QQuickGeoCoordinateAnimation::West); + + //keep animation in correct bounds + if (latitude > 85.05113) + latitude = 85.05113; + else if (latitude < -85.05113) + latitude = -85.05113; + + if (longitude > 180) + longitude = longitude - 360; + else if (longitude < -180) + longitude = longitude + 360; + + animationEndCoordinate.setLongitude(longitude); + animationEndCoordinate.setLatitude(latitude); + + m_flick.m_animation->setFrom(animationStartCoordinate); + m_flick.m_animation->setTo(animationEndCoordinate); + m_flick.m_animation->start(); +} + +void QQuickGeoMapGestureArea::stopPan() +{ + if (m_flickState == flickActive) { + stopFlick(); + } else if (m_flickState == panActive) { + m_velocityX = 0; + m_velocityY = 0; + m_flickState = flickInactive; + m_declarativeMap->setKeepMouseGrab(m_preventStealing); + emit panFinished(); + emit panActiveChanged(); + m_map->prefetchData(); + } +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::stopFlick() +{ + if (!m_flick.m_animation) + return; + m_velocityX = 0; + m_velocityY = 0; + if (m_flick.m_animation->isRunning()) + m_flick.m_animation->stop(); + else + handleFlickAnimationStopped(); +} + +void QQuickGeoMapGestureArea::handleFlickAnimationStopped() +{ + m_declarativeMap->setKeepMouseGrab(m_preventStealing); + if (m_flickState == flickActive) { + m_flickState = flickInactive; + emit flickFinished(); + m_map->prefetchData(); + } +} + +#include "moc_qquickgeomapgesturearea_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qquickgeomapgesturearea_p.h b/src/imports/location/qquickgeomapgesturearea_p.h new file mode 100644 index 0000000..51c5cc1 --- /dev/null +++ b/src/imports/location/qquickgeomapgesturearea_p.h @@ -0,0 +1,317 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKGEOMAPGESTUREAREA_P_H +#define QQUICKGEOMAPGESTUREAREA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include "qgeocoordinate.h" +#include "qgeomap_p.h" +#include "qquickgeocoordinateanimation_p.h" + +QT_BEGIN_NAMESPACE + +class QGraphicsSceneMouseEvent; +class QDeclarativeGeoMap; +class QTouchEvent; +class QWheelEvent; +class QGeoMap; + +class QGeoMapPinchEvent : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPointF center READ center) + Q_PROPERTY(qreal angle READ angle) + Q_PROPERTY(QPointF point1 READ point1) + Q_PROPERTY(QPointF point2 READ point2) + Q_PROPERTY(int pointCount READ pointCount) + Q_PROPERTY(bool accepted READ accepted WRITE setAccepted) + +public: + QGeoMapPinchEvent(const QPointF ¢er, qreal angle, + const QPointF &point1, const QPointF &point2, + int pointCount = 0, bool accepted = true) + : QObject(), m_center(center), m_angle(angle), + m_point1(point1), m_point2(point2), + m_pointCount(pointCount), m_accepted(accepted) {} + QGeoMapPinchEvent() + : QObject(), + m_angle(0.0), + m_pointCount(0), + m_accepted(true) {} + + QPointF center() const { return m_center; } + void setCenter(const QPointF ¢er) { m_center = center; } + qreal angle() const { return m_angle; } + void setAngle(qreal angle) { m_angle = angle; } + QPointF point1() const { return m_point1; } + void setPoint1(const QPointF &p) { m_point1 = p; } + QPointF point2() const { return m_point2; } + void setPoint2(const QPointF &p) { m_point2 = p; } + int pointCount() const { return m_pointCount; } + void setPointCount(int count) { m_pointCount = count; } + bool accepted() const { return m_accepted; } + void setAccepted(bool a) { m_accepted = a; } + +private: + QPointF m_center; + qreal m_angle; + QPointF m_point1; + QPointF m_point2; + int m_pointCount; + bool m_accepted; +}; + +class QQuickGeoMapGestureArea: public QQuickItem +{ + Q_OBJECT + Q_ENUMS(GeoMapGesture) + Q_FLAGS(AcceptedGestures) + + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(bool pinchActive READ isPinchActive NOTIFY pinchActiveChanged) + Q_PROPERTY(bool panActive READ isPanActive NOTIFY panActiveChanged) + Q_PROPERTY(AcceptedGestures acceptedGestures READ acceptedGestures WRITE setAcceptedGestures NOTIFY acceptedGesturesChanged) + Q_PROPERTY(qreal maximumZoomLevelChange READ maximumZoomLevelChange WRITE setMaximumZoomLevelChange NOTIFY maximumZoomLevelChangeChanged) + Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) + Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged REVISION 1) + +public: + QQuickGeoMapGestureArea(QDeclarativeGeoMap *map); + ~QQuickGeoMapGestureArea(); + + enum GeoMapGesture { + NoGesture = 0x0000, + PinchGesture = 0x0001, + PanGesture = 0x0002, + FlickGesture = 0x004 + }; + + Q_DECLARE_FLAGS(AcceptedGestures, GeoMapGesture) + + AcceptedGestures acceptedGestures() const; + void setAcceptedGestures(AcceptedGestures acceptedGestures); + + bool isPinchActive() const; + bool isPanActive() const; + bool isActive() const; + + bool enabled() const; + void setEnabled(bool enabled); + + qreal maximumZoomLevelChange() const; + void setMaximumZoomLevelChange(qreal maxChange); + + qreal flickDeceleration() const; + void setFlickDeceleration(qreal deceleration); + + void handleTouchEvent(QTouchEvent *event); + void handleWheelEvent(QWheelEvent *event); + void handleMousePressEvent(QMouseEvent *event); + void handleMouseMoveEvent(QMouseEvent *event); + void handleMouseReleaseEvent(QMouseEvent *event); + void handleMouseUngrabEvent(); + void handleTouchUngrabEvent(); + + void setMinimumZoomLevel(qreal min); + qreal minimumZoomLevel() const; + + void setMaximumZoomLevel(qreal max); + qreal maximumZoomLevel() const; + + void setMap(QGeoMap *map); + + bool preventStealing() const; + void setPreventStealing(bool prevent); + +Q_SIGNALS: + void panActiveChanged(); + void pinchActiveChanged(); + void enabledChanged(); + void maximumZoomLevelChangeChanged(); + void acceptedGesturesChanged(); + void flickDecelerationChanged(); + void pinchStarted(QGeoMapPinchEvent *pinch); + void pinchUpdated(QGeoMapPinchEvent *pinch); + void pinchFinished(QGeoMapPinchEvent *pinch); + void panStarted(); + void panFinished(); + void flickStarted(); + void flickFinished(); + void preventStealingChanged(); +private: + void update(); + + // Create general data relating to the touch points + void touchPointStateMachine(); + void startOneTouchPoint(); + void updateOneTouchPoint(); + void startTwoTouchPoints(); + void updateTwoTouchPoints(); + + // All pinch related code, which encompasses zoom + void pinchStateMachine(); + bool canStartPinch(); + void startPinch(); + void updatePinch(); + void endPinch(); + + // Pan related code (regardles of number of touch points), + // includes the flick based panning after letting go + void panStateMachine(); + bool canStartPan(); + void updatePan(); + bool tryStartFlick(); + void startFlick(int dx, int dy, int timeMs = 0); + void stopFlick(); + + bool pinchEnabled() const; + void setPinchEnabled(bool enabled); + bool panEnabled() const; + void setPanEnabled(bool enabled); + bool flickEnabled() const; + void setFlickEnabled(bool enabled); + +private Q_SLOTS: + void handleFlickAnimationStopped(); + + +private: + void stopPan(); + void clearTouchData(); + void updateVelocityList(const QPointF &pos); + +private: + QGeoMap *m_map; + QDeclarativeGeoMap *m_declarativeMap; + bool m_enabled; + + struct Pinch + { + Pinch() : m_enabled(true), m_startDist(0), m_lastAngle(0.0) {} + + QGeoMapPinchEvent m_event; + bool m_enabled; + struct Zoom + { + Zoom() : m_minimum(-1.0), m_maximum(20.0), m_start(0.0), m_previous(0.0), + maximumChange(4.0) {} + qreal m_minimum; + qreal m_maximum; + qreal m_start; + qreal m_previous; + qreal maximumChange; + } m_zoom; + + QPointF m_lastPoint1; + QPointF m_lastPoint2; + qreal m_startDist; + qreal m_lastAngle; + } m_pinch; + + AcceptedGestures m_acceptedGestures; + + struct Pan + { + qreal m_maxVelocity; + qreal m_deceleration; + QQuickGeoCoordinateAnimation *m_animation; + bool m_enabled; + } m_flick; + + + // these are calculated regardless of gesture or number of touch points + qreal m_velocityX; + qreal m_velocityY; + QElapsedTimer m_lastPosTime; + QPointF m_lastPos; + QList m_allPoints; + QList m_touchPoints; + QScopedPointer m_mousePoint; + QPointF m_sceneStartPoint1; + + // only set when two points in contact + QPointF m_sceneStartPoint2; + QGeoCoordinate m_startCoord; + QGeoCoordinate m_touchCenterCoord; + qreal m_twoTouchAngle; + qreal m_distanceBetweenTouchPoints; + QPointF m_sceneCenter; + bool m_preventStealing; + bool m_panEnabled; + + // prototype state machine... + enum TouchPointState + { + touchPoints0, + touchPoints1, + touchPoints2 + } m_touchPointState; + + enum PinchState + { + pinchInactive, + pinchInactiveTwoPoints, + pinchActive + } m_pinchState; + + enum FlickState + { + flickInactive, + panActive, + flickActive + } m_flickState; +}; + +QT_END_NAMESPACE +QML_DECLARE_TYPE(QQuickGeoMapGestureArea) + +#endif // QQUICKGEOMAPGESTUREAREA_P_H diff --git a/src/imports/positioning/locationsingleton.cpp b/src/imports/positioning/locationsingleton.cpp new file mode 100644 index 0000000..f12486b --- /dev/null +++ b/src/imports/positioning/locationsingleton.cpp @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "locationsingleton.h" + +/*! + \qmltype QtPositioning + \instantiates LocationSingleton + \inqmlmodule QtPositioning + \since 5.2 + + \brief The QtPositioning global object provides useful functions for working with location-based + types in QML. + + \qml + import QtPositioning 5.2 + + Item { + property variant coordinate: QtPositioning.coordinate(-27.5, 153.1) + } + \endqml +*/ + +LocationSingleton::LocationSingleton(QObject *parent) +: QObject(parent) +{ +} + +/*! + \qmlmethod coordinate ::QtPositioning::coordinate() + + Constructs an invalid coordinate. + +*/ +QGeoCoordinate LocationSingleton::coordinate() const +{ + return QGeoCoordinate(); +} + +/*! + \qmlmethod coordinate QtPositioning::coordinate(real latitude, real longitue, real altitude) const + + Constructs a coordinate with the specified \a latitude, \a longitude and optional \a altitude. + Both \a latitude and \a longitude must be valid, otherwise an invalid coordinate is returned. + + \sa {coordinate} +*/ +QGeoCoordinate LocationSingleton::coordinate(double latitude, double longitude, double altitude) const +{ + return QGeoCoordinate(latitude, longitude, altitude); +} + +/*! + \qmlmethod geoshape QtPositioning::shape() const + + Constructs an invalid geoshape. + + \sa {geoshape} +*/ +QGeoShape LocationSingleton::shape() const +{ + return QGeoShape(); +} + +/*! + \qmlmethod georectangle QtPositioning::rectangle() const + + Constructs an invalid georectangle. + + \sa {georectangle} +*/ +QGeoRectangle LocationSingleton::rectangle() const +{ + return QGeoRectangle(); +} + +/*! + \qmlmethod georectangle QtPositioning::rectangle(coordinate center, real width, real height) const + + Constructs a georectangle centered at \a center with a width of \a width degrees and a hight of + \a height degrees. + + \sa {georectangle} +*/ +QGeoRectangle LocationSingleton::rectangle(const QGeoCoordinate ¢er, + double width, double height) const +{ + return QGeoRectangle(center, width, height); +} + +/*! + \qmlmethod georectangle QtPositioning::rectangle(coordinate topLeft, coordinate bottomRight) const + + Constructs a georectangle with its top left corner positioned at \a topLeft and its bottom + right corner positioned at \a {bottomLeft}. + + \sa {georectangle} +*/ +QGeoRectangle LocationSingleton::rectangle(const QGeoCoordinate &topLeft, + const QGeoCoordinate &bottomRight) const +{ + return QGeoRectangle(topLeft, bottomRight); +} + +/*! + \qmlmethod georectangle QtLocation5::QtLocation::rectangle(list coordinates) const + + Constructs a georectangle from the list of coordinates, the returned list is the smallest possible + containing all the coordinates. + + \sa {georectangle} +*/ +QGeoRectangle LocationSingleton::rectangle(const QVariantList &coordinates) const +{ + QList internalCoordinates; + for (int i = 0; i < coordinates.size(); i++) { + if (coordinates.at(i).canConvert()) + internalCoordinates << coordinates.at(i).value(); + } + return QGeoRectangle(internalCoordinates); +} + +/*! + \qmlmethod geocircle QtPositioning::circle() const + + Constructs an invalid geocircle. + + \sa {geocircle} +*/ +QGeoCircle LocationSingleton::circle() const +{ + return QGeoCircle(); +} + +/*! + \qmlmethod geocircle QtPositioning::circle(coordinate center, real radius) const + + Constructs a geocircle centered at \a center with a radius of \a radius meters. +*/ +QGeoCircle LocationSingleton::circle(const QGeoCoordinate ¢er, qreal radius) const +{ + return QGeoCircle(center, radius); +} + +/*! + \qmlmethod geocircle QtPositioning::shapeToCircle(geoshape shape) const + + Converts \a shape to a geocircle. + + \sa {geocircle} + \since 5.5 +*/ +QGeoCircle LocationSingleton::shapeToCircle(const QGeoShape &shape) const +{ + return QGeoCircle(shape); +} + +/*! + \qmlmethod georectangle QtPositioning::shapeToRectangle(geoshape shape) const + + Converts \a shape to a georectangle. + + \sa {georectangle} + \since 5.5 +*/ +QGeoRectangle LocationSingleton::shapeToRectangle(const QGeoShape &shape) const +{ + return QGeoRectangle(shape); +} + diff --git a/src/imports/positioning/locationsingleton.h b/src/imports/positioning/locationsingleton.h new file mode 100644 index 0000000..cc4ea5c --- /dev/null +++ b/src/imports/positioning/locationsingleton.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LOCATIONSINGLETON_H +#define LOCATIONSINGLETON_H + +#include +#include +#include +#include +#include +#include +#include + +class LocationSingleton : public QObject +{ + Q_OBJECT + +public: + explicit LocationSingleton(QObject *parent = 0); + + Q_INVOKABLE QGeoCoordinate coordinate() const; + Q_INVOKABLE QGeoCoordinate coordinate(double latitude, double longitude, + double altitude = qQNaN()) const; + + Q_INVOKABLE QGeoShape shape() const; + + Q_INVOKABLE QGeoRectangle rectangle() const; + Q_INVOKABLE QGeoRectangle rectangle(const QGeoCoordinate ¢er, + double width, double height) const; + Q_INVOKABLE QGeoRectangle rectangle(const QGeoCoordinate &topLeft, + const QGeoCoordinate &bottomRight) const; + Q_INVOKABLE QGeoRectangle rectangle(const QVariantList &coordinates) const; + + Q_INVOKABLE QGeoCircle circle() const; + Q_INVOKABLE QGeoCircle circle(const QGeoCoordinate ¢er, qreal radius = -1.0) const; + + Q_INVOKABLE QGeoCircle shapeToCircle(const QGeoShape &shape) const; + Q_INVOKABLE QGeoRectangle shapeToRectangle(const QGeoShape &shape) const; +}; + +#endif // LOCATIONSINGLETON_H diff --git a/src/imports/positioning/plugin.json b/src/imports/positioning/plugin.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/src/imports/positioning/plugin.json @@ -0,0 +1,2 @@ +{ +} diff --git a/src/imports/positioning/plugins.qmltypes b/src/imports/positioning/plugins.qmltypes new file mode 100644 index 0000000..55fcbba --- /dev/null +++ b/src/imports/positioning/plugins.qmltypes @@ -0,0 +1,224 @@ +import QtQuick.tooling 1.2 + +// This file describes the plugin-supplied types contained in the library. +// It is used for QML tooling purposes only. +// +// This file was auto-generated by: +// 'qmlplugindump -nonrelocatable QtPositioning 5.7' + +Module { + dependencies: ["QtQuick 2.0"] + Component { + name: "LocationSingleton" + prototype: "QObject" + exports: ["QtPositioning/QtPositioning 5.0"] + isCreatable: false + isSingleton: true + exportMetaObjectRevisions: [0] + Method { name: "coordinate"; type: "QGeoCoordinate" } + Method { + name: "coordinate" + type: "QGeoCoordinate" + Parameter { name: "latitude"; type: "double" } + Parameter { name: "longitude"; type: "double" } + Parameter { name: "altitude"; type: "double" } + } + Method { + name: "coordinate" + type: "QGeoCoordinate" + Parameter { name: "latitude"; type: "double" } + Parameter { name: "longitude"; type: "double" } + } + Method { name: "shape"; type: "QGeoShape" } + Method { name: "rectangle"; type: "QGeoRectangle" } + Method { + name: "rectangle" + type: "QGeoRectangle" + Parameter { name: "center"; type: "QGeoCoordinate" } + Parameter { name: "width"; type: "double" } + Parameter { name: "height"; type: "double" } + } + Method { + name: "rectangle" + type: "QGeoRectangle" + Parameter { name: "topLeft"; type: "QGeoCoordinate" } + Parameter { name: "bottomRight"; type: "QGeoCoordinate" } + } + Method { + name: "rectangle" + type: "QGeoRectangle" + Parameter { name: "coordinates"; type: "QVariantList" } + } + Method { name: "circle"; type: "QGeoCircle" } + Method { + name: "circle" + type: "QGeoCircle" + Parameter { name: "center"; type: "QGeoCoordinate" } + Parameter { name: "radius"; type: "double" } + } + Method { + name: "circle" + type: "QGeoCircle" + Parameter { name: "center"; type: "QGeoCoordinate" } + } + Method { + name: "shapeToCircle" + type: "QGeoCircle" + Parameter { name: "shape"; type: "QGeoShape" } + } + Method { + name: "shapeToRectangle" + type: "QGeoRectangle" + Parameter { name: "shape"; type: "QGeoShape" } + } + } + Component { + name: "QDeclarativeGeoAddress" + prototype: "QObject" + exports: ["QtPositioning/Address 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "address"; type: "QGeoAddress" } + Property { name: "text"; type: "string" } + Property { name: "country"; type: "string" } + Property { name: "countryCode"; type: "string" } + Property { name: "state"; type: "string" } + Property { name: "county"; type: "string" } + Property { name: "city"; type: "string" } + Property { name: "district"; type: "string" } + Property { name: "street"; type: "string" } + Property { name: "postalCode"; type: "string" } + Property { name: "isTextGenerated"; type: "bool"; isReadonly: true } + } + Component { + name: "QDeclarativeGeoLocation" + prototype: "QObject" + exports: ["QtPositioning/Location 5.0"] + exportMetaObjectRevisions: [0] + Property { name: "location"; type: "QGeoLocation" } + Property { name: "address"; type: "QDeclarativeGeoAddress"; isPointer: true } + Property { name: "coordinate"; type: "QGeoCoordinate" } + Property { name: "boundingBox"; type: "QGeoRectangle" } + } + Component { + name: "QDeclarativePosition" + prototype: "QObject" + exports: [ + "QtPositioning/Position 5.0", + "QtPositioning/Position 5.3", + "QtPositioning/Position 5.4", + "QtPositioning/Position 5.7" + ] + exportMetaObjectRevisions: [0, 1, 2, 2] + Property { name: "latitudeValid"; type: "bool"; isReadonly: true } + Property { name: "longitudeValid"; type: "bool"; isReadonly: true } + Property { name: "altitudeValid"; type: "bool"; isReadonly: true } + Property { name: "coordinate"; type: "QGeoCoordinate"; isReadonly: true } + Property { name: "timestamp"; type: "QDateTime"; isReadonly: true } + Property { name: "speed"; type: "double"; isReadonly: true } + Property { name: "speedValid"; type: "bool"; isReadonly: true } + Property { name: "horizontalAccuracy"; type: "double" } + Property { name: "verticalAccuracy"; type: "double" } + Property { name: "horizontalAccuracyValid"; type: "bool"; isReadonly: true } + Property { name: "verticalAccuracyValid"; type: "bool"; isReadonly: true } + Property { name: "directionValid"; revision: 1; type: "bool"; isReadonly: true } + Property { name: "direction"; revision: 1; type: "double"; isReadonly: true } + Property { name: "verticalSpeedValid"; revision: 1; type: "bool"; isReadonly: true } + Property { name: "verticalSpeed"; revision: 1; type: "double"; isReadonly: true } + Property { name: "magneticVariation"; revision: 2; type: "double"; isReadonly: true } + Property { name: "magneticVariationValid"; revision: 2; type: "bool"; isReadonly: true } + Signal { name: "directionValidChanged"; revision: 1 } + Signal { name: "directionChanged"; revision: 1 } + Signal { name: "verticalSpeedValidChanged"; revision: 1 } + Signal { name: "verticalSpeedChanged"; revision: 1 } + Signal { name: "magneticVariationChanged"; revision: 2 } + Signal { name: "magneticVariationValidChanged"; revision: 2 } + } + Component { + name: "QDeclarativePositionSource" + prototype: "QObject" + exports: ["QtPositioning/PositionSource 5.0"] + exportMetaObjectRevisions: [0] + Enum { + name: "PositioningMethod" + values: { + "NoPositioningMethods": 0, + "SatellitePositioningMethods": 255, + "NonSatellitePositioningMethods": -256, + "AllPositioningMethods": -1 + } + } + Enum { + name: "PositioningMethods" + values: { + "NoPositioningMethods": 0, + "SatellitePositioningMethods": 255, + "NonSatellitePositioningMethods": -256, + "AllPositioningMethods": -1 + } + } + Enum { + name: "SourceError" + values: { + "AccessError": 0, + "ClosedError": 1, + "UnknownSourceError": 2, + "NoError": 3, + "SocketError": 100 + } + } + Property { name: "position"; type: "QDeclarativePosition"; isReadonly: true; isPointer: true } + Property { name: "active"; type: "bool" } + Property { name: "valid"; type: "bool"; isReadonly: true } + Property { name: "nmeaSource"; type: "QUrl" } + Property { name: "updateInterval"; type: "int" } + Property { name: "supportedPositioningMethods"; type: "PositioningMethods"; isReadonly: true } + Property { name: "preferredPositioningMethods"; type: "PositioningMethods" } + Property { name: "sourceError"; type: "SourceError"; isReadonly: true } + Property { name: "name"; type: "string" } + Signal { name: "validityChanged" } + Signal { name: "updateTimeout" } + Method { name: "update" } + Method { name: "start" } + Method { name: "stop" } + } + Component { + name: "QGeoShape" + exports: ["QtPositioning/GeoShape 5.0"] + isCreatable: false + exportMetaObjectRevisions: [0] + Enum { + name: "ShapeType" + values: { + "UnknownType": 0, + "RectangleType": 1, + "CircleType": 2 + } + } + Property { name: "type"; type: "ShapeType"; isReadonly: true } + Property { name: "isValid"; type: "bool"; isReadonly: true } + Property { name: "isEmpty"; type: "bool"; isReadonly: true } + Method { + name: "contains" + type: "bool" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + } + Method { name: "toString"; type: "string" } + } + Component { + name: "QQuickGeoCoordinateAnimation" + prototype: "QQuickPropertyAnimation" + exports: ["QtPositioning/CoordinateAnimation 5.3"] + exportMetaObjectRevisions: [0] + Enum { + name: "Direction" + values: { + "Shortest": 0, + "West": 1, + "East": 2 + } + } + Property { name: "from"; type: "QGeoCoordinate" } + Property { name: "to"; type: "QGeoCoordinate" } + Property { name: "direction"; type: "Direction" } + } +} diff --git a/src/imports/positioning/positioning.cpp b/src/imports/positioning/positioning.cpp new file mode 100644 index 0000000..5137da2 --- /dev/null +++ b/src/imports/positioning/positioning.cpp @@ -0,0 +1,566 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include + +#include "qdeclarativepositionsource_p.h" +#include "qdeclarativeposition_p.h" + +#include "qquickgeocoordinateanimation_p.h" +#include "locationsingleton.h" + +#include + +#include +#include + +#include +#include +#include + +#include + +static void initResources() +{ +#ifdef QT_STATIC + Q_INIT_RESOURCE(qmake_QtPositioning); +#endif +} + +QT_BEGIN_NAMESPACE + +/*! + \qmlbasictype coordinate + \inqmlmodule QtPositioning + \ingroup qml-QtPositioning5-basictypes + \since 5.2 + + \brief The coordinate type represents and stores a geographic position. + + This type is a QML representation of \l QGeoCoordinate and represents a geographic + position in the form of \l {latitude}, \l longitude and \l altitude attributes. + The \l latitude attribute specifies the number of + decimal degrees above and below the equator. A positive latitude indicates the Northern + Hemisphere and a negative latitude indicates the Southern Hemisphere. The \l longitude + attribute specifies the number of decimal degrees east and west. A positive longitude + indicates the Eastern Hemisphere and a negative longitude indicates the Western Hemisphere. + The \l altitude attribute specifies the number of meters above sea level. Together, these + attributes specify a 3-dimensional position anywhere on or near the Earth's surface. + + The \l isValid attribute can be used to test if a coordinate is valid. A coordinate is + considered valid if it has a valid latitude and longitude. A valid altitude is not required. + The latitude must be between -90 and 90 inclusive and the longitude must be between -180 and + 180 inclusive. + + The \c coordinate type is used by many other types in the Qt Location module, for specifying + the position of an object on a Map, the current position of a device and many other tasks. + They also feature a number of important utility methods that make otherwise complex + calculations simple to use, such as \l {atDistanceAndAzimuth}(). + + \section1 Accuracy + + The latitude, longitude and altitude attributes stored in the coordinate type are represented + as doubles, giving them approximately 16 decimal digits of precision -- enough to specify + micrometers. The calculations performed in coordinate's methods such as \l {azimuthTo}() and + \l {distanceTo}() also use doubles for all intermediate values, but the inherent inaccuracies in + their spherical Earth model dominate the amount of error in their output. + + \section1 Example Usage + + Use properties of type \l variant to store a \c {coordinate}. To create a \c coordinate use + one of the methods described below. In all cases, specifying the \l altitude attribute is + optional. + + To create a \c coordinate value, use the \l{QtPositioning::coordinate}{QtPositioning.coordinate()} + function: + + \qml + import QtPositioning 5.2 + + Location { coordinate: QtPositioning.coordinate(-27.5, 153.1) } + \endqml + + or as separate \l latitude, \l longitude and \l altitude components: + + \qml + Location { + coordinate { + latitude: -27.5 + longitude: 153.1 + } + } + \endqml + + When integrating with C++, note that any QGeoCoordinate value passed into QML from C++ is + automatically converted into a \c coordinate value, and vice-versa. + + \section1 Properties + + \section2 latitude + + \code + real latitude + \endcode + + This property holds the latitude value of the geographical position + (decimal degrees). A positive latitude indicates the Northern Hemisphere, + and a negative latitude indicates the Southern Hemisphere. + If the property has not been set, its default value is NaN. + + For more details see the \l {QGeoCoordinate::latitude} property + + \section2 longitude + + \code + real longitude + \endcode + + This property holds the longitude value of the geographical position + (decimal degrees). A positive longitude indicates the Eastern Hemisphere, + and a negative longitude indicates the Western Hemisphere + If the property has not been set, its default value is NaN. + + For more details see the \l {QGeoCoordinate::longitude} property + + \section2 altitude + + \code + real altitude + \endcode + + This property holds the altitude value (meters above sea level). + If the property has not been set, its default value is NaN. + + For more details see the \l {QGeoCoordinate::altitude} property + + \section2 isValid + + \code + bool isValid + \endcode + + This property holds the current validity of the coordinate. Coordinates + are considered valid if they have been set with a valid latitude and + longitude (altitude is not required). + + The latitude must be between -90 to 90 inclusive to be considered valid, + and the longitude must be between -180 to 180 inclusive to be considered + valid. + + This is a read-only property. + + \section1 Methods + + \section2 distanceTo() + + \code + real distanceTo(coordinate other) + \endcode + + Returns the distance (in meters) from this coordinate to the coordinate specified by \a other. + Altitude is not used in the calculation. + + This calculation returns the great-circle distance between the two coordinates, with an + assumption that the Earth is spherical for the purpose of this calculation. + + \section2 azimuthTo() + + \code + real azimuth(coordinate other) + \endcode + + Returns the azimuth (or bearing) in degrees from this coordinate to the coordinate specified by + \a other. Altitude is not used in the calculation. + + There is an assumption that the Earth is spherical for the purpose of this calculation. + + \section2 atDistanceAndAzimuth() + + \code + coordinate atDistanceAndAzimuth(real distance, real azimuth) + \endcode + + Returns the coordinate that is reached by traveling \a distance metres from this coordinate at + \a azimuth degrees along a great-circle. + + There is an assumption that the Earth is spherical for the purpose of this calculation. +*/ + +/*! + \qmlbasictype geoshape + \inqmlmodule QtPositioning + \ingroup qml-QtPositioning5-basictypes + \since 5.2 + + \brief A geoshape type represents an abstract geographic area. + + This type is a QML representation of \l QGeoShape which is an abstract geographic area. + It includes attributes and methods common to all geographic areas. To create objects + that represent a valid geographic area use \l {georectangle} or \l {geocircle}. + + The \l isValid attribute can be used to test if the geoshape represents a valid geographic + area. + + The \l isEmpty attribute can be used to test if the geoshape represents a region with a + geometrical area of 0. + + The \l {contains}{contains()} method can be used to test if a \l {coordinate} is + within the geoshape. + + \section1 Example Usage + + Use properties of type \l variant to store a \c {geoshape}. To create a \c geoshape use one + of the methods described below. + + To create a \c geoshape value, specify it as a "shape()" string: + + \qml + import QtPositioning + + Item { + property variant region: "shape()" + } + \endqml + + or with the \l {QtPositioning::shape}{QtPositioning.shape()} function: + + \qml + import QtPositioning 5.2 + + Item { + property variant region: QtPositioning.shape() + } + \endqml + + When integrating with C++, note that any QGeoShape value passed into QML from C++ is + automatically converted into a \c geoshape value, and vice-versa. + + \section1 Properties + + \section2 isEmpty + + \code + bool isEmpty + \endcode + + Returns whether this geoshape is empty. An empty geoshape is a region which has + a geometrical area of 0. + + \section2 isValid + + \code + bool isValid + \endcode + + Returns whether this geoshape is valid. + + A geoshape is considered to be invalid if some of the data that is required to + unambiguously describe the geoshape has not been set or has been set to an + unsuitable value. + + \section2 type + + \code + ShapeType type + \endcode + + Returns the current type of the shape. + + \list + \li GeoShape.UnknownType - The shape's type is not known. + \li GeoShape.RectangleType - The shape is a \l georectangle. + \li GeoShape.CircleType - The shape is a \l geocircle. + \endlist + + This QML property was introduced by Qt 5.5. + + \section1 Methods + + \section2 contains() + + \code + bool contains(coordinate coord) + \endcode + + Returns true if the \l {QtPositioning::coordinate}{coordinate} specified by \a coord is within + this geoshape; Otherwise returns false. +*/ + +/*! + \qmlbasictype georectangle + \inqmlmodule QtPositioning + \ingroup qml-QtPositioning5-basictypes + \since 5.2 + + \brief The georectangle type represents a rectangular geographic area. + + The \c georectangle type is a \l {geoshape} that represents a + rectangular geographic area. The type is direct representation of a \l QGeoRectangle. + It is defined by a pair of \l {coordinate}{coordinates} which represent the top-left + and bottom-right corners of the \c {georectangle}. The coordinates are accessible + from the \l topLeft and \l bottomRight attributes. + + A \c georectangle is considered invalid if the top-left or bottom-right coordinates are invalid + or if the top-left coordinate is south of the bottom-right coordinate. + + The coordinates of the four corners of the \c georectangle can be accessed with the + \l {topLeft}, \l {topRight}, \l {bottomLeft} and \l {bottomRight} attributes. The \l center + attribute can be used to get the coordinate of the center of the \c georectangle. The \l width + and \l height attributes can be used to get the width and height of the \c georectangle in + degrees. Setting one of these attributes will cause the other attributes to be adjusted + accordingly. + + \section1 Limitations + + A \c georectangle can never cross the poles. + + If the height or center of a \c georectangle is adjusted such that it would cross one of the + poles the height is modified such that the \c georectangle touches but does not cross the pole + and that the center coordinate is still in the center of the \c georectangle. + + \section1 Example Usage + + Use properties of type \l variant to store a \c {georectangle}. To create a \c georectangle + value, use the \l {QtPositioning::rectangle}{QtPositioning.rectangle()} function: + + \qml + import QtPositioning 5.2 + + Item { + property variant region: QtPositioning.rectangle(QtPositioning.coordinate(-27.5, 153.1), QtPositioning.coordinate(-27.6, 153.2)) + } + \endqml + + When integrating with C++, note that any QGeoRectangle value passed into QML from C++ is + automatically converted into a \c georectangle value, and vice-versa. + + \section1 Properties + + \section2 bottomLeft + + \code + coordinate bottomLeft + \endcode + + This property holds the bottom left coordinate of this georectangle. + + \section2 bottomRight + + \code + coordinate bottomRight + \endcode + + This property holds the bottom right coordinate of this georectangle. + + \section2 center + + \code + coordinate center + \endcode + + This property holds the center coordinate of this georectangle. For more details + see \l {QGeoRectangle::setCenter()}. + + \section2 height + + \code + double height + \endcode + + This property holds the height of this georectangle (in degrees). For more details + see \l {QGeoRectangle::setHeight()}. + + \note If the georectangle is invalid, it is not possible to set the height. QtPositioning + releases prior to Qt 5.5 permitted the setting of the height even on invalid georectangles. + + \section2 topLeft + + \code + coordinate topLeft + \endcode + + This property holds the top left coordinate of this georectangle. + + \section2 topRight + + \code + coordinate topRight + \endcode + + This property holds the top right coordinate of this georectangle. + + \section2 width + + \code + double width + \endcode + + This property holds the width of this georectangle (in degrees). For more details + see \l {QGeoRectangle::setWidth()}. + + \note If the georectangle is invalid, it is not possible to set the width. QtPositioning + releases prior to Qt 5.5 permitted the setting of the width even on invalid georectangles. +*/ + +/*! + \qmlbasictype geocircle + \inqmlmodule QtPositioning + \ingroup qml-QtPositioning5-basictypes + \since 5.2 + + \brief The geocircle type represents a circular geographic area. + + The \c geocircle type is a \l {geoshape} that represents a circular + geographic area. It is a direct representation of a \l QGeoCircle and is defined + in terms of a \l {coordinate} which specifies the \l center of the circle and + a qreal which specifies the \l radius of the circle in meters. + + The circle is considered invalid if the \l center coordinate is invalid or if + the \l radius is less than zero. + + \section1 Example Usage + + Use properties of type \l variant to store a \c {geocircle}. To create a \c geocircle value, + use the \l {QtPositioning::circle}{QtPositioning.circle()} function: + + \qml + import QtPositioning 5.2 + + Item { + property variant region: QtPositioning.circle(QtPositioning.coordinate(-27.5, 153.1), 1000) + } + \endqml + + When integrating with C++, note that any QGeoCircle value passed into QML from C++ is + automatically converted into a \c geocircle value, and vise-versa. + + \section1 Properties + + \section2 center + + \code + coordinate radius + \endcode + + This property holds the coordinate of the center of the geocircle. + + \section2 radius + + \code + real radius + \endcode + + This property holds the radius of the geocircle in meters. + + The default value for the radius is -1 indicating an invalid geocircle area. +*/ + +static QObject *singleton_type_factory(QQmlEngine *engine, QJSEngine *jsEngine) +{ + Q_UNUSED(engine) + Q_UNUSED(jsEngine) + + return new LocationSingleton; +} + +class QtPositioningDeclarativeModule: public QQmlExtensionPlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0" + FILE "plugin.json") + +public: + QtPositioningDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } + virtual void registerTypes(const char *uri) + { + if (QLatin1String(uri) == QStringLiteral("QtPositioning")) { + + // @uri QtPositioning 5.0 + + int major = 5; + int minor = 0; + + qRegisterMetaType(); + QMetaType::registerEqualsComparator(); + qRegisterMetaType(); + qRegisterMetaType(); + QMetaType::registerEqualsComparator(); + qRegisterMetaType(); + QMetaType::registerEqualsComparator(); + qRegisterMetaType(); + qRegisterMetaType(); + QMetaType::registerEqualsComparator(); + + qRegisterAnimationInterpolator(q_coordinateInterpolator); + + // Register the 5.0 types + // 5.0 is silent and not advertised + qmlRegisterSingletonType(uri, major, minor, "QtPositioning", singleton_type_factory); + qmlRegisterValueTypeEnums(uri, major, minor, "GeoShape"); + qmlRegisterType(uri, major, minor, "Position"); + qmlRegisterType(uri, major, minor, "PositionSource"); + qmlRegisterType(uri, major, minor, "Address"); + qmlRegisterType(uri, major, minor, "Location"); + + // Register the 5.3 types + // Introduction of 5.3 version; existing 5.0 exports become automatically available under 5.3 + minor = 3; + qmlRegisterType(uri, major, minor, "CoordinateAnimation"); + qmlRegisterType(uri, major, minor, "Position"); + + // Register the 5.4 types + // Introduction of 5.4 version; existing 5.3 exports become automatically available under 5.4 + minor = 4; + qmlRegisterType(uri, major, minor, "Position"); + + minor = 7; + qmlRegisterType(uri, major, minor, "Position"); + } else { + qDebug() << "Unsupported URI given to load positioning QML plugin: " << QLatin1String(uri); + } + } +}; + +#include "positioning.moc" + +QT_END_NAMESPACE diff --git a/src/imports/positioning/positioning.pro b/src/imports/positioning/positioning.pro new file mode 100644 index 0000000..119c3de --- /dev/null +++ b/src/imports/positioning/positioning.pro @@ -0,0 +1,21 @@ +QT += quick-private positioning-private qml-private core-private + +INCLUDEPATH *= $$PWD + +HEADERS += qdeclarativeposition_p.h \ + qdeclarativepositionsource_p.h \ + locationsingleton.h \ + qquickgeocoordinateanimation_p.h \ + qquickgeocoordinateanimation_p_p.h + +SOURCES += qdeclarativeposition.cpp \ + positioning.cpp \ + qdeclarativepositionsource.cpp \ + locationsingleton.cpp \ + qquickgeocoordinateanimation.cpp + +load(qml_plugin) + +OTHER_FILES += \ + plugin.json \ + qmldir diff --git a/src/imports/positioning/qdeclarativeposition.cpp b/src/imports/positioning/qdeclarativeposition.cpp new file mode 100644 index 0000000..50313de --- /dev/null +++ b/src/imports/positioning/qdeclarativeposition.cpp @@ -0,0 +1,471 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "qdeclarativeposition_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Position + \instantiates QDeclarativePosition + \inqmlmodule QtPositioning + \since 5.2 + + \brief The Position type holds positional data at a particular point in time, + such as coordinate (longitude, latitude, altitude) and speed. + + The Position type holds values related to geographic location such as + a \l coordinate (longitude, latitude, and altitude), the \l timestamp when + the Position was obtained, the \l speed at that time, and the accuracy of + the data. + + Primarily, it is used in the \l{PositionSource::position}{position} property + of a \l{PositionSource}, as the basic unit of data available from the system + location data source. + + Not all properties of a Position object are necessarily valid or available + (for example latitude and longitude may be valid, but speed update has not been + received or set manually). As a result, corresponding "valid" properties + are available (for example \l{coordinate} and \l{longitudeValid}, \l{latitudeValid} + etc) to discern whether the data is available and valid in this position + update. + + Position objects are read-only and can only be produced by a PositionSource. + + \section2 Example Usage + + See the example given for the \l{PositionSource} type, or the + \l{geoflickr}{GeoFlickr} example application. + + \sa PositionSource, coordinate +*/ + +namespace +{ + +bool equalOrNaN(qreal a, qreal b) +{ + return a == b || (qIsNaN(a) && qIsNaN(b)); +} + +bool exclusiveNaN(qreal a, qreal b) +{ + return qIsNaN(a) != qIsNaN(b); +} + +} + +QDeclarativePosition::QDeclarativePosition(QObject *parent) +: QObject(parent) +{ +} + +QDeclarativePosition::~QDeclarativePosition() +{ +} + +void QDeclarativePosition::setPosition(const QGeoPositionInfo &info) +{ + // timestamp + const QDateTime pTimestamp = m_info.timestamp(); + const QDateTime timestamp = info.timestamp(); + bool emitTimestampChanged = pTimestamp != timestamp; + + // coordinate + const QGeoCoordinate pCoordinate = m_info.coordinate(); + const QGeoCoordinate coordinate = info.coordinate(); + bool emitCoordinateChanged = pCoordinate != coordinate; + bool emitLatitudeValidChanged = exclusiveNaN(pCoordinate.latitude(), coordinate.latitude()); + bool emitLongitudeValidChanged = exclusiveNaN(pCoordinate.longitude(), coordinate.longitude()); + bool emitAltitudeValidChanged = exclusiveNaN(pCoordinate.altitude(), coordinate.altitude()); + + // direction + const qreal pDirection = m_info.attribute(QGeoPositionInfo::Direction); + const qreal direction = info.attribute(QGeoPositionInfo::Direction); + bool emitDirectionChanged = !equalOrNaN(pDirection, direction); + bool emitDirectionValidChanged = exclusiveNaN(pDirection, direction); + + // ground speed + const qreal pSpeed = m_info.attribute(QGeoPositionInfo::GroundSpeed); + const qreal speed = info.attribute(QGeoPositionInfo::GroundSpeed); + bool emitSpeedChanged = !equalOrNaN(pSpeed, speed); + bool emitSpeedValidChanged = exclusiveNaN(pSpeed, speed); + + // vertical speed + const qreal pVerticalSpeed = m_info.attribute(QGeoPositionInfo::VerticalSpeed); + const qreal verticalSpeed = info.attribute(QGeoPositionInfo::VerticalSpeed); + bool emitVerticalSpeedChanged = !equalOrNaN(pVerticalSpeed, verticalSpeed); + bool emitVerticalSpeedValidChanged = exclusiveNaN(pVerticalSpeed, verticalSpeed); + + // magnetic variation + const qreal pMagneticVariation = m_info.attribute(QGeoPositionInfo::MagneticVariation); + const qreal magneticVariation = info.attribute(QGeoPositionInfo::MagneticVariation); + bool emitMagneticVariationChanged = !equalOrNaN(pMagneticVariation, magneticVariation); + bool emitMagneticVariationValidChanged = exclusiveNaN(pMagneticVariation, magneticVariation); + + // horizontal accuracy + const qreal pHorizontalAccuracy = m_info.attribute(QGeoPositionInfo::HorizontalAccuracy); + const qreal horizontalAccuracy = info.attribute(QGeoPositionInfo::HorizontalAccuracy); + bool emitHorizontalAccuracyChanged = !equalOrNaN(pHorizontalAccuracy, horizontalAccuracy); + bool emitHorizontalAccuracyValidChanged = exclusiveNaN(pHorizontalAccuracy, horizontalAccuracy); + + // vertical accuracy + const qreal pVerticalAccuracy = m_info.attribute(QGeoPositionInfo::VerticalAccuracy); + const qreal verticalAccuracy = info.attribute(QGeoPositionInfo::VerticalAccuracy); + bool emitVerticalAccuracyChanged = !equalOrNaN(pVerticalAccuracy, verticalAccuracy); + bool emitVerticalAccuracyValidChanged = exclusiveNaN(pVerticalAccuracy, verticalAccuracy); + + m_info = info; + + if (emitTimestampChanged) + emit timestampChanged(); + if (emitCoordinateChanged) + emit coordinateChanged(); + if (emitLatitudeValidChanged) + emit latitudeValidChanged(); + if (emitLongitudeValidChanged) + emit longitudeValidChanged(); + if (emitAltitudeValidChanged) + emit altitudeValidChanged(); + if (emitDirectionChanged) + emit directionChanged(); + if (emitDirectionValidChanged) + emit directionValidChanged(); + if (emitSpeedChanged) + emit speedChanged(); + if (emitSpeedValidChanged) + emit speedValidChanged(); + if (emitVerticalSpeedChanged) + emit verticalSpeedChanged(); + if (emitVerticalSpeedValidChanged) + emit verticalSpeedValidChanged(); + if (emitHorizontalAccuracyChanged) + emit horizontalAccuracyChanged(); + if (emitHorizontalAccuracyValidChanged) + emit horizontalAccuracyValidChanged(); + if (emitVerticalAccuracyChanged) + emit verticalAccuracyChanged(); + if (emitVerticalAccuracyValidChanged) + emit verticalAccuracyValidChanged(); + if (emitMagneticVariationChanged) + emit magneticVariationChanged(); + if (emitMagneticVariationValidChanged) + emit magneticVariationValidChanged(); +} + +/*! + \qmlproperty coordinate Position::coordinate + + This property holds the latitude, longitude, and altitude value of the Position. + + It is a read-only property. + + \sa longitudeValid, latitudeValid, altitudeValid +*/ +QGeoCoordinate QDeclarativePosition::coordinate() +{ + return m_info.coordinate(); +} + +/*! + \qmlproperty bool Position::latitudeValid + + This property is true if coordinate's latitude has been set + (to indicate whether that data has been received or not, as every update + does not necessarily contain all data). + + \sa coordinate +*/ +bool QDeclarativePosition::isLatitudeValid() const +{ + return !qIsNaN(m_info.coordinate().latitude()); +} + + +/*! + \qmlproperty bool Position::longitudeValid + + This property is true if coordinate's longitude has been set + (to indicate whether that data has been received or not, as every update + does not necessarily contain all data). + + \sa coordinate +*/ +bool QDeclarativePosition::isLongitudeValid() const +{ + return !qIsNaN(m_info.coordinate().longitude()); +} + + +/*! + \qmlproperty bool Position::speedValid + + This property is true if \l speed has been set + (to indicate whether that data has been received or not, as every update + does not necessarily contain all data). + + \sa speed +*/ +bool QDeclarativePosition::isSpeedValid() const +{ + return !qIsNaN(m_info.attribute(QGeoPositionInfo::GroundSpeed)); +} + +/*! + \qmlproperty bool Position::altitudeValid + + This property is true if coordinate's altitude has been set + (to indicate whether that data has been received or not, as every update + does not necessarily contain all data). + + \sa coordinate +*/ +bool QDeclarativePosition::isAltitudeValid() const +{ + return !qIsNaN(m_info.coordinate().altitude()); +} + +/*! + \qmlproperty double Position::speed + + This property holds the value of speed (groundspeed, meters / second). + + It is a read-only property. + + \sa speedValid, coordinate +*/ +double QDeclarativePosition::speed() const +{ + return m_info.attribute(QGeoPositionInfo::GroundSpeed); +} + +/*! + \qmlproperty real Position::horizontalAccuracy + + This property holds the horizontal accuracy of the coordinate (in meters). + + \sa horizontalAccuracyValid, coordinate +*/ +void QDeclarativePosition::setHorizontalAccuracy(qreal horizontalAccuracy) +{ + const qreal pHorizontalAccuracy = m_info.attribute(QGeoPositionInfo::HorizontalAccuracy); + + if (equalOrNaN(pHorizontalAccuracy, horizontalAccuracy)) + return; + + bool validChanged = exclusiveNaN(pHorizontalAccuracy, horizontalAccuracy); + + m_info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, horizontalAccuracy); + emit horizontalAccuracyChanged(); + if (validChanged) + emit horizontalAccuracyValidChanged(); +} + +qreal QDeclarativePosition::horizontalAccuracy() const +{ + return m_info.attribute(QGeoPositionInfo::HorizontalAccuracy); +} + +/*! + \qmlproperty bool Position::horizontalAccuracyValid + + This property is true if \l horizontalAccuracy has been set + (to indicate whether that data has been received or not, as every update + does not necessarily contain all data). + + \sa horizontalAccuracy +*/ +bool QDeclarativePosition::isHorizontalAccuracyValid() const +{ + return !qIsNaN(m_info.attribute(QGeoPositionInfo::HorizontalAccuracy)); +} + +/*! + \qmlproperty real Position::verticalAccuracy + + This property holds the vertical accuracy of the coordinate (in meters). + + \sa verticalAccuracyValid, coordinate +*/ +void QDeclarativePosition::setVerticalAccuracy(qreal verticalAccuracy) +{ + const qreal pVerticalAccuracy = m_info.attribute(QGeoPositionInfo::VerticalAccuracy); + + if (equalOrNaN(pVerticalAccuracy, verticalAccuracy)) + return; + + bool validChanged = exclusiveNaN(pVerticalAccuracy, verticalAccuracy); + + m_info.setAttribute(QGeoPositionInfo::VerticalAccuracy, verticalAccuracy); + emit verticalAccuracyChanged(); + if (validChanged) + emit verticalAccuracyValidChanged(); +} + +qreal QDeclarativePosition::verticalAccuracy() const +{ + return m_info.attribute(QGeoPositionInfo::VerticalAccuracy); +} + +/*! + \qmlproperty bool Position::verticalAccuracyValid + + This property is true if \l verticalAccuracy has been set + (to indicate whether that data has been received or not, as every update + does not necessarily contain all data). + + \sa verticalAccuracy +*/ +bool QDeclarativePosition::isVerticalAccuracyValid() const +{ + return !qIsNaN(m_info.attribute(QGeoPositionInfo::VerticalAccuracy)); +} + +/*! + \qmlproperty date Position::timestamp + + This property holds the timestamp when this position + was received. If the property has not been set, it is invalid. + + It is a read-only property. +*/ +QDateTime QDeclarativePosition::timestamp() const +{ + return m_info.timestamp(); +} + +/*! + \qmlproperty bool Position::directionValid + \since Qt Positioning 5.3 + + This property is true if \l direction has been set (to indicate whether that data has been + received or not, as every update does not necessarily contain all data). + + \sa direction +*/ +bool QDeclarativePosition::isDirectionValid() const +{ + return !qIsNaN(m_info.attribute(QGeoPositionInfo::Direction)); +} + +/*! + \qmlproperty double Position::direction + \since Qt Positioning 5.3 + + This property holds the value of the direction of travel in degrees from true north. + + It is a read-only property. + + \sa directionValid +*/ +double QDeclarativePosition::direction() const +{ + return m_info.attribute(QGeoPositionInfo::Direction); +} + +/*! + \qmlproperty bool Position::verticalSpeedValid + \since Qt Positioning 5.3 + + This property is true if \l verticalSpeed has been set (to indicate whether that data has been + received or not, as every update does not necessarily contain all data). + + \sa verticalSpeed +*/ +bool QDeclarativePosition::isVerticalSpeedValid() const +{ + return !qIsNaN(m_info.attribute(QGeoPositionInfo::VerticalSpeed)); +} + +/*! + \qmlproperty double Position::verticalSpeed + \since Qt Positioning 5.3 + + This property holds the value of the vertical speed in meters per second. + + It is a read-only property. + + \sa verticalSpeedValid +*/ +double QDeclarativePosition::verticalSpeed() const +{ + return m_info.attribute(QGeoPositionInfo::VerticalSpeed); +} + +/*! + \qmlproperty bool Position::magneticVariationValid + \since Qt Positioning 5.4 + + This property is true if \l magneticVariation has been set (to indicate whether that data has been + received or not, as every update does not necessarily contain all data). + + \sa magneticVariation +*/ +bool QDeclarativePosition::isMagneticVariationValid() const +{ + return !qIsNaN(m_info.attribute(QGeoPositionInfo::MagneticVariation)); +} + +/*! + \qmlproperty double Position::magneticVariation + \since Qt Positioning 5.4 + + This property holds the angle between the horizontal component of the + magnetic field and true north, in degrees. Also known as magnetic + declination. A positive value indicates a clockwise direction from + true north and a negative value indicates a counter-clockwise direction. + + It is a read-only property. + + \sa magneticVariationValid +*/ +double QDeclarativePosition::magneticVariation() const +{ + return m_info.attribute(QGeoPositionInfo::MagneticVariation); +} + +#include "moc_qdeclarativeposition_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/positioning/qdeclarativeposition_p.h b/src/imports/positioning/qdeclarativeposition_p.h new file mode 100644 index 0000000..208d81c --- /dev/null +++ b/src/imports/positioning/qdeclarativeposition_p.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +***************************************************************************/ + +#ifndef QDECLARATIVEPOSITION_H +#define QDECLARATIVEPOSITION_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativePosition : public QObject +{ + Q_OBJECT + + Q_PROPERTY(bool latitudeValid READ isLatitudeValid NOTIFY latitudeValidChanged) + Q_PROPERTY(bool longitudeValid READ isLongitudeValid NOTIFY longitudeValidChanged) + Q_PROPERTY(bool altitudeValid READ isAltitudeValid NOTIFY altitudeValidChanged) + Q_PROPERTY(QGeoCoordinate coordinate READ coordinate NOTIFY coordinateChanged) + Q_PROPERTY(QDateTime timestamp READ timestamp NOTIFY timestampChanged) + Q_PROPERTY(double speed READ speed NOTIFY speedChanged) + Q_PROPERTY(bool speedValid READ isSpeedValid NOTIFY speedValidChanged) + Q_PROPERTY(qreal horizontalAccuracy READ horizontalAccuracy WRITE setHorizontalAccuracy NOTIFY horizontalAccuracyChanged) + Q_PROPERTY(qreal verticalAccuracy READ verticalAccuracy WRITE setVerticalAccuracy NOTIFY verticalAccuracyChanged) + Q_PROPERTY(bool horizontalAccuracyValid READ isHorizontalAccuracyValid NOTIFY horizontalAccuracyValidChanged) + Q_PROPERTY(bool verticalAccuracyValid READ isVerticalAccuracyValid NOTIFY verticalAccuracyValidChanged) + + Q_PROPERTY(bool directionValid READ isDirectionValid NOTIFY directionValidChanged REVISION 1) + Q_PROPERTY(double direction READ direction NOTIFY directionChanged REVISION 1) + Q_PROPERTY(bool verticalSpeedValid READ isVerticalSpeedValid NOTIFY verticalSpeedValidChanged REVISION 1) + Q_PROPERTY(double verticalSpeed READ verticalSpeed NOTIFY verticalSpeedChanged REVISION 1) + + Q_PROPERTY(double magneticVariation READ magneticVariation NOTIFY magneticVariationChanged REVISION 2) + Q_PROPERTY(bool magneticVariationValid READ isMagneticVariationValid NOTIFY magneticVariationChanged REVISION 2) + +public: + explicit QDeclarativePosition(QObject *parent = 0); + ~QDeclarativePosition(); + + bool isLatitudeValid() const; + bool isLongitudeValid() const; + bool isAltitudeValid() const; + QDateTime timestamp() const; + double speed() const; + bool isSpeedValid() const; + QGeoCoordinate coordinate(); + bool isHorizontalAccuracyValid() const; + qreal horizontalAccuracy() const; + void setHorizontalAccuracy(qreal horizontalAccuracy); + bool isVerticalAccuracyValid() const; + qreal verticalAccuracy() const; + void setVerticalAccuracy(qreal verticalAccuracy); + + bool isDirectionValid() const; + double direction() const; + void setDirection(double direction); + + bool isVerticalSpeedValid() const; + double verticalSpeed() const; + void setVerticalSpeed(double speed); + + bool isMagneticVariationValid() const; + double magneticVariation() const; + + void setPosition(const QGeoPositionInfo &info); + +Q_SIGNALS: + void latitudeValidChanged(); + void longitudeValidChanged(); + void altitudeValidChanged(); + void timestampChanged(); + void speedChanged(); + void speedValidChanged(); + void coordinateChanged(); + void horizontalAccuracyChanged(); + void horizontalAccuracyValidChanged(); + void verticalAccuracyChanged(); + void verticalAccuracyValidChanged(); + + Q_REVISION(1) void directionValidChanged(); + Q_REVISION(1) void directionChanged(); + Q_REVISION(1) void verticalSpeedValidChanged(); + Q_REVISION(1) void verticalSpeedChanged(); + + Q_REVISION(2) void magneticVariationChanged(); + Q_REVISION(2) void magneticVariationValidChanged(); + +private: + QGeoPositionInfo m_info; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativePosition) + +#endif diff --git a/src/imports/positioning/qdeclarativepositionsource.cpp b/src/imports/positioning/qdeclarativepositionsource.cpp new file mode 100644 index 0000000..35ff33b --- /dev/null +++ b/src/imports/positioning/qdeclarativepositionsource.cpp @@ -0,0 +1,765 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativepositionsource_p.h" +#include "qdeclarativeposition_p.h" + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype PositionSource + \instantiates QDeclarativePositionSource + \inqmlmodule QtPositioning + \since 5.2 + + \brief The PositionSource type provides the device's current position. + + The PositionSource type provides information about the user device's + current position. The position is available as a \l{Position} type, which + contains all the standard parameters typically available from GPS and other + similar systems, including longitude, latitude, speed and accuracy details. + + As different position sources are available on different platforms and + devices, these are categorized by their basic type (Satellite, NonSatellite, + and AllPositioningMethods). The available methods for the current platform + can be enumerated in the \l{supportedPositioningMethods} property. + + To indicate which methods are suitable for your application, set the + \l{preferredPositioningMethods} property. If the preferred methods are not + available, the default source of location data for the platform will be + chosen instead. If no default source is available (because none are installed + for the runtime platform, or because it is disabled), the \l{valid} property + will be set to false. + + The \l updateInterval property can then be used to indicate how often your + application wishes to receive position updates. The \l{start}(), + \l{stop}() and \l{update}() methods can be used to control the operation + of the PositionSource, as well as the \l{active} property, which when set + is equivalent to calling \l{start}() or \l{stop}(). + + When the PositionSource is active, position updates can be retrieved + either by simply using the \l{position} property in a binding (as the + value of another item's property), or by providing an implementation of + the \c {onPositionChanged} signal-handler. + + \section2 Example Usage + + The following example shows a simple PositionSource used to receive + updates every second and print the longitude and latitude out to + the console. + + \code + PositionSource { + id: src + updateInterval: 1000 + active: true + + onPositionChanged: { + var coord = src.position.coordinate; + console.log("Coordinate:", coord.longitude, coord.latitude); + } + } + \endcode + + The \l{geoflickr}{GeoFlickr} example application shows how to use + a PositionSource in your application to retrieve local data for users + from a REST web service. + + \sa {QtPositioning::Position}, {QGeoPositionInfoSource} + +*/ + +/*! + \qmlsignal PositionSource::updateTimeout() + + If \l update() was called, this signal is emitted if the current position could not be + retrieved within a certain amount of time. + + If \l start() was called, this signal is emitted if the position engine determines that + it is not able to provide further regular updates. + + \since Qt Positioning 5.5 + + \sa QGeoPositionInfoSource::updateTimeout() +*/ + + +QDeclarativePositionSource::QDeclarativePositionSource() +: m_positionSource(0), m_preferredPositioningMethods(NoPositioningMethods), m_nmeaFile(0), + m_nmeaSocket(0), m_active(false), m_singleUpdate(false), m_updateInterval(0), + m_sourceError(NoError) +{ +} + +QDeclarativePositionSource::~QDeclarativePositionSource() +{ + delete m_nmeaFile; + delete m_nmeaSocket; + delete m_positionSource; +} + + +/*! + \qmlproperty string PositionSource::name + + This property holds the unique internal name for the plugin currently + providing position information. + + Setting the property causes the PositionSource to use a particular positioning provider. If + the PositionSource is active at the time that the name property is changed, it will become + inactive. If the specified positioning provider cannot be loaded the position source will + become invalid. + + Changing the name property may cause the \l {updateInterval}, \l {supportedPositioningMethods} + and \l {preferredPositioningMethods} properties to change as well. +*/ + + +QString QDeclarativePositionSource::name() const +{ + if (m_positionSource) + return m_positionSource->sourceName(); + else + return QString(); +} + +void QDeclarativePositionSource::setName(const QString &newName) +{ + if (m_positionSource && m_positionSource->sourceName() == newName) + return; + + const QString previousName = name(); + int previousUpdateInterval = updateInterval(); + PositioningMethods previousPositioningMethods = supportedPositioningMethods(); + PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods(); + + delete m_positionSource; + if (newName.isEmpty()) + m_positionSource = QGeoPositionInfoSource::createDefaultSource(this); + else + m_positionSource = QGeoPositionInfoSource::createSource(newName, this); + + if (m_positionSource) { + connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)), + this, SLOT(positionUpdateReceived(QGeoPositionInfo))); + connect(m_positionSource, SIGNAL(error(QGeoPositionInfoSource::Error)), + this, SLOT(sourceErrorReceived(QGeoPositionInfoSource::Error))); + connect(m_positionSource, SIGNAL(updateTimeout()), + this, SLOT(updateTimeoutReceived())); + + m_positionSource->setUpdateInterval(m_updateInterval); + m_positionSource->setPreferredPositioningMethods( + static_cast(int(m_preferredPositioningMethods))); + + setPosition(m_positionSource->lastKnownPosition()); + } + + if (previousUpdateInterval != updateInterval()) + emit updateIntervalChanged(); + + if (previousPreferredPositioningMethods != preferredPositioningMethods()) + emit preferredPositioningMethodsChanged(); + + if (previousPositioningMethods != supportedPositioningMethods()) + emit supportedPositioningMethodsChanged(); + + emit validityChanged(); + + if (m_active) { + m_active = false; + emit activeChanged(); + } + + if (previousName != name()) + emit nameChanged(); +} + +/*! + \qmlproperty bool PositionSource::valid + + This property is true if the PositionSource object has acquired a valid + backend plugin to provide data. If false, other methods on the PositionSource + will have no effect. + + Applications should check this property to determine whether positioning is + available and enabled on the runtime platform, and react accordingly. +*/ +bool QDeclarativePositionSource::isValid() const +{ + return (m_positionSource != 0); +} + +/*! + \internal +*/ +void QDeclarativePositionSource::setNmeaSource(const QUrl &nmeaSource) +{ + if (nmeaSource.scheme() == QLatin1String("socket")) { + if (m_nmeaSocket + && nmeaSource.host() == m_nmeaSocket->peerName() + && nmeaSource.port() == m_nmeaSocket->peerPort()) { + return; + } + + delete m_nmeaSocket; + m_nmeaSocket = new QTcpSocket(); + + connect(m_nmeaSocket, static_cast (&QAbstractSocket::error), + this, &QDeclarativePositionSource::socketError); + connect(m_nmeaSocket, &QTcpSocket::connected, + this, &QDeclarativePositionSource::socketConnected); + + m_nmeaSocket->connectToHost(nmeaSource.host(), nmeaSource.port(), QTcpSocket::ReadOnly); + } else { + // Strip the filename. This is clumsy but the file may be prefixed in several + // ways: "file:///", "qrc:///", "/", "" in platform dependent manner. + QString localFileName = nmeaSource.toString(); + if (!QFile::exists(localFileName)) { + if (localFileName.startsWith("qrc:///")) { + localFileName.remove(0, 7); + } else if (localFileName.startsWith("file:///")) { + localFileName.remove(0, 7); + } else if (localFileName.startsWith("qrc:/")) { + localFileName.remove(0, 5); + } + if (!QFile::exists(localFileName) && localFileName.startsWith('/')) { + localFileName.remove(0,1); + } + } + if (m_nmeaFileName == localFileName) + return; + m_nmeaFileName = localFileName; + + PositioningMethods previousPositioningMethods = supportedPositioningMethods(); + + // The current position source needs to be deleted + // because QNmeaPositionInfoSource can be bound only to a one file. + delete m_nmeaSocket; + m_nmeaSocket = 0; + delete m_positionSource; + m_positionSource = 0; + setPosition(QGeoPositionInfo()); + // Create the NMEA source based on the given data. QML has automatically set QUrl + // type to point to correct path. If the file is not found, check if the file actually + // was an embedded resource file. + delete m_nmeaFile; + m_nmeaFile = new QFile(localFileName); + if (!m_nmeaFile->exists()) { + localFileName.prepend(":"); + m_nmeaFile->setFileName(localFileName); + } + if (m_nmeaFile->exists()) { +#ifdef QDECLARATIVE_POSITION_DEBUG + qDebug() << "QDeclarativePositionSource NMEA File was found: " << localFileName; +#endif + m_positionSource = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::SimulationMode); + (qobject_cast(m_positionSource))->setDevice(m_nmeaFile); + connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)), + this, SLOT(positionUpdateReceived(QGeoPositionInfo))); + connect(m_positionSource, SIGNAL(error(QGeoPositionInfoSource::Error)), + this, SLOT(sourceErrorReceived(QGeoPositionInfoSource::Error))); + connect(m_positionSource, SIGNAL(updateTimeout()), + this, SLOT(updateTimeoutReceived())); + + setPosition(m_positionSource->lastKnownPosition()); + if (m_active && !m_singleUpdate) { + // Keep on updating even though source changed + QTimer::singleShot(0, this, SLOT(start())); + } + } else { + qmlInfo(this) << QStringLiteral("Nmea file not found") << localFileName; +#ifdef QDECLARATIVE_POSITION_DEBUG + qDebug() << "QDeclarativePositionSource NMEA File was not found: " << localFileName; +#endif + if (m_active) { + m_active = false; + m_singleUpdate = false; + emit activeChanged(); + } + } + + if (previousPositioningMethods != supportedPositioningMethods()) + emit supportedPositioningMethodsChanged(); + } + + m_nmeaSource = nmeaSource; + emit nmeaSourceChanged(); +} + +/*! + \internal +*/ +void QDeclarativePositionSource::socketConnected() +{ +#ifdef QDECLARATIVE_POSITION_DEBUG + qDebug() << "Socket connected: " << m_nmeaSocket->peerName(); +#endif + PositioningMethods previousPositioningMethods = supportedPositioningMethods(); + + // The current position source needs to be deleted + // because QNmeaPositionInfoSource can be bound only to a one file. + delete m_nmeaFile; + m_nmeaFile = 0; + delete m_positionSource; + + m_positionSource = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::RealTimeMode); + (qobject_cast(m_positionSource))->setDevice(m_nmeaSocket); + + connect(m_positionSource, &QNmeaPositionInfoSource::positionUpdated, + this, &QDeclarativePositionSource::positionUpdateReceived); + connect(m_positionSource, SIGNAL(error(QGeoPositionInfoSource::Error)), + this, SLOT(sourceErrorReceived(QGeoPositionInfoSource::Error))); + connect(m_positionSource, SIGNAL(updateTimeout()), + this, SLOT(updateTimeoutReceived())); + + setPosition(m_positionSource->lastKnownPosition()); + + if (m_active && !m_singleUpdate) { + // Keep on updating even though source changed + QTimer::singleShot(0, this, SLOT(start())); + } + + if (previousPositioningMethods != supportedPositioningMethods()) + emit supportedPositioningMethodsChanged(); +} + +/*! + \internal +*/ +void QDeclarativePositionSource::socketError(QAbstractSocket::SocketError error) +{ + delete m_nmeaSocket; + m_nmeaSocket = 0; + + switch (error) { + case QAbstractSocket::UnknownSocketError: + m_sourceError = QDeclarativePositionSource::UnknownSourceError; + break; + case QAbstractSocket::SocketAccessError: + m_sourceError = QDeclarativePositionSource::AccessError; + break; + case QAbstractSocket::RemoteHostClosedError: + m_sourceError = QDeclarativePositionSource::ClosedError; + break; + default: + qWarning() << "Connection failed! QAbstractSocket::SocketError" << error; + m_sourceError = QDeclarativePositionSource::SocketError; + break; + } + + emit sourceErrorChanged(); +} + + +void QDeclarativePositionSource::updateTimeoutReceived() +{ + if (!m_active) + return; + + if (m_singleUpdate) { + m_singleUpdate = false; + + // only singleUpdate based timeouts change activity + // continuous updates may resume again (see QGeoPositionInfoSource::startUpdates()) + m_active = false; + emit activeChanged(); + } + + emit updateTimeout(); +} + +void QDeclarativePositionSource::setPosition(const QGeoPositionInfo &pi) +{ + m_position.setPosition(pi); + emit positionChanged(); +} + +/*! + \internal +*/ +void QDeclarativePositionSource::setUpdateInterval(int updateInterval) +{ + if (m_positionSource) { + int previousUpdateInterval = m_positionSource->updateInterval(); + + m_updateInterval = updateInterval; + + if (previousUpdateInterval != updateInterval) { + m_positionSource->setUpdateInterval(updateInterval); + if (previousUpdateInterval != m_positionSource->updateInterval()) + emit updateIntervalChanged(); + } + } else { + if (m_updateInterval != updateInterval) { + m_updateInterval = updateInterval; + emit updateIntervalChanged(); + } + } +} + +/*! + \qmlproperty url PositionSource::nmeaSource + + This property holds the source for NMEA (National Marine Electronics Association) + position-specification data (file). One purpose of this property is to be of + development convenience. + + Setting this property will override any other position source. Currently only + files local to the .qml -file are supported. The NMEA source is created in simulation mode, + meaning that the data and time information in the NMEA source data is used to provide + positional updates at the rate at which the data was originally recorded. + + If nmeaSource has been set for a PositionSource object, there is no way to revert + back to non-file sources. +*/ + +QUrl QDeclarativePositionSource::nmeaSource() const +{ + return m_nmeaSource; +} + +/*! + \qmlproperty int PositionSource::updateInterval + + This property holds the desired interval between updates (milliseconds). + + \sa {QGeoPositionInfoSource::updateInterval()} +*/ + +int QDeclarativePositionSource::updateInterval() const +{ + if (!m_positionSource) + return m_updateInterval; + + return m_positionSource->updateInterval(); +} + +/*! + \qmlproperty enumeration PositionSource::supportedPositioningMethods + + This property holds the supported positioning methods of the + current source. + + \list + \li PositionSource.NoPositioningMethods - No positioning methods supported (no source). + \li PositionSource.SatellitePositioningMethods - Satellite-based positioning methods such as GPS are supported. + \li PositionSource.NonSatellitePositioningMethods - Non-satellite-based methods are supported. + \li PositionSource.AllPositioningMethods - Both satellite-based and non-satellite positioning methods are supported. + \endlist + +*/ + +QDeclarativePositionSource::PositioningMethods QDeclarativePositionSource::supportedPositioningMethods() const +{ + if (m_positionSource) { + return static_cast( + int(m_positionSource->supportedPositioningMethods())); + } + return QDeclarativePositionSource::NoPositioningMethods; +} + +/*! + \qmlproperty enumeration PositionSource::preferredPositioningMethods + + This property holds the preferred positioning methods of the + current source. + + \list + \li PositionSource.NoPositioningMethods - No positioning method is preferred. + \li PositionSource.SatellitePositioningMethods - Satellite-based positioning methods such as GPS should be preferred. + \li PositionSource.NonSatellitePositioningMethods - Non-satellite-based methods should be preferred. + \li PositionSource.AllPositioningMethods - Any positioning methods are acceptable. + \endlist + +*/ + +void QDeclarativePositionSource::setPreferredPositioningMethods(PositioningMethods methods) +{ + if (m_positionSource) { + PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods(); + + m_preferredPositioningMethods = methods; + + if (previousPreferredPositioningMethods != methods) { + m_positionSource->setPreferredPositioningMethods( + static_cast(int(methods))); + if (previousPreferredPositioningMethods != m_positionSource->preferredPositioningMethods()) + emit preferredPositioningMethodsChanged(); + } + } else { + if (m_preferredPositioningMethods != methods) { + m_preferredPositioningMethods = methods; + emit preferredPositioningMethodsChanged(); + } + } +} + +QDeclarativePositionSource::PositioningMethods QDeclarativePositionSource::preferredPositioningMethods() const +{ + if (m_positionSource) { + return static_cast( + int(m_positionSource->preferredPositioningMethods())); + } + return m_preferredPositioningMethods; +} + +/*! + \qmlmethod PositionSource::start() + + Requests updates from the location source. + Uses \l updateInterval if set, default interval otherwise. + If there is no source available, this method has no effect. + + \sa stop, update, active +*/ + +void QDeclarativePositionSource::start() +{ + if (!m_positionSource) + return; + + m_positionSource->startUpdates(); + if (!m_active) { + m_active = true; + emit activeChanged(); + } +} + +/*! + \qmlmethod PositionSource::update() + + A convenience method to request single update from the location source. + If there is no source available, this method has no effect. + + If the position source is not active, it will be activated for as + long as it takes to receive an update, or until the request times + out. The request timeout period is source-specific. + + \sa start, stop, active +*/ + +void QDeclarativePositionSource::update() +{ + if (m_positionSource) { + if (!m_active) { + m_active = true; + m_singleUpdate = true; + emit activeChanged(); + } + // Use default timeout value. Set active before calling the + // update request because on some platforms there may + // be results immediately. + m_positionSource->requestUpdate(); + } +} + +/*! + \qmlmethod PositionSource::stop() + + Stops updates from the location source. + If there is no source available or it is not active, + this method has no effect. + + \sa start, update, active +*/ + +void QDeclarativePositionSource::stop() +{ + if (m_positionSource) { + m_positionSource->stopUpdates(); + if (m_active) { + m_active = false; + emit activeChanged(); + } + } +} + +/*! + \qmlproperty bool PositionSource::active + + This property indicates whether the position source is active. + Setting this property to false equals calling \l stop, and + setting this property true equals calling \l start. + + \sa start, stop, update +*/ +void QDeclarativePositionSource::setActive(bool active) +{ + if (active == m_active) + return; + + if (active) + QTimer::singleShot(0, this, SLOT(start())); // delay ensures all properties have been set + else + stop(); +} + +bool QDeclarativePositionSource::isActive() const +{ + return m_active; +} + +/*! + \qmlproperty Position PositionSource::position + + This property holds the last known positional data. + It is a read-only property. + + The Position type has different positional member variables, + whose validity can be checked with appropriate validity functions + (for example sometimes an update does not have speed or altitude data). + + However, whenever a \c {positionChanged} signal has been received, at least + position::coordinate::latitude, position::coordinate::longitude, and position::timestamp can + be assumed to be valid. + + \sa start, stop, update +*/ + +QDeclarativePosition *QDeclarativePositionSource::position() +{ + return &m_position; +} + +void QDeclarativePositionSource::positionUpdateReceived(const QGeoPositionInfo &update) +{ + setPosition(update); + + if (m_singleUpdate && m_active) { + m_active = false; + m_singleUpdate = false; + emit activeChanged(); + } +} + + +/*! + \qmlproperty enumeration PositionSource::sourceError + + This property holds the error which last occurred with the PositionSource. + + \list + \li PositionSource.AccessError - The connection setup to the remote positioning backend failed because the + application lacked the required privileges. + \li PositionSource.ClosedError - The positioning backend closed the connection, which happens for example in case + the user is switching location services to off. As soon as the location service is re-enabled + regular updates will resume. + \li PositionSource.NoError - No error has occurred. + \li PositionSource.UnknownSourceError - An unidentified error occurred. + \li PositionSource.SocketError - An error occurred while connecting to an nmea source using a socket. + \endlist + +*/ + +QDeclarativePositionSource::SourceError QDeclarativePositionSource::sourceError() const +{ + return m_sourceError; +} + +void QDeclarativePositionSource::componentComplete() +{ + if (!m_positionSource) { + int previousUpdateInterval = updateInterval(); + PositioningMethods previousPositioningMethods = supportedPositioningMethods(); + PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods(); + + m_positionSource = QGeoPositionInfoSource::createDefaultSource(this); + if (m_positionSource) { + connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)), + this, SLOT(positionUpdateReceived(QGeoPositionInfo))); + connect(m_positionSource, SIGNAL(error(QGeoPositionInfoSource::Error)), + this, SLOT(sourceErrorReceived(QGeoPositionInfoSource::Error))); + connect(m_positionSource, SIGNAL(updateTimeout()), + this, SLOT(updateTimeoutReceived())); + + m_positionSource->setUpdateInterval(m_updateInterval); + m_positionSource->setPreferredPositioningMethods( + static_cast(int(m_preferredPositioningMethods))); + + setPosition(m_positionSource->lastKnownPosition()); + } + + if (previousUpdateInterval != updateInterval()) + emit updateIntervalChanged(); + + if (previousPreferredPositioningMethods != preferredPositioningMethods()) + emit preferredPositioningMethodsChanged(); + + if (previousPositioningMethods != supportedPositioningMethods()) + emit supportedPositioningMethodsChanged(); + + emit validityChanged(); + + if (m_active) { + m_active = false; + emit activeChanged(); + } + + emit nameChanged(); + } +} + +/*! + \internal +*/ +void QDeclarativePositionSource::sourceErrorReceived(const QGeoPositionInfoSource::Error error) +{ + if (error == QGeoPositionInfoSource::AccessError) + m_sourceError = QDeclarativePositionSource::AccessError; + else if (error == QGeoPositionInfoSource::ClosedError) + m_sourceError = QDeclarativePositionSource::ClosedError; + else if (error == QGeoPositionInfoSource::NoError) + return; //nothing to do + else + m_sourceError = QDeclarativePositionSource::UnknownSourceError; + + emit sourceErrorChanged(); +} + +#include "moc_qdeclarativepositionsource_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/positioning/qdeclarativepositionsource_p.h b/src/imports/positioning/qdeclarativepositionsource_p.h new file mode 100644 index 0000000..f785234 --- /dev/null +++ b/src/imports/positioning/qdeclarativepositionsource_p.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +***************************************************************************/ + +#ifndef QDECLARATIVEPOSITIONSOURCE_H +#define QDECLARATIVEPOSITIONSOURCE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativeposition_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QFile; +class QTcpSocket; + +class QDeclarativePositionSource : public QObject, public QQmlParserStatus +{ + Q_OBJECT + + Q_PROPERTY(QDeclarativePosition *position READ position NOTIFY positionChanged) + Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) + Q_PROPERTY(bool valid READ isValid NOTIFY validityChanged) + Q_PROPERTY(QUrl nmeaSource READ nmeaSource WRITE setNmeaSource NOTIFY nmeaSourceChanged) + Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval NOTIFY updateIntervalChanged) + Q_PROPERTY(PositioningMethods supportedPositioningMethods READ supportedPositioningMethods NOTIFY supportedPositioningMethodsChanged) + Q_PROPERTY(PositioningMethods preferredPositioningMethods READ preferredPositioningMethods WRITE setPreferredPositioningMethods NOTIFY preferredPositioningMethodsChanged) + Q_PROPERTY(SourceError sourceError READ sourceError NOTIFY sourceErrorChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_ENUMS(PositioningMethod) + + Q_INTERFACES(QQmlParserStatus) + +public: + enum PositioningMethod { + NoPositioningMethods = QGeoPositionInfoSource::NoPositioningMethods, + SatellitePositioningMethods = QGeoPositionInfoSource::SatellitePositioningMethods, + NonSatellitePositioningMethods = QGeoPositionInfoSource::NonSatellitePositioningMethods, + AllPositioningMethods = QGeoPositionInfoSource::AllPositioningMethods + }; + + Q_DECLARE_FLAGS(PositioningMethods, PositioningMethod) + Q_FLAGS(PositioningMethods) + + enum SourceError { + AccessError = QGeoPositionInfoSource::AccessError, + ClosedError = QGeoPositionInfoSource::ClosedError, + UnknownSourceError = QGeoPositionInfoSource::UnknownSourceError, + NoError = QGeoPositionInfoSource::NoError, + + //Leave a gap for future error enum values in QGeoPositionInfoSource::Error + SocketError = 100 + }; + Q_ENUMS(SourceError) + + QDeclarativePositionSource(); + ~QDeclarativePositionSource(); + void setNmeaSource(const QUrl &nmeaSource); + void setUpdateInterval(int updateInterval); + void setActive(bool active); + void setPreferredPositioningMethods(PositioningMethods methods); + + QString name() const; + void setName(const QString &name); + + QUrl nmeaSource() const; + int updateInterval() const; + bool isActive() const; + bool isValid() const; + QDeclarativePosition *position(); + PositioningMethods supportedPositioningMethods() const; + PositioningMethods preferredPositioningMethods() const; + SourceError sourceError() const; + + // Virtuals from QQmlParserStatus + void classBegin() { } + void componentComplete(); + +public Q_SLOTS: + void update(); // TODO Qt 6 change to void update(int) + void start(); + void stop(); + +Q_SIGNALS: + void positionChanged(); + void activeChanged(); + void nmeaSourceChanged(); + void updateIntervalChanged(); + void supportedPositioningMethodsChanged(); + void preferredPositioningMethodsChanged(); + void sourceErrorChanged(); + void nameChanged(); + void validityChanged(); + void updateTimeout(); + +private Q_SLOTS: + void positionUpdateReceived(const QGeoPositionInfo &update); + void sourceErrorReceived(const QGeoPositionInfoSource::Error error); + void socketConnected(); + void socketError(QAbstractSocket::SocketError error); + void updateTimeoutReceived(); + +private: + void setPosition(const QGeoPositionInfo &pi); + + QGeoPositionInfoSource *m_positionSource; + QDeclarativePosition m_position; + PositioningMethods m_preferredPositioningMethods; + QFile *m_nmeaFile; + QTcpSocket *m_nmeaSocket; + QString m_nmeaFileName; + QUrl m_nmeaSource; + bool m_active; + bool m_singleUpdate; + int m_updateInterval; + SourceError m_sourceError; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativePositionSource) + +#endif diff --git a/src/imports/positioning/qmldir b/src/imports/positioning/qmldir new file mode 100644 index 0000000..fc4ebf8 --- /dev/null +++ b/src/imports/positioning/qmldir @@ -0,0 +1,4 @@ +module QtPositioning +plugin declarative_positioning +classname QtPositioningDeclarativeModule +typeinfo plugins.qmltypes diff --git a/src/imports/positioning/qquickgeocoordinateanimation.cpp b/src/imports/positioning/qquickgeocoordinateanimation.cpp new file mode 100644 index 0000000..c386074 --- /dev/null +++ b/src/imports/positioning/qquickgeocoordinateanimation.cpp @@ -0,0 +1,297 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickgeocoordinateanimation_p.h" +#include "qquickgeocoordinateanimation_p_p.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype CoordinateAnimation + \instantiates QQuickGeoCoordinateAnimation + \inherits PropertyAnimation + \inqmlmodule QtPositioning + \since 5.3 + + \brief A PropertyAnimation for geo coordinate properties. + + A specialized \l{PropertyAnimation} that defines an animation + between two \l{coordinate}{coordinates}. + + By default, a \l{latitude} of the \l{coordinate} is animated in the direction of shortest + (geodesic) distance between those coordinates. Since CoordinateAnimation uses Mercator + map projection, the \l{latitude} animation is always between -90 and 90 degrees. + The \l{longitude} animation path is not limited and can go over 180 degrees + in both west and east directions. + + The \l{direction} property can be set to specify the direction in which the \l{longitude} + animation should occur. + + \sa {Animation and Transitions in Qt Quick} +*/ + +QVariant q_coordinateInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) +{ + if (from == to) { + if (progress < 0.5) { + return QVariant::fromValue(from); + } else { + return QVariant::fromValue(to); + } + } + + QGeoCoordinate result = QGeoProjection::coordinateInterpolation(from, to, progress); + + return QVariant::fromValue(result); +} + +QVariant q_coordinateShortestInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) +{ + const QGeoMercatorCoordinatePrivate* fromMercator = + static_cast(QGeoCoordinatePrivate::get(&from)); + const QGeoMercatorCoordinatePrivate* toMercator = + static_cast(QGeoCoordinatePrivate::get(&to)); + + double toX = toMercator->m_mercatorX; + double toY = toMercator->m_mercatorY; + double fromX = fromMercator->m_mercatorX; + double fromY = fromMercator->m_mercatorY; + double x; + if (0.5 < qAbs(toX - fromX)) { + // handle dateline crossing + double ex = toX; + double sx = fromX; + if (ex < sx) + sx -= 1.0; + else if (sx < ex) + ex -= 1.0; + + x = fromX + (toX - fromX) * progress; + + if (x < 0.0) + x += 1.0; + + } else { + x = fromX + (toX - fromX) * progress; + } + + double y = fromY + (toY - fromY) * progress; + + QGeoCoordinate result = QGeoProjection::mercatorToCoord(QDoubleVector2D(x, y)); + result.setAltitude(from.altitude() + (to.altitude() - from.altitude()) * progress); + return QVariant::fromValue(result); +} + +QVariant q_coordinateWestInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) +{ + const QGeoMercatorCoordinatePrivate* fromMercator = + static_cast(QGeoCoordinatePrivate::get(&from)); + const QGeoMercatorCoordinatePrivate* toMercator = + static_cast(QGeoCoordinatePrivate::get(&to)); + + double toX = toMercator->m_mercatorX; + double toY = toMercator->m_mercatorY; + double fromX = fromMercator->m_mercatorX; + double fromY = fromMercator->m_mercatorY; + double diff = toX - fromX; + + while (diff < 0.0) { + toX += 1.0; + diff += 1.0; + } + + double x = fromX + (toX - fromX) * progress; + double y = fromY + (toY - fromY) * progress; + + while (x > 1.0) + x -= 1.0; + + QGeoCoordinate result = QGeoProjection::mercatorToCoord(QDoubleVector2D(x, y)); + result.setAltitude(from.altitude() + (to.altitude() - from.altitude()) * progress); + + return QVariant::fromValue(result); +} + +QVariant q_coordinateEastInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) +{ + const QGeoMercatorCoordinatePrivate* fromMercator = + static_cast(QGeoCoordinatePrivate::get(&from)); + const QGeoMercatorCoordinatePrivate* toMercator = + static_cast(QGeoCoordinatePrivate::get(&to)); + + double toX = toMercator->m_mercatorX; + double toY = toMercator->m_mercatorY; + double fromX = fromMercator->m_mercatorX; + double fromY = fromMercator->m_mercatorY; + double diff = toX - fromX; + + while (diff > 0.0) { + toX -= 1.0; + diff -= 1.0; + } + + double x = fromX + (toX - fromX) * progress; + double y = fromY + (toY - fromY) * progress; + + while (x < 0.0) + x += 1.0; + + QGeoCoordinate result = QGeoProjection::mercatorToCoord(QDoubleVector2D(x, y)); + result.setAltitude(from.altitude() + (to.altitude() - from.altitude()) * progress); + + return QVariant::fromValue(result); +} + +QQuickGeoCoordinateAnimation::QQuickGeoCoordinateAnimation(QObject *parent) + : QQuickPropertyAnimation(*(new QQuickGeoCoordinateAnimationPrivate), parent) + +{ + Q_D(QQuickGeoCoordinateAnimation); + d->interpolatorType = qMetaTypeId(); + d->defaultToInterpolatorType = true; + d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); +} + +QQuickGeoCoordinateAnimation::~QQuickGeoCoordinateAnimation() +{ +} + +/*! + \qmlproperty coordinate CoordinateAnimation::from + This property holds the coordinate where the animation should begin. +*/ +QGeoCoordinate QQuickGeoCoordinateAnimation::from() const +{ + Q_D(const QQuickGeoCoordinateAnimation); + return d->from.value(); +} + +void QQuickGeoCoordinateAnimation::setFrom(const QGeoCoordinate &f) +{ + QGeoMercatorCoordinatePrivate *mercator = new QGeoMercatorCoordinatePrivate(); + QDoubleVector2D fromVector = QGeoProjection::coordToMercator(f); + mercator->lat = f.latitude(); + mercator->lng = f.longitude(); + mercator->alt = f.altitude(); + mercator->m_mercatorX = fromVector.x(); + mercator->m_mercatorY = fromVector.y(); + QGeoCoordinate from(*mercator); + QQuickPropertyAnimation::setFrom(QVariant::fromValue(from)); +} + +/*! + \qmlproperty coordinate CoordinateAnimation::to + This property holds the coordinate where the animation should end. +*/ +QGeoCoordinate QQuickGeoCoordinateAnimation::to() const +{ + Q_D(const QQuickGeoCoordinateAnimation); + return d->to.value(); +} + +void QQuickGeoCoordinateAnimation::setTo(const QGeoCoordinate &t) +{ + QGeoMercatorCoordinatePrivate *mercator = new QGeoMercatorCoordinatePrivate(); + QDoubleVector2D toVector = QGeoProjection::coordToMercator(t); + mercator->lat = t.latitude(); + mercator->lng = t.longitude(); + mercator->alt = t.altitude(); + mercator->m_mercatorX = toVector.x(); + mercator->m_mercatorY = toVector.y(); + QGeoCoordinate to(*mercator); + QQuickPropertyAnimation::setTo(QVariant::fromValue(to)); +} + +/*! + \qmlproperty enumeration CoordinateAnimation::direction + This property holds the direction of the \l{longitude} animation of the \l{coordinate}. + + Possible values are: + + \list + \li CoordinateAnimation.Shortest (default) - the longitude animation goes in the direction + that produces the shortest animation path. + \li CoordinateAnimation.West - the longitude animation always goes into western direction + and may cross the date line. + \li CoordinateAnimation.East - the longitude animation always goes into eastern direction + and may cross the date line. + \endlist + \since 5.5 +*/ + + +QQuickGeoCoordinateAnimation::Direction QQuickGeoCoordinateAnimation::direction() const +{ + Q_D(const QQuickGeoCoordinateAnimation); + return d->m_direction; +} + +void QQuickGeoCoordinateAnimation::setDirection(QQuickGeoCoordinateAnimation::Direction direction) +{ + Q_D( QQuickGeoCoordinateAnimation); + if (d->m_direction == direction) + return; + + d->m_direction = direction; + switch (direction) { + case West: + d->interpolator = reinterpret_cast(&q_coordinateWestInterpolator); + break; + case East: + d->interpolator = reinterpret_cast(&q_coordinateEastInterpolator); + break; + case Shortest: + default: + d->interpolator = reinterpret_cast(&q_coordinateShortestInterpolator); + break; + } + emit directionChanged(); + +} + +QQuickGeoCoordinateAnimationPrivate::QQuickGeoCoordinateAnimationPrivate(): + m_direction(QQuickGeoCoordinateAnimation::Shortest) +{ +} + +QT_END_NAMESPACE diff --git a/src/imports/positioning/qquickgeocoordinateanimation_p.h b/src/imports/positioning/qquickgeocoordinateanimation_p.h new file mode 100644 index 0000000..95f8dc0 --- /dev/null +++ b/src/imports/positioning/qquickgeocoordinateanimation_p.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKGEOCOORDINATEANIMATION_P_H +#define QQUICKGEOCOORDINATEANIMATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QQuickGeoCoordinateAnimationPrivate; + +class QQuickGeoCoordinateAnimation : public QQuickPropertyAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickGeoCoordinateAnimation) + Q_PROPERTY(QGeoCoordinate from READ from WRITE setFrom) + Q_PROPERTY(QGeoCoordinate to READ to WRITE setTo) + Q_PROPERTY(Direction direction READ direction WRITE setDirection NOTIFY directionChanged) + +public: + enum Direction { + Shortest, + West, + East + }; + Q_ENUM(Direction) + + QQuickGeoCoordinateAnimation(QObject *parent=0); + ~QQuickGeoCoordinateAnimation(); + + QGeoCoordinate from() const; + void setFrom(const QGeoCoordinate &); + + QGeoCoordinate to() const; + void setTo(const QGeoCoordinate &); + + Direction direction() const; + void setDirection(Direction direction); + +Q_SIGNALS: + void directionChanged(); +}; + +QVariant q_coordinateInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress); + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickGeoCoordinateAnimation) + +#endif // QQUICKCOORDINATEANIMATION_P_H diff --git a/src/imports/positioning/qquickgeocoordinateanimation_p_p.h b/src/imports/positioning/qquickgeocoordinateanimation_p_p.h new file mode 100644 index 0000000..946a38c --- /dev/null +++ b/src/imports/positioning/qquickgeocoordinateanimation_p_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKGEOCOORDINATEANIMATION_P_P_H +#define QQUICKGEOCOORDINATEANIMATION_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickgeocoordinateanimation_p.h" +#include + +QT_BEGIN_NAMESPACE + +class QQuickGeoCoordinateAnimationPrivate : public QQuickPropertyAnimationPrivate +{ + Q_DECLARE_PUBLIC(QQuickGeoCoordinateAnimation) +public: + QQuickGeoCoordinateAnimationPrivate(); + QQuickGeoCoordinateAnimation::Direction m_direction; +}; + +QT_END_NAMESPACE + +#endif // QQUICKGEOCOORDINATEANIMATION_P_P_H diff --git a/src/location/doc/images/api-mapcircle.png b/src/location/doc/images/api-mapcircle.png new file mode 100644 index 0000000..ab31eef Binary files /dev/null and b/src/location/doc/images/api-mapcircle.png differ diff --git a/src/location/doc/images/api-mappolygon.png b/src/location/doc/images/api-mappolygon.png new file mode 100644 index 0000000..46b5fc1 Binary files /dev/null and b/src/location/doc/images/api-mappolygon.png differ diff --git a/src/location/doc/images/api-mappolyline.png b/src/location/doc/images/api-mappolyline.png new file mode 100644 index 0000000..682812c Binary files /dev/null and b/src/location/doc/images/api-mappolyline.png differ diff --git a/src/location/doc/images/api-mapquickitem-anchor.png b/src/location/doc/images/api-mapquickitem-anchor.png new file mode 100644 index 0000000..40581db Binary files /dev/null and b/src/location/doc/images/api-mapquickitem-anchor.png differ diff --git a/src/location/doc/images/api-mapquickitem.png b/src/location/doc/images/api-mapquickitem.png new file mode 100644 index 0000000..3abde6b Binary files /dev/null and b/src/location/doc/images/api-mapquickitem.png differ diff --git a/src/location/doc/images/api-maprectangle.png b/src/location/doc/images/api-maprectangle.png new file mode 100644 index 0000000..957503e Binary files /dev/null and b/src/location/doc/images/api-maprectangle.png differ diff --git a/src/location/doc/images/mapsdemo-finished.png b/src/location/doc/images/mapsdemo-finished.png new file mode 100644 index 0000000..cadee4a Binary files /dev/null and b/src/location/doc/images/mapsdemo-finished.png differ diff --git a/src/location/doc/images/mapsdemo-routing.png b/src/location/doc/images/mapsdemo-routing.png new file mode 100644 index 0000000..3c2d0ca Binary files /dev/null and b/src/location/doc/images/mapsdemo-routing.png differ diff --git a/src/location/doc/images/mapsdemo-searchgui.png b/src/location/doc/images/mapsdemo-searchgui.png new file mode 100644 index 0000000..a307e68 Binary files /dev/null and b/src/location/doc/images/mapsdemo-searchgui.png differ diff --git a/src/location/doc/images/mapsdemo-verybasic.png b/src/location/doc/images/mapsdemo-verybasic.png new file mode 100644 index 0000000..9d92a74 Binary files /dev/null and b/src/location/doc/images/mapsdemo-verybasic.png differ diff --git a/src/location/doc/qtlocation.qdocconf b/src/location/doc/qtlocation.qdocconf new file mode 100644 index 0000000..695860a --- /dev/null +++ b/src/location/doc/qtlocation.qdocconf @@ -0,0 +1,54 @@ +include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) + +project = QtLocation +description = Qt Location Reference Documentation +version = $QT_VERSION + + + +qhp.projects = QtLocation + +qhp.QtLocation.file = qtlocation.qhp +qhp.QtLocation.namespace = org.qt-project.qtlocation.$QT_VERSION_TAG +qhp.QtLocation.virtualFolder = qtlocation +qhp.QtLocation.indexTitle = Qt Location +qhp.QtLocation.indexRoot = + +qhp.QtLocation.filterAttributes = qtlocation $QT_VERSION qtrefdoc +qhp.QtLocation.customFilters.Qt.name = QtLocation $QT_VERSION +qhp.QtLocation.customFilters.Qt.filterAttributes = qtLocation $QT_VERSION +qhp.QtLocation.subprojects = classes qml examples +qhp.QtLocation.subprojects.classes.title = C++ Classes +qhp.QtLocation.subprojects.classes.indexTitle = Qt Location C++ Classes +qhp.QtLocation.subprojects.classes.selectors = class fake:headerfile +qhp.QtLocation.subprojects.classes.sortPages = true +qhp.QtLocation.subprojects.qml.title = QML Types +qhp.QtLocation.subprojects.qml.indexTitle = Qt Location QML Types +qhp.QtLocation.subprojects.qml.selectors = qmlclass +qhp.QtLocation.subprojects.qml.sortPages = true +qhp.QtLocation.subprojects.examples.title = Qt Location Examples +qhp.QtLocation.subprojects.examples.indexTitle = Qt Location Examples +qhp.QtLocation.subprojects.examples.selectors = fake:example + +tagfile = ../../../doc/qtlocation/qtlocation.tags + +depends += qtcore qtdoc qtquick qtqml qtnetwork qtpositioning qtquickcontrols + +headerdirs += .. \ + ../../imports/location + +sourcedirs += .. \ + ../../imports/location \ + ../../plugins/geoservices/nokia + +examplesinstallpath = location + +exampledirs += ../../../examples/location \ + snippets/ + + +imagedirs += images + +navigation.landingpage = "Qt Location" +navigation.cppclassespage = "Qt Location C++ Classes" +navigation.qmltypespage = "Qt Location QML Types" diff --git a/src/location/doc/snippets/cpp/cpp.pro b/src/location/doc/snippets/cpp/cpp.pro new file mode 100644 index 0000000..b961b98 --- /dev/null +++ b/src/location/doc/snippets/cpp/cpp.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +TARGET = cppsnippet +QT = core location + +SOURCES += \ + main.cpp \ + cppqml.cpp + diff --git a/src/location/doc/snippets/cpp/cppqml.cpp b/src/location/doc/snippets/cpp/cppqml.cpp new file mode 100644 index 0000000..48a5007 --- /dev/null +++ b/src/location/doc/snippets/cpp/cppqml.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void cppQmlInterface(QObject *qmlObject) +{ + //! [Category get] + QPlaceCategory category = qmlObject->property("category").value(); + //! [Category get] + + //! [Category set] + qmlObject->setProperty("category", QVariant::fromValue(category)); + //! [Category set] + + //! [ContactDetail get] + QPlaceContactDetail contactDetail = qmlObject->property("contactDetail").value(); + //! [ContactDetail get] + + //! [ContactDetail set] + qmlObject->setProperty("contactDetail", QVariant::fromValue(contactDetail)); + //! [ContactDetail set] + + //! [Place get] + QPlace place = qmlObject->property("place").value(); + //! [Place get] + + //! [Place set] + qmlObject->setProperty("place", QVariant::fromValue(place)); + //! [Place set] + + //! [PlaceAttribute get] + QPlaceAttribute placeAttribute = qmlObject->property("attribute").value(); + //! [PlaceAttribute get] + + //! [PlaceAttribute set] + qmlObject->setProperty("attribute", QVariant::fromValue(placeAttribute)); + //! [PlaceAttribute set] + + //! [Icon get] + QPlaceIcon placeIcon = qmlObject->property("icon").value(); + //! [Icon get] + + //! [Icon set] + qmlObject->setProperty("icon", QVariant::fromValue(placeIcon)); + //! [Icon set] + + //! [User get] + QPlaceUser placeUser = qmlObject->property("user").value(); + //! [User get] + + //! [User set] + qmlObject->setProperty("user", QVariant::fromValue(placeUser)); + //! [User set] + + //! [Ratings get] + QPlaceRatings placeRatings = qmlObject->property("ratings").value(); + //! [Ratings get] + + //! [Ratings set] + qmlObject->setProperty("ratings", QVariant::fromValue(placeRatings)); + //! [Ratings set] + + //! [Supplier get] + QPlaceSupplier placeSupplier = qmlObject->property("supplier").value(); + //! [Supplier get] + + //! [Supplier set] + qmlObject->setProperty("supplier", QVariant::fromValue(placeSupplier)); + //! [Supplier set] +} + diff --git a/src/location/doc/snippets/cpp/main.cpp b/src/location/doc/snippets/cpp/main.cpp new file mode 100644 index 0000000..1cc1184 --- /dev/null +++ b/src/location/doc/snippets/cpp/main.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +int main(int /*argc*/, char ** /*argv*/) +{ + return 0; +} + diff --git a/src/location/doc/snippets/declarative/content/Cell.qml b/src/location/doc/snippets/declarative/content/Cell.qml new file mode 100644 index 0000000..0391e0b --- /dev/null +++ b/src/location/doc/snippets/declarative/content/Cell.qml @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt 4.7 + +Item { + id: container + property string action: "no-op" + signal clicked(string action) + + width: 100; height:30 + + Rectangle { + id: rectangle + border.color: "white" + border.width: 2 + anchors.fill: parent // Fill the whole container + } + Text { + id: text + text: container.action + color: "black" + anchors.left: parent.left + anchors.leftMargin: 5 + anchors.verticalCenter: parent.verticalCenter + } + MouseArea { + anchors.fill: parent // Whole container is clickable + onClicked: container.clicked(container.action) + } +} diff --git a/src/location/doc/snippets/declarative/declarative-location.qml b/src/location/doc/snippets/declarative/declarative-location.qml new file mode 100644 index 0000000..8eb18e2 --- /dev/null +++ b/src/location/doc/snippets/declarative/declarative-location.qml @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//![0] +import QtQuick 2.0 +import QtPositioning 5.2 + +Rectangle { + id: page + width: 350 + height: 350 + PositionSource { + id: positionSource + updateInterval: 1000 + active: true + // nmeaSource: "nmealog.txt" + } + Column { + Text {text: "<==== PositionSource ====>"} + Text {text: "preferredPositioningMethods: " + printableMethod(positionSource.preferredPositioningMethods)} + Text {text: "supportedPositioningMethods: " + printableMethod(positionSource.supportedPositioningMethods)} + Text {text: "nmeaSource: " + positionSource.nmeaSource} + Text {text: "updateInterval: " + positionSource.updateInterval} + Text {text: "active: " + positionSource.active} + Text {text: "<==== Position ====>"} + Text {text: "latitude: " + positionSource.position.coordinate.latitude} + Text {text: "longitude: " + positionSource.position.coordinate.longitude} + Text {text: "altitude: " + positionSource.position.coordinate.altitude} + Text {text: "speed: " + positionSource.position.speed} + Text {text: "timestamp: " + positionSource.position.timestamp} + Text {text: "altitudeValid: " + positionSource.position.altitudeValid} + Text {text: "longitudeValid: " + positionSource.position.longitudeValid} + Text {text: "latitudeValid: " + positionSource.position.latitudeValid} + Text {text: "speedValid: " + positionSource.position.speedValid} + } + function printableMethod(method) { + if (method == PositionSource.SatellitePositioningMethods) + return "Satellite"; + else if (method == PositionSource.NoPositioningMethods) + return "Not available" + else if (method == PositionSource.NonSatellitePositioningMethods) + return "Non-satellite" + else if (method == PositionSource.AllPositioningMethods) + return "All/multiple" + return "source error"; + } + } +//![0] diff --git a/src/location/doc/snippets/declarative/declarative.pro b/src/location/doc/snippets/declarative/declarative.pro new file mode 100644 index 0000000..226010c --- /dev/null +++ b/src/location/doc/snippets/declarative/declarative.pro @@ -0,0 +1,18 @@ +TEMPLATE = aux + +content.files = \ + declarative-location.qml \ + maps.qml \ + places.qml \ + plugin.qml \ + routing.qml \ + places_loader.qml + +OTHER_FILES = \ + $${content.files} + +# Put content in INSTALLS so that content.files become part of the project tree in Qt Creator, +# but scoped with false as we don't actually want to install them. They are documentation +# snippets. +false:INSTALLS += content + diff --git a/src/location/doc/snippets/declarative/maps.qml b/src/location/doc/snippets/declarative/maps.qml new file mode 100644 index 0000000..3378ee0 --- /dev/null +++ b/src/location/doc/snippets/declarative/maps.qml @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [QtQuick import] +import QtQuick 2.0 +//! [QtQuick import] +//! [QtLocation import] +import QtPositioning 5.5 +import QtLocation 5.6 +//! [QtLocation import] + +Item { + id: page + + Plugin { + id: myPlugin + } + + //! [MapRoute] + Map { + RouteModel { + id: routeModel + } + + MapItemView { + model: routeModel + delegate: routeDelegate + } + + Component { + id: routeDelegate + + MapRoute { + route: routeData + line.color: "blue" + line.width: 5 + smooth: true + opacity: 0.8 + } + } + } + //! [MapRoute] + + //! [Map addMapItem MapCircle at current position] + PositionSource { + id: positionSource + } + + Map { + id: map + property MapCircle circle + + Component.onCompleted: { + circle = Qt.createQmlObject('import QtLocation 5.3; MapCircle {}', page) + circle.center = positionSource.position.coordinate + circle.radius = 5000.0 + circle.color = 'green' + circle.border.width = 3 + map.addMapItem(circle) + } + } + //! [Map addMapItem MapCircle at current position] +} diff --git a/src/location/doc/snippets/declarative/marker.png b/src/location/doc/snippets/declarative/marker.png new file mode 100644 index 0000000..fd727d9 Binary files /dev/null and b/src/location/doc/snippets/declarative/marker.png differ diff --git a/src/location/doc/snippets/declarative/nmealog.txt b/src/location/doc/snippets/declarative/nmealog.txt new file mode 100644 index 0000000..8c8286d --- /dev/null +++ b/src/location/doc/snippets/declarative/nmealog.txt @@ -0,0 +1,1403 @@ +$GPGGA,222437.000,2734.33926,S,15305.44310,E,1,07,1.3,50.6,M,39.2,M,,*72 +$GPGLL,2734.33926,S,15305.44310,E,222437.000,A,A*49 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222437.000,13.3,7.4,6.6,85.1,6.0,6.8,13.7*56 +$GPGSV,3,1,10,16,49,115,42,25,39,269,36,23,58,176,29,20,72,335,35*75 +$GPGSV,3,2,10,19,02,028,,04,06,241,22,13,30,223,30,27,19,284,35*78 +$GPGSV,3,3,10,11,06,337,30,03,13,055,25*7C +$GPRMC,222437.000,A,2734.33926,S,15305.44310,E,33.9,157.8,030308,11.2,W,A*0F +$GPVTG,157.8,T,169.0,M,33.9,N,62.9,K,A*22 +$GPGGA,222438.000,2734.34821,S,15305.44697,E,1,07,1.2,50.8,M,39.2,M,,*79 +$GPGLL,2734.34821,S,15305.44697,E,222438.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222438.000,12.4,6.4,9.3,16.2,6.1,8.3,16.4*5F +$GPGSV,3,1,10,16,49,115,41,25,39,269,36,23,58,176,28,20,72,335,36*74 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,28,27,19,284,35*73 +$GPGSV,3,3,10,11,06,337,28,03,13,055,25*75 +$GPRMC,222438.000,A,2734.34821,S,15305.44697,E,33.8,158.3,030308,11.2,W,A*0E +$GPVTG,158.3,T,169.5,M,33.8,N,62.5,K,A*2E +$GPGGA,222439.000,2734.35696,S,15305.45072,E,1,06,1.7,51.2,M,39.2,M,,*78 +$GPGLL,2734.35696,S,15305.45072,E,222439.000,A,A*43 +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222439.000,10.3,9.1,12.2,44.6,9.8,9.9,25.2*62 +$GPGSV,3,1,10,16,49,115,34,25,39,269,36,23,58,175,29,20,72,335,35*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,27,27,19,284,32*7B +$GPGSV,3,3,10,11,06,337,28,03,14,055,25*72 +$GPRMC,222439.000,A,2734.35696,S,15305.45072,E,33.2,158.7,030308,11.2,W,A*0E +$GPVTG,158.7,T,169.9,M,33.2,N,61.5,K,A*2F +$GPGGA,222440.000,2734.36580,S,15305.45446,E,1,07,1.3,52.0,M,39.2,M,,*76 +$GPGLL,2734.36580,S,15305.45446,E,222440.000,A,A*49 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222440.000,13.0,8.0,13.4,6.2,7.4,12.2,20.9*64 +$GPGSV,3,1,10,16,49,115,40,25,39,269,38,23,58,175,31,20,72,335,34*72 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,26,27,19,284,30*78 +$GPGSV,3,3,10,11,06,337,26,03,14,055,25*7C +$GPRMC,222440.000,A,2734.36580,S,15305.45446,E,33.7,159.1,030308,11.2,W,A*06 +$GPVTG,159.1,T,170.3,M,33.7,N,62.4,K,A*2D +$GPGGA,222441.000,2734.37483,S,15305.45825,E,1,07,1.3,52.7,M,39.2,M,,*7A +$GPGLL,2734.37483,S,15305.45825,E,222441.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222441.000,14.0,7.6,14.1,17.6,7.7,12.5,21.0*51 +$GPGSV,3,1,10,16,49,115,41,25,39,269,39,23,58,175,29,20,72,335,35*7A +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,24,27,19,284,30*7A +$GPGSV,3,3,10,11,06,337,28,03,14,055,25*72 +$GPRMC,222441.000,A,2734.37483,S,15305.45825,E,34.6,159.4,030308,11.2,W,A*0E +$GPVTG,159.4,T,170.6,M,34.6,N,64.1,K,A*28 +$GPGGA,222442.000,2734.38407,S,15305.46216,E,1,06,1.3,53.3,M,39.2,M,,*77 +$GPGLL,2734.38407,S,15305.46216,E,222442.000,A,A*4B +$GPGSA,A,3,16,25,20,13,27,11,,,,,,,2.3,1.3,1.9*3C +$GPGST,222442.000,16.6,7.0,14.4,14.6,7.0,12.8,21.6*5A +$GPGSV,3,1,10,16,49,115,40,25,39,269,38,23,58,175,22,20,72,335,35*71 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,25,27,19,284,29*73 +$GPGSV,3,3,10,11,06,337,27,03,14,055,25*7D +$GPRMC,222442.000,A,2734.38407,S,15305.46216,E,35.5,159.3,030308,11.2,W,A*02 +$GPVTG,159.3,T,170.5,M,35.5,N,65.8,K,A*26 +$GPGGA,222443.000,2734.39347,S,15305.46609,E,1,05,1.8,53.8,M,39.2,M,,*7D +$GPGLL,2734.39347,S,15305.46609,E,222443.000,A,A*42 +$GPGSA,A,3,16,25,20,27,11,,,,,,,,2.8,1.8,2.1*35 +$GPGST,222443.000,11.3,6.5,14.6,14.5,6.6,13.0,18.4*5A +$GPGSV,3,1,10,16,49,115,40,25,39,269,38,23,58,175,22,20,72,335,36*72 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,26,27,19,284,31*79 +$GPGSV,3,3,10,11,06,337,28,03,14,055,25*72 +$GPRMC,222443.000,A,2734.39347,S,15305.46609,E,36.2,159.4,030308,11.2,W,A*08 +$GPVTG,159.4,T,170.6,M,36.2,N,67.0,K,A*2C +$GPGGA,222444.000,2734.40297,S,15305.47000,E,1,06,1.3,54.1,M,39.2,M,,*70 +$GPGLL,2734.40297,S,15305.47000,E,222444.000,A,A*49 +$GPGSA,A,3,16,25,20,13,27,11,,,,,,,2.3,1.3,1.9*3C +$GPGST,222444.000,17.6,6.3,12.7,14.4,6.3,11.4,16.2*55 +$GPGSV,3,1,10,16,49,115,38,25,39,269,38,23,58,175,22,20,72,335,35*7E +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,25,27,19,284,29*73 +$GPGSV,3,3,10,11,06,337,25,03,14,055,23*79 +$GPRMC,222444.000,A,2734.40297,S,15305.47000,E,36.5,159.5,030308,11.2,W,A*05 +$GPVTG,159.5,T,170.8,M,36.5,N,67.5,K,A*21 +$GPGGA,222445.000,2734.41247,S,15305.47390,E,1,07,1.3,54.2,M,39.2,M,,*75 +$GPGLL,2734.41247,S,15305.47390,E,222445.000,A,A*4E +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222445.000,16.0,7.0,14.4,10.4,6.7,13.0,20.7*52 +$GPGSV,3,1,10,16,49,115,36,25,39,269,36,23,58,175,22,20,72,335,34*7F +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,30,223,26,27,19,284,31*79 +$GPGSV,3,3,10,11,06,337,26,03,14,055,23*7A +$GPRMC,222445.000,A,2734.41247,S,15305.47390,E,36.6,159.7,030308,11.2,W,A*03 +$GPVTG,159.7,T,170.9,M,36.6,N,67.8,K,A*2C +$GPGGA,222446.000,2734.42201,S,15305.47790,E,1,07,1.3,54.4,M,39.2,M,,*75 +$GPGLL,2734.42201,S,15305.47790,E,222446.000,A,A*48 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222446.000,13.0,7.4,12.3,6.6,6.9,11.2,17.9*60 +$GPGSV,3,1,10,16,49,115,36,25,39,269,37,23,58,175,27,20,72,335,35*7A +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,30,223,30,27,19,284,32*7E +$GPGSV,3,3,10,11,06,337,27,03,14,055,23*7B +$GPRMC,222446.000,A,2734.42201,S,15305.47790,E,36.6,159.3,030308,11.2,W,A*01 +$GPVTG,159.3,T,170.5,M,36.6,N,67.7,K,A*2B +$GPGGA,222447.000,2734.43157,S,15305.48195,E,1,07,1.3,54.3,M,39.2,M,,*7E +$GPGLL,2734.43157,S,15305.48195,E,222447.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222447.000,10.7,6.7,10.5,6.6,6.2,9.6,15.5*5B +$GPGSV,3,1,11,16,49,115,32,25,39,269,37,23,58,175,28,20,72,335,33*76 +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,30,223,30,27,19,284,32*7F +$GPGSV,3,3,11,11,06,337,29,01,,,19,03,14,055,23*7D +$GPRMC,222447.000,A,2734.43157,S,15305.48195,E,36.7,159.1,030308,11.2,W,A*0E +$GPVTG,159.1,T,170.3,M,36.7,N,67.9,K,A*20 +$GPGGA,222448.000,2734.44111,S,15305.48610,E,1,08,1.1,54.1,M,39.2,M,,*71 +$GPGLL,2734.44111,S,15305.48610,E,222448.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222448.000,20.4,10.5,8.8,52.5,8.7,9.1,15.2*6C +$GPGSV,3,1,11,16,49,115,27,25,39,269,38,23,58,175,26,20,72,335,31*71 +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,30,223,37,27,19,284,27*7C +$GPGSV,3,3,11,11,06,337,27,01,,,19,03,14,055,23*73 +$GPRMC,222448.000,A,2734.44111,S,15305.48610,E,36.8,158.7,030308,11.2,W,A*06 +$GPVTG,158.7,T,169.9,M,36.8,N,68.2,K,A*2E +$GPGGA,222449.000,2734.45068,S,15305.49044,E,1,08,1.1,53.6,M,39.2,M,,*78 +$GPGLL,2734.45068,S,15305.49044,E,222449.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222449.000,17.1,8.8,10.2,14.2,8.2,9.3,17.4*6D +$GPGSV,3,1,11,16,49,115,28,25,39,269,37,23,58,175,25,20,72,335,28*7A +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,30,223,37,27,19,284,32*78 +$GPGSV,3,3,11,11,06,337,27,01,,,19,03,14,055,24*74 +$GPRMC,222449.000,A,2734.45068,S,15305.49044,E,37.2,157.8,030308,11.2,W,A*04 +$GPVTG,157.8,T,169.0,M,37.2,N,68.9,K,A*27 +$GPGGA,222450.000,2734.46041,S,15305.49485,E,1,08,1.1,53.3,M,39.2,M,,*74 +$GPGLL,2734.46041,S,15305.49485,E,222450.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222450.000,17.4,8.9,12.7,10.1,11.5,8.2,16.5*5E +$GPGSV,3,1,11,16,49,115,25,25,39,269,36,23,58,175,30,20,72,336,28*71 +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,38,27,19,284,34*73 +$GPGSV,3,3,11,11,06,337,27,01,,,19,03,14,055,22*72 +$GPRMC,222450.000,A,2734.46041,S,15305.49485,E,37.7,157.9,030308,11.2,W,A*09 +$GPVTG,157.9,T,169.1,M,37.7,N,69.8,K,A*22 +$GPGGA,222451.000,2734.47033,S,15305.49924,E,1,08,1.1,53.1,M,39.2,M,,*75 +$GPGLL,2734.47033,S,15305.49924,E,222451.000,A,A*47 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222451.000,14.1,8.0,10.5,14.3,9.5,7.5,15.0*61 +$GPGSV,3,1,11,16,49,115,27,25,39,269,38,23,58,175,28,20,72,336,25*79 +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,38,27,19,284,34*73 +$GPGSV,3,3,11,11,06,337,24,01,,,19,03,14,055,25*76 +$GPRMC,222451.000,A,2734.47033,S,15305.49924,E,38.1,158.1,030308,11.2,W,A*04 +$GPVTG,158.1,T,169.3,M,38.1,N,70.5,K,A*2B +$GPGGA,222452.000,2734.48022,S,15305.50375,E,1,08,1.1,52.5,M,39.2,M,,*7A +$GPGLL,2734.48022,S,15305.50375,E,222452.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222452.000,24.1,13.9,9.7,80.6,12.7,9.0,21.0*54 +$GPGSV,3,1,11,16,49,115,29,25,39,269,38,23,58,175,27,20,72,336,30*7C +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,35,27,19,284,34*7E +$GPGSV,3,3,11,11,06,337,22,01,,,19,03,14,055,24*71 +$GPRMC,222452.000,A,2734.48022,S,15305.50375,E,38.3,157.9,030308,11.2,W,A*0B +$GPVTG,157.9,T,169.1,M,38.3,N,70.9,K,A*20 +$GPGGA,222453.000,2734.49019,S,15305.50802,E,1,06,1.7,52.1,M,39.2,M,,*75 +$GPGLL,2734.49019,S,15305.50802,E,222453.000,A,A*4E +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222453.000,10.4,15.4,9.3,66.3,13.4,9.6,24.6*52 +$GPGSV,3,1,11,16,49,115,31,25,39,269,36,23,58,175,28,20,71,336,25*73 +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,33,27,19,284,31*7D +$GPGSV,3,3,11,11,06,337,22,01,,,19,03,14,055,24*71 +$GPRMC,222453.000,A,2734.49019,S,15305.50802,E,38.3,159.1,030308,11.2,W,A*0E +$GPVTG,159.1,T,170.3,M,38.3,N,70.9,K,A*2C +$GPGGA,222454.000,2734.50008,S,15305.51221,E,1,07,1.3,52.1,M,39.2,M,,*75 +$GPGLL,2734.50008,S,15305.51221,E,222454.000,A,A*4B +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222454.000,12.5,11.7,8.3,70.6,10.4,8.0,19.0*5E +$GPGSV,3,1,11,16,49,115,30,25,39,269,36,23,58,175,26,20,71,336,28*71 +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,32,27,19,284,30*7D +$GPGSV,3,3,11,11,06,337,24,01,,,18,03,14,055,24*76 +$GPRMC,222454.000,A,2734.50008,S,15305.51221,E,38.1,159.4,030308,11.2,W,A*0C +$GPVTG,159.4,T,170.6,M,38.1,N,70.5,K,A*22 +$GPGGA,222455.000,2734.50992,S,15305.51642,E,1,07,1.3,52.2,M,39.2,M,,*7C +$GPGLL,2734.50992,S,15305.51642,E,222455.000,A,A*41 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222455.000,11.5,10.8,9.3,83.5,9.9,8.6,23.3*65 +$GPGSV,3,1,11,16,49,115,33,25,39,269,36,23,58,175,32,20,71,336,31*7F +$GPGSV,3,2,11,19,02,028,,04,06,241,21,13,30,223,29,27,19,284,29*7F +$GPGSV,3,3,11,11,06,337,28,01,,,18,03,14,055,24*7A +$GPRMC,222455.000,A,2734.50992,S,15305.51642,E,37.8,159.0,030308,11.2,W,A*04 +$GPVTG,159.0,T,170.2,M,37.8,N,70.0,K,A*21 +$GPGGA,222456.000,2734.51963,S,15305.52059,E,1,07,1.3,52.5,M,39.2,M,,*78 +$GPGLL,2734.51963,S,15305.52059,E,222456.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,11,,,,,,2.3,1.3,1.9*3D +$GPGST,222456.000,11.3,9.0,13.1,11.0,8.4,11.9,20.9*55 +$GPGSV,3,1,11,16,49,115,31,25,39,269,37,23,58,175,27,20,71,336,33*7A +$GPGSV,3,2,11,19,02,028,,04,06,241,19,13,30,223,29,27,19,284,32*7E +$GPGSV,3,3,11,11,06,337,30,01,,,18,03,14,055,24*73 +$GPRMC,222456.000,A,2734.51963,S,15305.52059,E,37.3,158.8,030308,11.2,W,A*05 +$GPVTG,158.8,T,170.0,M,37.3,N,69.1,K,A*28 +$GPGGA,222457.000,2734.52908,S,15305.52467,E,1,06,1.3,53.2,M,39.2,M,,*79 +$GPGLL,2734.52908,S,15305.52467,E,222457.000,A,A*44 +$GPGSA,A,3,16,25,20,13,27,11,,,,,,,2.3,1.3,1.9*3C +$GPGST,222457.000,20.4,7.8,12.0,8.1,7.3,10.9,17.9*63 +$GPGSV,3,1,11,16,49,115,37,25,39,269,37,23,58,175,24,20,71,336,35*79 +$GPGSV,3,2,11,19,02,028,,04,06,241,19,13,30,223,29,27,19,284,32*7E +$GPGSV,3,3,11,11,06,337,28,01,,,18,03,14,055,23*7D +$GPRMC,222457.000,A,2734.52908,S,15305.52467,E,36.2,158.7,030308,11.2,W,A*0C +$GPVTG,158.7,T,169.9,M,36.2,N,67.1,K,A*28 +$GPGGA,222458.000,2734.53845,S,15305.52866,E,1,06,1.6,54.2,M,39.2,M,,*70 +$GPGLL,2734.53845,S,15305.52866,E,222458.000,A,A*4F +$GPGSA,A,3,16,25,23,20,27,11,,,,,,,2.6,1.6,2.1*34 +$GPGST,222458.000,16.7,7.3,13.9,11.0,7.0,12.5,17.9*5D +$GPGSV,3,1,11,16,49,115,36,25,39,269,37,23,58,175,24,20,71,336,35*78 +$GPGSV,3,2,11,19,02,028,19,04,06,241,19,13,30,223,26,27,19,284,31*7A +$GPGSV,3,3,11,11,06,337,23,01,,,18,03,14,055,23*76 +$GPRMC,222458.000,A,2734.53845,S,15305.52866,E,35.9,159.1,030308,11.2,W,A*08 +$GPVTG,159.1,T,170.3,M,35.9,N,66.5,K,A*20 +$GPGGA,222459.000,2734.54772,S,15305.53309,E,1,08,1.1,55.6,M,39.2,M,,*72 +$GPGLL,2734.54772,S,15305.53309,E,222459.000,A,A*41 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222459.000,17.5,6.5,9.3,15.5,6.1,8.3,15.2*5C +$GPGSV,3,1,11,16,49,115,38,25,39,268,36,23,58,175,35,20,71,336,35*76 +$GPGSV,3,2,11,19,02,028,19,04,06,241,19,13,30,223,33,27,19,284,34*7B +$GPGSV,3,3,11,11,06,337,29,01,,,18,03,14,055,22*7D +$GPRMC,222459.000,A,2734.54772,S,15305.53309,E,35.9,156.8,030308,11.2,W,A*00 +$GPVTG,156.8,T,168.0,M,35.9,N,66.4,K,A*2D +$GPGGA,222500.000,2734.55655,S,15305.53845,E,1,08,1.1,56.1,M,39.2,M,,*7D +$GPGLL,2734.55655,S,15305.53845,E,222500.000,A,A*4A +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222500.000,14.5,9.8,7.9,83.3,7.3,9.0,14.3*5C +$GPGSV,3,1,11,16,49,115,36,25,39,268,31,23,58,175,39,20,71,336,33*75 +$GPGSV,3,2,11,19,02,028,21,04,06,241,19,13,30,223,30,27,19,284,29*7F +$GPGSV,3,3,11,11,06,337,25,01,,,18,03,14,055,28*7B +$GPRMC,222500.000,A,2734.55655,S,15305.53845,E,35.9,151.6,030308,11.2,W,A*02 +$GPVTG,151.6,T,162.8,M,35.9,N,66.5,K,A*27 +$GPGGA,222501.000,2734.56495,S,15305.54489,E,1,08,1.1,57.0,M,39.2,M,,*7A +$GPGLL,2734.56495,S,15305.54489,E,222501.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222501.000,14.3,8.0,10.9,27.0,8.0,9.5,15.6*64 +$GPGSV,3,1,11,16,49,115,41,25,39,268,31,23,58,175,36,20,71,336,31*78 +$GPGSV,3,2,11,19,02,028,21,04,06,241,19,13,30,223,27,27,19,284,29*79 +$GPGSV,3,3,11,11,06,337,22,01,,,18,03,14,055,31*74 +$GPRMC,222501.000,A,2734.56495,S,15305.54489,E,36.5,145.7,030308,11.2,W,A*0E +$GPVTG,145.7,T,156.9,M,36.5,N,67.5,K,A*2B +$GPGGA,222502.000,2734.57337,S,15305.55181,E,1,06,1.5,57.9,M,39.2,M,,*78 +$GPGLL,2734.57337,S,15305.55181,E,222502.000,A,A*4C +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222502.000,14.5,7.0,11.9,20.7,7.1,10.5,15.0*5F +$GPGSV,3,1,11,16,49,115,43,25,39,268,35,23,58,175,37,20,71,336,34*7A +$GPGSV,3,2,11,19,02,028,21,04,06,241,19,13,30,223,23,27,19,284,33*76 +$GPGSV,3,3,11,11,06,337,22,01,,,18,03,14,055,34*71 +$GPRMC,222502.000,A,2734.57337,S,15305.55181,E,37.4,143.8,030308,11.2,W,A*06 +$GPVTG,143.8,T,155.0,M,37.4,N,69.3,K,A*20 +$GPGGA,222503.000,2734.58184,S,15305.55887,E,1,08,1.1,58.5,M,39.2,M,,*7A +$GPGLL,2734.58184,S,15305.55887,E,222503.000,A,A*47 +$GPGSA,A,3,16,25,23,20,13,27,11,03,,,,,2.0,1.1,1.6*30 +$GPGST,222503.000,13.4,6.4,14.1,0.3,5.9,12.9,21.5*60 +$GPGSV,3,1,11,16,49,115,43,25,39,268,35,23,58,175,38,20,71,336,35*74 +$GPGSV,3,2,11,19,02,028,19,04,06,241,19,13,30,223,23,27,19,284,32*7C +$GPGSV,3,3,11,11,06,337,26,01,,,17,03,14,055,34*7A +$GPRMC,222503.000,A,2734.58184,S,15305.55887,E,37.8,143.4,030308,11.2,W,A*0D +$GPVTG,143.4,T,154.6,M,37.8,N,70.0,K,A*2C +$GPGGA,222504.000,2734.59032,S,15305.56580,E,1,07,1.2,58.9,M,39.2,M,,*79 +$GPGLL,2734.59032,S,15305.56580,E,222504.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222504.000,24.6,6.2,13.3,3.6,5.7,12.2,20.2*67 +$GPGSV,3,1,11,16,49,115,43,25,39,268,35,23,58,175,39,20,71,336,35*75 +$GPGSV,3,2,11,19,02,028,19,04,06,241,19,13,30,223,22,27,19,284,31*7E +$GPGSV,3,3,11,11,06,337,25,01,,,17,03,14,055,30*7D +$GPRMC,222504.000,A,2734.59032,S,15305.56580,E,37.6,143.6,030308,11.2,W,A*02 +$GPVTG,143.6,T,154.8,M,37.6,N,69.7,K,A*21 +$GPGGA,222505.000,2734.59874,S,15305.57271,E,1,06,1.5,59.4,M,39.2,M,,*70 +$GPGLL,2734.59874,S,15305.57271,E,222505.000,A,A*47 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222505.000,17.4,5.5,11.8,3.4,5.0,10.8,17.3*61 +$GPGSV,3,1,11,16,49,115,44,25,39,268,35,23,58,175,39,20,71,336,36*71 +$GPGSV,3,2,11,19,02,028,21,04,06,241,19,13,30,223,24,27,19,284,31*73 +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,29*72 +$GPRMC,222505.000,A,2734.59874,S,15305.57271,E,37.3,143.7,030308,11.2,W,A*05 +$GPVTG,143.7,T,154.9,M,37.3,N,69.1,K,A*22 +$GPGGA,222506.000,2734.60703,S,15305.57943,E,1,07,1.2,60.1,M,39.2,M,,*75 +$GPGLL,2734.60703,S,15305.57943,E,222506.000,A,A*4B +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222506.000,16.1,6.2,11.7,15.3,6.1,10.4,17.4*54 +$GPGSV,3,1,11,16,49,115,43,25,39,268,34,23,58,175,37,20,71,336,36*79 +$GPGSV,3,2,11,19,02,028,21,04,06,241,,13,30,223,24,27,19,284,31*7B +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,28*73 +$GPRMC,222506.000,A,2734.60703,S,15305.57943,E,36.5,143.9,030308,11.2,W,A*00 +$GPVTG,143.9,T,155.1,M,36.5,N,67.6,K,A*2B +$GPGGA,222507.000,2734.61507,S,15305.58593,E,1,07,1.2,60.9,M,39.2,M,,*75 +$GPGLL,2734.61507,S,15305.58593,E,222507.000,A,A*43 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222507.000,14.0,6.8,11.8,10.9,6.4,10.7,18.5*54 +$GPGSV,3,1,11,16,49,115,43,25,39,268,34,23,58,175,37,20,71,336,34*7B +$GPGSV,3,2,11,19,02,028,21,04,06,241,,13,30,223,29,27,19,284,34*73 +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,29*72 +$GPRMC,222507.000,A,2734.61507,S,15305.58593,E,35.4,143.9,030308,11.2,W,A*0A +$GPVTG,143.9,T,155.1,M,35.4,N,65.5,K,A*28 +$GPGGA,222508.000,2734.62275,S,15305.59221,E,1,06,1.7,61.8,M,39.2,M,,*70 +$GPGLL,2734.62275,S,15305.59221,E,222508.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222508.000,12.5,9.3,16.3,19.5,9.4,14.4,27.5*51 +$GPGSV,3,1,11,16,49,115,43,25,39,268,33,23,58,175,38,20,71,336,31*76 +$GPGSV,3,2,11,19,02,028,21,04,06,241,,13,30,223,30,27,19,284,35*7A +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,28*73 +$GPRMC,222508.000,A,2734.62275,S,15305.59221,E,33.9,143.9,030308,11.2,W,A*00 +$GPVTG,143.9,T,155.1,M,33.9,N,62.9,K,A*28 +$GPGGA,222509.000,2734.63006,S,15305.59817,E,1,06,1.7,62.7,M,39.2,M,,*75 +$GPGLL,2734.63006,S,15305.59817,E,222509.000,A,A*4B +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222509.000,10.4,8.1,14.2,21.9,8.4,12.3,23.7*52 +$GPGSV,3,1,11,16,49,115,44,25,39,268,32,23,58,175,37,20,71,336,29*76 +$GPGSV,3,2,11,19,02,028,21,04,06,241,,13,30,223,28,27,19,284,35*73 +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,30*7A +$GPRMC,222509.000,A,2734.63006,S,15305.59817,E,32.2,143.9,030308,11.2,W,A*03 +$GPVTG,143.9,T,155.1,M,32.2,N,59.7,K,A*24 +$GPGGA,222510.000,2734.63706,S,15305.60376,E,1,06,1.7,63.5,M,39.2,M,,*7F +$GPGLL,2734.63706,S,15305.60376,E,222510.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.8*3A +$GPGST,222510.000,12.4,8.3,12.9,28.0,8.7,11.0,21.6*57 +$GPGSV,3,1,11,16,48,115,43,25,39,268,32,23,58,175,37,20,71,336,29*70 +$GPGSV,3,2,11,19,02,028,20,04,06,241,,13,30,223,31,27,19,284,35*7A +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,25*7E +$GPRMC,222510.000,A,2734.63706,S,15305.60376,E,30.6,144.3,030308,11.2,W,A*01 +$GPVTG,144.3,T,155.5,M,30.6,N,56.7,K,A*24 +$GPGGA,222511.000,2734.64376,S,15305.60904,E,1,07,1.2,64.4,M,39.2,M,,*77 +$GPGLL,2734.64376,S,15305.60904,E,222511.000,A,A*48 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222511.000,14.6,5.7,10.5,2.7,5.2,9.6,15.0*5C +$GPGSV,3,1,11,16,48,115,44,25,39,268,32,23,58,175,37,20,71,336,28*76 +$GPGSV,3,2,11,19,02,028,20,04,06,241,23,13,30,223,29,27,19,284,36*71 +$GPGSV,3,3,11,11,06,337,,01,,,17,03,14,055,29*72 +$GPRMC,222511.000,A,2734.64376,S,15305.60904,E,29.1,144.2,030308,11.2,W,A*05 +$GPVTG,144.2,T,155.4,M,29.1,N,53.9,K,A*20 +$GPGGA,222512.000,2734.64992,S,15305.61405,E,1,07,1.2,65.4,M,39.2,M,,*78 +$GPGLL,2734.64992,S,15305.61405,E,222512.000,A,A*46 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222512.000,13.4,17.0,5.7,85.6,5.3,15.5,23.6*5A +$GPGSV,3,1,11,16,48,115,45,25,39,268,33,23,58,175,38,20,71,336,28*79 +$GPGSV,3,2,11,19,02,028,20,04,06,241,23,13,30,223,26,27,19,284,33*7B +$GPGSV,3,3,11,11,06,337,24,01,,,17,03,14,055,27*7A +$GPRMC,222512.000,A,2734.64992,S,15305.61405,E,27.2,143.6,030308,11.2,W,A*05 +$GPVTG,143.6,T,154.8,M,27.2,N,50.5,K,A*2C +$GPGGA,222513.000,2734.65572,S,15305.61884,E,1,07,1.2,66.2,M,39.2,M,,*7A +$GPGLL,2734.65572,S,15305.61884,E,222513.000,A,A*41 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222513.000,12.3,7.0,14.8,2.4,6.5,13.5,21.4*6D +$GPGSV,3,1,10,16,48,115,44,25,39,268,35,23,58,175,38,20,71,336,28*7F +$GPGSV,3,2,10,19,02,028,20,04,06,241,23,13,30,223,23,27,19,284,33*7F +$GPGSV,3,3,10,11,06,337,24,03,14,055,28*73 +$GPRMC,222513.000,A,2734.65572,S,15305.61884,E,25.8,143.6,030308,11.2,W,A*0A +$GPVTG,143.6,T,154.8,M,25.8,N,47.9,K,A*2E +$GPGGA,222514.000,2734.66155,S,15305.62364,E,1,06,1.5,67.0,M,39.2,M,,*7C +$GPGLL,2734.66155,S,15305.62364,E,222514.000,A,A*42 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222514.000,25.5,6.1,14.4,3.1,5.6,13.2,19.2*6A +$GPGSV,3,1,10,16,48,115,44,25,39,268,33,23,58,175,38,20,71,336,26*77 +$GPGSV,3,2,10,19,02,028,18,04,06,241,23,13,30,223,23,27,19,284,34*73 +$GPGSV,3,3,10,11,06,337,28,03,14,055,29*7E +$GPRMC,222514.000,A,2734.66155,S,15305.62364,E,25.9,143.6,030308,11.2,W,A*08 +$GPVTG,143.6,T,154.8,M,25.9,N,48.0,K,A*29 +$GPGGA,222515.000,2734.66761,S,15305.62860,E,1,06,1.5,67.5,M,39.2,M,,*76 +$GPGLL,2734.66761,S,15305.62860,E,222515.000,A,A*4D +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222515.000,20.1,5.5,13.0,3.0,5.1,11.8,17.4*68 +$GPGSV,3,1,10,16,48,115,44,25,39,268,32,23,58,175,38,20,71,336,26*76 +$GPGSV,3,2,10,19,02,028,18,04,06,241,23,13,30,223,24,27,19,284,34*74 +$GPGSV,3,3,10,11,06,337,28,03,14,055,24*73 +$GPRMC,222515.000,A,2734.66761,S,15305.62860,E,26.9,143.7,030308,11.2,W,A*05 +$GPVTG,143.7,T,154.9,M,26.9,N,49.8,K,A*23 +$GPGGA,222516.000,2734.67384,S,15305.63376,E,1,06,1.5,68.2,M,39.2,M,,*7E +$GPGLL,2734.67384,S,15305.63376,E,222516.000,A,A*4D +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222516.000,16.4,5.8,11.5,4.5,5.3,10.5,17.3*6A +$GPGSV,3,1,10,16,48,115,44,25,39,268,32,23,58,175,38,20,71,336,30*71 +$GPGSV,3,2,10,19,02,028,18,04,06,241,23,13,30,223,24,27,19,284,33*73 +$GPGSV,3,3,10,11,06,337,28,03,14,055,28*7F +$GPRMC,222516.000,A,2734.67384,S,15305.63376,E,27.7,143.8,030308,11.2,W,A*05 +$GPVTG,143.8,T,155.0,M,27.7,N,51.4,K,A*2E +$GPGGA,222517.000,2734.68035,S,15305.63901,E,1,06,1.5,68.8,M,39.2,M,,*79 +$GPGLL,2734.68035,S,15305.63901,E,222517.000,A,A*40 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222517.000,19.1,6.2,12.1,7.2,5.8,11.0,15.3*66 +$GPGSV,3,1,10,16,48,115,44,25,39,268,34,23,58,175,38,20,71,336,32*75 +$GPGSV,3,2,10,19,02,028,20,04,06,241,23,13,30,223,24,27,19,284,34*7F +$GPGSV,3,3,10,11,06,337,24,03,14,055,29*72 +$GPRMC,222517.000,A,2734.68035,S,15305.63901,E,28.6,144.1,030308,11.2,W,A*08 +$GPVTG,144.1,T,155.3,M,28.6,N,53.0,K,A*2B +$GPGGA,222518.000,2734.68718,S,15305.64446,E,1,07,1.4,69.1,M,39.2,M,,*7F +$GPGLL,2734.68718,S,15305.64446,E,222518.000,A,A*4E +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222518.000,13.8,5.5,10.6,5.8,5.1,9.6,13.4*54 +$GPGSV,3,1,10,16,48,115,43,25,39,268,33,23,58,175,37,20,71,336,35*7D +$GPGSV,3,2,10,19,02,028,20,04,06,241,18,13,30,223,24,27,19,284,33*70 +$GPGSV,3,3,10,11,06,337,22,03,14,055,33*7F +$GPRMC,222518.000,A,2734.68718,S,15305.64446,E,29.9,144.4,030308,11.2,W,A*0D +$GPVTG,144.4,T,155.6,M,29.9,N,55.3,K,A*20 +$GPGGA,222519.000,2734.69424,S,15305.65010,E,1,07,1.4,69.5,M,39.2,M,,*71 +$GPGLL,2734.69424,S,15305.65010,E,222519.000,A,A*44 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222519.000,14.0,13.4,5.0,89.4,4.6,12.3,18.8*58 +$GPGSV,3,1,10,16,48,115,44,25,39,268,34,23,58,175,37,20,71,336,37*7F +$GPGSV,3,2,10,19,02,028,20,04,06,241,18,13,30,223,23,27,19,284,31*75 +$GPGSV,3,3,10,11,06,337,26,03,14,055,35*7D +$GPRMC,222519.000,A,2734.69424,S,15305.65010,E,31.0,144.4,030308,11.2,W,A*07 +$GPVTG,144.4,T,155.6,M,31.0,N,57.5,K,A*24 +$GPGGA,222520.000,2734.70163,S,15305.65604,E,1,07,1.4,69.6,M,39.2,M,,*75 +$GPGLL,2734.70163,S,15305.65604,E,222520.000,A,A*43 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222520.000,9.8,11.6,4.7,89.0,4.3,10.6,15.9*6A +$GPGSV,3,1,10,16,48,115,44,25,39,268,35,23,58,175,39,20,71,336,36*71 +$GPGSV,3,2,10,19,02,028,20,04,06,241,19,13,30,223,23,27,19,284,31*74 +$GPGSV,3,3,10,11,06,337,31,03,14,055,37*79 +$GPRMC,222520.000,A,2734.70163,S,15305.65604,E,32.5,144.1,030308,11.2,W,A*03 +$GPVTG,144.1,T,155.3,M,32.5,N,60.2,K,A*21 +$GPGGA,222521.000,2734.70923,S,15305.66218,E,1,07,1.4,69.5,M,39.2,M,,*71 +$GPGLL,2734.70923,S,15305.66218,E,222521.000,A,A*44 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222521.000,11.1,6.2,10.8,9.6,5.8,9.8,16.8*53 +$GPGSV,3,1,10,16,48,115,44,25,39,268,36,23,58,175,40,20,71,336,38*72 +$GPGSV,3,2,10,19,02,028,20,04,06,241,19,13,30,223,23,27,19,284,26*72 +$GPGSV,3,3,10,11,06,338,31,03,14,055,37*76 +$GPRMC,222521.000,A,2734.70923,S,15305.66218,E,33.5,144.0,030308,11.2,W,A*04 +$GPVTG,144.0,T,155.3,M,33.5,N,62.0,K,A*21 +$GPGGA,222522.000,2734.71700,S,15305.66845,E,1,06,1.5,69.1,M,39.2,M,,*7A +$GPGLL,2734.71700,S,15305.66845,E,222522.000,A,A*4B +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222522.000,15.0,5.7,9.9,5.5,5.2,9.0,15.4*68 +$GPGSV,3,1,10,16,48,115,43,25,39,268,36,23,58,175,40,20,71,336,37*7A +$GPGSV,3,2,10,19,02,028,20,04,06,241,24,13,30,223,23,27,19,284,26*7C +$GPGSV,3,3,10,11,06,338,25,03,14,055,37*73 +$GPRMC,222522.000,A,2734.71700,S,15305.66845,E,34.2,144.1,030308,11.2,W,A*0A +$GPVTG,144.1,T,155.3,M,34.2,N,63.4,K,A*25 +$GPGGA,222523.000,2734.72487,S,15305.67483,E,1,07,1.4,68.6,M,39.2,M,,*75 +$GPGLL,2734.72487,S,15305.67483,E,222523.000,A,A*42 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222523.000,13.8,5.2,10.1,3.9,4.8,9.2,13.8*5B +$GPGSV,3,1,10,16,48,115,44,25,39,268,37,23,58,175,41,20,71,336,35*7F +$GPGSV,3,2,10,19,02,028,20,04,06,241,24,13,30,223,23,27,19,284,26*7C +$GPGSV,3,3,10,11,06,338,23,03,14,055,31*73 +$GPRMC,222523.000,A,2734.72487,S,15305.67483,E,34.7,144.2,030308,11.2,W,A*05 +$GPVTG,144.2,T,155.4,M,34.7,N,64.3,K,A*24 +$GPGGA,222524.000,2734.73280,S,15305.68126,E,1,07,1.4,68.1,M,39.2,M,,*70 +$GPGLL,2734.73280,S,15305.68126,E,222524.000,A,A*40 +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222524.000,10.5,4.9,9.4,3.5,4.5,8.6,12.8*60 +$GPGSV,3,1,10,16,48,115,44,25,39,268,37,23,58,175,41,20,71,336,35*7F +$GPGSV,3,2,10,19,02,028,20,04,06,241,22,13,30,223,23,27,19,284,26*7A +$GPGSV,3,3,10,11,06,338,25,03,14,055,29*7C +$GPRMC,222524.000,A,2734.73280,S,15305.68126,E,35.0,144.2,030308,11.2,W,A*01 +$GPVTG,144.2,T,155.4,M,35.0,N,64.9,K,A*28 +$GPGGA,222525.000,2734.74083,S,15305.68778,E,1,07,1.4,67.7,M,39.2,M,,*73 +$GPGLL,2734.74083,S,15305.68778,E,222525.000,A,A*4A +$GPGSA,A,3,16,25,23,20,27,11,03,,,,,,2.4,1.4,1.9*3C +$GPGST,222525.000,10.3,5.2,13.4,3.6,4.8,12.3,20.4*6B +$GPGSV,3,1,10,16,48,115,43,25,39,268,38,23,58,175,40,20,71,336,36*75 +$GPGSV,3,2,10,19,02,028,20,04,06,241,22,13,30,223,23,27,19,284,23*7F +$GPGSV,3,3,10,11,06,338,27,03,14,055,36*70 +$GPRMC,222525.000,A,2734.74083,S,15305.68778,E,35.6,144.2,030308,11.2,W,A*0D +$GPVTG,144.2,T,155.4,M,35.6,N,65.9,K,A*2F +$GPGGA,222526.000,2734.74894,S,15305.69428,E,1,06,1.5,67.2,M,39.2,M,,*7C +$GPGLL,2734.74894,S,15305.69428,E,222526.000,A,A*40 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222526.000,8.0,5.7,12.0,2.6,5.2,10.9,17.4*54 +$GPGSV,3,1,10,16,48,115,43,25,39,268,37,23,58,175,40,20,71,336,35*79 +$GPGSV,3,2,10,19,02,028,20,04,06,241,22,13,30,223,23,27,19,284,24*78 +$GPGSV,3,3,10,11,06,338,27,03,14,055,39*7F +$GPRMC,222526.000,A,2734.74894,S,15305.69428,E,35.8,144.5,030308,11.2,W,A*0E +$GPVTG,144.5,T,155.7,M,35.8,N,66.3,K,A*2C +$GPGGA,222527.000,2734.75707,S,15305.70075,E,1,05,1.7,66.8,M,39.2,M,,*77 +$GPGLL,2734.75707,S,15305.70075,E,222527.000,A,A*41 +$GPGSA,A,3,16,25,23,20,03,,,,,,,,2.9,1.7,2.4*39 +$GPGST,222527.000,13.9,6.3,10.9,6.3,5.9,10.0,18.2*60 +$GPGSV,3,1,10,16,48,115,44,25,39,268,38,23,58,175,40,20,71,336,33*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,30,223,23,27,19,284,26*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,36*75 +$GPRMC,222527.000,A,2734.75707,S,15305.70075,E,35.8,144.6,030308,11.2,W,A*0C +$GPVTG,144.6,T,155.8,M,35.8,N,66.2,K,A*21 +$GPGGA,222528.000,2734.76518,S,15305.70724,E,1,06,1.5,66.1,M,39.2,M,,*7C +$GPGLL,2734.76518,S,15305.70724,E,222528.000,A,A*42 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222528.000,11.3,5.6,10.1,4.5,5.2,9.2,16.1*51 +$GPGSV,3,1,10,16,48,115,43,25,39,268,39,23,58,175,39,20,71,336,28*75 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,30,223,23,27,19,284,26*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,36*75 +$GPRMC,222528.000,A,2734.76518,S,15305.70724,E,35.7,144.4,030308,11.2,W,A*02 +$GPVTG,144.4,T,155.6,M,35.7,N,66.2,K,A*22 +$GPGGA,222529.000,2734.77313,S,15305.71385,E,1,06,1.5,66.1,M,39.2,M,,*7F +$GPGLL,2734.77313,S,15305.71385,E,222529.000,A,A*41 +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222529.000,10.9,5.6,12.5,5.4,5.2,11.4,20.9*6F +$GPGSV,3,1,10,16,48,115,41,25,39,268,40,23,58,175,36,20,71,336,28*76 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,30,223,23,27,19,284,24*7D +$GPGSV,3,3,10,11,06,338,27,03,14,055,30*76 +$GPRMC,222529.000,A,2734.77313,S,15305.71385,E,35.6,143.5,030308,11.2,W,A*06 +$GPVTG,143.5,T,154.7,M,35.6,N,65.8,K,A*2C +$GPGGA,222530.000,2734.78106,S,15305.72042,E,1,06,1.5,66.0,M,39.2,M,,*74 +$GPGLL,2734.78106,S,15305.72042,E,222530.000,A,A*4B +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222530.000,9.4,5.4,18.9,2.4,4.9,17.3,30.6*54 +$GPGSV,3,1,10,16,48,115,40,25,39,268,40,23,58,175,36,20,71,336,28*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,30,223,23,27,19,284,26*7F +$GPGSV,3,3,10,11,06,338,27,03,14,055,29*7E +$GPRMC,222530.000,A,2734.78106,S,15305.72042,E,35.5,143.7,030308,11.2,W,A*0D +$GPVTG,143.7,T,155.0,M,35.5,N,65.8,K,A*2B +$GPGGA,222531.000,2734.78918,S,15305.72691,E,1,05,4.4,66.0,M,39.2,M,,*7D +$GPGLL,2734.78918,S,15305.72691,E,222531.000,A,A*45 +$GPGSA,A,3,16,25,23,27,11,,,,,,,,9.3,4.4,8.2*36 +$GPGST,222531.000,9.1,8.5,53.9,3.2,8.2,49.2,81.3*56 +$GPGSV,3,1,10,16,48,115,40,25,39,268,39,23,58,175,37,20,71,336,28*78 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,31,223,23,27,19,284,25*7D +$GPGSV,3,3,10,11,06,338,24,03,14,055,22*76 +$GPRMC,222531.000,A,2734.78918,S,15305.72691,E,35.9,144.5,030308,11.2,W,A*0A +$GPVTG,144.5,T,155.7,M,35.9,N,66.4,K,A*2A +$GPGGA,222532.000,2734.79737,S,15305.73347,E,1,06,1.5,66.0,M,39.2,M,,*74 +$GPGLL,2734.79737,S,15305.73347,E,222532.000,A,A*4B +$GPGSA,A,3,16,25,23,20,27,03,,,,,,,2.5,1.5,2.0*36 +$GPGST,222532.000,11.0,6.8,38.7,1.2,6.3,35.3,58.4*69 +$GPGSV,3,1,10,16,48,115,40,25,39,268,39,23,58,175,36,20,71,336,28*79 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,31,223,24,27,19,284,23*7C +$GPGSV,3,3,10,11,06,338,24,03,14,055,30*75 +$GPRMC,222532.000,A,2734.79737,S,15305.73347,E,36.1,144.5,030308,11.2,W,A*0F +$GPVTG,144.5,T,155.7,M,36.1,N,66.9,K,A*2C +$GPGGA,222533.000,2734.80571,S,15305.74004,E,1,06,4.1,66.1,M,39.2,M,,*70 +$GPGLL,2734.80571,S,15305.74004,E,222533.000,A,A*4F +$GPGSA,A,3,16,25,23,27,11,03,,,,,,,8.3,4.1,7.3*3F +$GPGST,222533.000,9.4,6.1,45.5,0.4,5.6,41.6,69.5*50 +$GPGSV,3,1,10,16,48,115,40,25,39,268,39,23,58,175,37,20,71,336,28*78 +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,31,223,24,27,19,284,25*7C +$GPGSV,3,3,10,11,06,338,22,03,14,055,25*77 +$GPRMC,222533.000,A,2734.80571,S,15305.74004,E,36.6,145.0,030308,11.2,W,A*08 +$GPVTG,145.0,T,156.2,M,36.6,N,67.7,K,A*26 +$GPGGA,222534.000,2734.81441,S,15305.74656,E,1,06,1.8,65.2,M,39.2,M,,*79 +$GPGLL,2734.81441,S,15305.74656,E,222534.000,A,A*4A +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222534.000,20.2,5.8,45.7,1.7,5.4,41.7,71.3*6C +$GPGSV,3,1,10,16,48,115,40,25,39,268,38,23,58,175,37,20,71,336,28*79 +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,31,223,25,27,19,284,25*7D +$GPGSV,3,3,10,11,06,338,22,03,14,055,31*72 +$GPRMC,222534.000,A,2734.81441,S,15305.74656,E,37.6,146.2,030308,11.2,W,A*0D +$GPVTG,146.2,T,157.5,M,37.6,N,69.7,K,A*2E +$GPGGA,222535.000,2734.82349,S,15305.75307,E,1,05,1.9,63.5,M,39.2,M,,*77 +$GPGLL,2734.82349,S,15305.75307,E,222535.000,A,A*47 +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.6,1.9,3.1*3D +$GPGST,222535.000,27.6,7.0,40.6,3.1,6.7,37.1,68.4*6C +$GPGSV,3,1,10,16,48,115,40,25,39,268,36,23,58,175,37,20,71,336,28*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,31,223,25,27,19,284,23*78 +$GPGSV,3,3,10,11,06,338,22,03,14,055,26*74 +$GPRMC,222535.000,A,2734.82349,S,15305.75307,E,38.7,147.3,030308,11.2,W,A*0E +$GPVTG,147.3,T,158.6,M,38.7,N,71.7,K,A*25 +$GPGGA,222536.000,2734.83215,S,15305.75969,E,1,05,1.7,63.5,M,39.2,M,,*71 +$GPGLL,2734.83215,S,15305.75969,E,222536.000,A,A*4F +$GPGSA,A,3,16,25,23,20,03,,,,,,,,2.9,1.7,2.4*39 +$GPGST,222536.000,7.9,6.3,97.2,3.9,8.3,88.7,161.0*62 +$GPGSV,3,1,10,16,48,115,40,25,39,268,37,23,58,175,36,20,71,336,28*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,20,13,31,223,25,27,19,284,23*78 +$GPGSV,3,3,10,11,06,338,22,03,14,055,26*74 +$GPRMC,222536.000,A,2734.83215,S,15305.75969,E,37.6,145.6,030308,11.2,W,A*0F +$GPVTG,145.6,T,156.8,M,37.6,N,69.7,K,A*25 +$GPGGA,222537.000,2734.84076,S,15305.76655,E,1,05,1.7,63.5,M,39.2,M,,*73 +$GPGLL,2734.84076,S,15305.76655,E,222537.000,A,A*4D +$GPGSA,A,3,16,25,23,20,03,,,,,,,,2.9,1.7,2.4*39 +$GPGST,222537.000,16.0,7.8,110.8,2.1,8.0,101.2,209.1*57 +$GPGSV,3,1,10,16,48,115,39,25,39,268,36,23,58,175,34,20,71,336,28*7A +$GPGSV,3,2,10,19,02,028,,04,06,241,22,13,31,223,25,27,19,284,23*7A +$GPGSV,3,3,10,11,06,338,22,03,14,055,25*77 +$GPRMC,222537.000,A,2734.84076,S,15305.76655,E,37.9,144.6,030308,11.2,W,A*03 +$GPVTG,144.6,T,155.8,M,37.9,N,70.3,K,A*24 +$GPGGA,222538.000,2734.84945,S,15305.77356,E,1,05,1.9,63.5,M,39.2,M,,*7C +$GPGLL,2734.84945,S,15305.77356,E,222538.000,A,A*4C +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.6,1.9,3.1*3D +$GPGST,222538.000,13.1,8.0,61.7,1.6,7.5,56.4,113.0*51 +$GPGSV,3,1,10,16,48,115,40,25,39,268,37,23,58,175,32,20,71,336,*79 +$GPGSV,3,2,10,19,02,028,,04,06,241,22,13,31,223,25,27,19,284,23*7A +$GPGSV,3,3,10,11,06,338,22,03,14,055,28*7A +$GPRMC,222538.000,A,2734.84945,S,15305.77356,E,38.4,144.2,030308,11.2,W,A*04 +$GPVTG,144.2,T,155.4,M,38.4,N,71.1,K,A*2D +$GPGGA,222539.000,2734.85792,S,15305.78022,E,1,05,1.9,63.5,M,39.2,M,,*77 +$GPGLL,2734.85792,S,15305.78022,E,222539.000,A,A*47 +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.6,1.9,3.1*3D +$GPGST,222539.000,6.4,7.5,72.7,1.5,7.1,66.5,137.2*68 +$GPGSV,3,1,10,16,48,115,40,25,39,268,38,23,58,175,32,20,71,336,*76 +$GPGSV,3,2,10,19,02,028,,04,06,241,22,13,31,223,25,27,19,284,23*7A +$GPGSV,3,3,10,11,06,338,22,03,14,055,28*7A +$GPRMC,222539.000,A,2734.85792,S,15305.78022,E,37.1,144.9,030308,11.2,W,A*0E +$GPVTG,144.9,T,156.1,M,37.1,N,68.7,K,A*24 +$GPGGA,222540.000,2734.86604,S,15305.78646,E,1,05,4.4,63.5,M,39.2,M,,*78 +$GPGLL,2734.86604,S,15305.78646,E,222540.000,A,A*40 +$GPGSA,A,3,16,25,23,27,11,,,,,,,,9.3,4.4,8.2*36 +$GPGST,222540.000,13.6,8.3,67.7,1.8,7.8,61.9,111.1*55 +$GPGSV,3,1,10,16,48,115,40,25,39,268,38,23,58,175,32,20,71,336,*76 +$GPGSV,3,2,10,19,02,028,,04,06,241,26,13,31,223,22,27,19,284,22*78 +$GPGSV,3,3,10,11,06,338,20,03,14,055,28*78 +$GPRMC,222540.000,A,2734.86604,S,15305.78646,E,35.3,145.6,030308,11.2,W,A*07 +$GPVTG,145.6,T,156.8,M,35.3,N,65.4,K,A*2D +$GPGGA,222541.000,2734.87421,S,15305.79222,E,1,06,1.8,63.5,M,39.2,M,,*70 +$GPGLL,2734.87421,S,15305.79222,E,222541.000,A,A*42 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222541.000,11.7,33.3,8.1,87.4,7.5,30.4,54.6*51 +$GPGSV,3,1,10,16,48,115,39,25,39,268,33,23,58,175,36,20,71,336,*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,26,13,31,223,22,27,19,284,22*78 +$GPGSV,3,3,10,11,06,338,20,03,14,055,26*76 +$GPRMC,222541.000,A,2734.87421,S,15305.79222,E,34.6,147.7,030308,11.2,W,A*02 +$GPVTG,147.7,T,158.9,M,34.6,N,64.1,K,A*21 +$GPGGA,222542.000,2734.88135,S,15305.79765,E,1,06,1.8,63.5,M,39.2,M,,*7A +$GPGLL,2734.88135,S,15305.79765,E,222542.000,A,A*48 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222542.000,23.5,7.9,53.0,0.2,7.2,48.5,78.4*6F +$GPGSV,3,1,10,16,48,115,40,25,39,268,36,23,58,175,35,20,71,336,*7F +$GPGSV,3,2,10,19,02,028,,04,06,241,27,13,31,223,23,27,19,284,25*7F +$GPGSV,3,3,10,11,06,338,20,03,14,055,26*76 +$GPRMC,222542.000,A,2734.88135,S,15305.79765,E,31.0,145.8,030308,11.2,W,A*06 +$GPVTG,145.8,T,157.0,M,31.0,N,57.4,K,A*2C +$GPGGA,222543.000,2734.88798,S,15305.80287,E,1,07,1.2,63.0,M,39.2,M,,*7B +$GPGLL,2734.88798,S,15305.80287,E,222543.000,A,A*47 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222543.000,18.8,6.7,28.4,0.5,6.1,26.0,41.8*62 +$GPGSV,3,1,10,16,48,115,40,25,39,268,39,23,58,175,35,20,71,336,21*73 +$GPGSV,3,2,10,19,02,028,,04,06,241,37,13,31,223,22,27,19,284,24*7E +$GPGSV,3,3,10,11,06,338,20,03,14,055,32*73 +$GPRMC,222543.000,A,2734.88798,S,15305.80287,E,29.0,144.8,030308,11.2,W,A*01 +$GPVTG,144.8,T,156.0,M,29.0,N,53.8,K,A*2D +$GPGGA,222544.000,2734.89328,S,15305.80767,E,1,06,1.8,62.9,M,39.2,M,,*7A +$GPGLL,2734.89328,S,15305.80767,E,222544.000,A,A*45 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222544.000,14.9,35.2,5.8,89.5,5.4,32.2,52.6*52 +$GPGSV,3,1,10,16,48,115,43,25,39,268,40,23,58,175,25,20,71,336,21*7F +$GPGSV,3,2,10,19,02,028,,04,06,241,28,13,31,223,30,27,19,284,29*7E +$GPGSV,3,3,10,11,06,338,20,03,14,055,33*72 +$GPRMC,222544.000,A,2734.89328,S,15305.80767,E,24.5,140.9,030308,11.2,W,A*0E +$GPVTG,140.9,T,152.1,M,24.5,N,45.3,K,A*29 +$GPGGA,222545.000,2734.89633,S,15305.81084,E,1,05,1.9,62.9,M,39.2,M,,*7D +$GPGLL,2734.89633,S,15305.81084,E,222545.000,A,A*40 +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.6,1.9,3.1*3D +$GPGST,222545.000,19.5,6.0,33.0,1.0,5.5,30.2,52.4*69 +$GPGSV,3,1,10,16,48,115,41,25,39,268,34,23,58,175,29,20,71,336,30*72 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,31,223,29,27,19,284,30*73 +$GPGSV,3,3,10,11,06,338,20,03,14,055,30*71 +$GPRMC,222545.000,A,2734.89633,S,15305.81084,E,14.6,136.6,030308,11.2,W,A*05 +$GPVTG,136.6,T,147.8,M,14.6,N,27.0,K,A*2D +$GPGGA,222546.000,2734.89236,S,15305.81130,E,1,06,1.3,62.6,M,39.2,M,,*77 +$GPGLL,2734.89236,S,15305.81130,E,222546.000,A,A*4C +$GPGSA,A,3,16,25,23,20,13,03,,,,,,,2.3,1.3,1.9*3B +$GPGST,222546.000,11.5,5.6,15.6,0.9,5.2,14.3,26.4*6E +$GPGSV,3,1,10,16,48,115,35,25,39,268,40,23,58,175,41,20,71,336,38*74 +$GPGSV,3,2,10,19,02,028,,04,06,241,26,13,31,223,33,27,19,284,26*7C +$GPGSV,3,3,10,11,06,338,20,03,14,055,28*78 +$GPRMC,222546.000,A,2734.89236,S,15305.81130,E,16.9,2.1,030308,11.2,W,A*05 +$GPVTG,2.1,T,13.3,M,16.9,N,31.2,K,A*1F +$GPGGA,222547.000,2734.89429,S,15305.81239,E,1,05,2.3,62.5,M,39.2,M,,*77 +$GPGLL,2734.89429,S,15305.81239,E,222547.000,A,A*4F +$GPGSA,A,3,16,23,13,27,03,,,,,,,,4.6,2.3,3.9*39 +$GPGST,222547.000,11.4,38.3,9.7,69.8,14.7,33.0,49.2*6B +$GPGSV,3,1,10,16,48,115,32,25,39,268,37,23,58,175,42,20,71,336,37*7F +$GPGSV,3,2,10,19,02,028,,04,06,241,26,13,31,223,36,27,19,284,29*76 +$GPGSV,3,3,10,11,06,338,20,03,14,055,34*75 +$GPRMC,222547.000,A,2734.89429,S,15305.81239,E,8.4,154.5,030308,11.2,W,A*32 +$GPVTG,154.5,T,165.7,M,8.4,N,15.6,K,A*1D +$GPGGA,222548.000,2734.89474,S,15305.81253,E,1,07,1.2,62.0,M,39.2,M,,*79 +$GPGLL,2734.89474,S,15305.81253,E,222548.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222548.000,11.0,12.3,7.9,86.0,7.3,11.3,20.6*5F +$GPGSV,3,1,10,16,48,115,34,25,39,268,36,23,58,175,42,20,71,336,38*77 +$GPGSV,3,2,10,19,02,028,,04,06,241,25,13,31,223,36,27,19,284,29*75 +$GPGSV,3,3,10,11,06,338,20,03,14,055,33*72 +$GPRMC,222548.000,A,2734.89474,S,15305.81253,E,0.3,353.0,030308,11.2,W,A*36 +$GPVTG,353.0,T,4.3,M,0.3,N,0.5,K,A*27 +$GPGGA,222549.000,2734.89490,S,15305.81265,E,1,04,2.0,61.8,M,39.2,M,,*7E +$GPGLL,2734.89490,S,15305.81265,E,222549.000,A,A*4A +$GPGSA,A,3,25,23,13,03,,,,,,,,,3.9,2.0,3.3*3D +$GPGST,222549.000,17.0,16.1,8.8,81.3,8.3,14.6,29.3*57 +$GPGSV,3,1,11,16,48,115,33,25,39,268,37,23,58,175,42,20,71,336,36*7E +$GPGSV,3,2,11,19,02,028,,04,06,241,25,13,31,223,35,27,19,284,30*7F +$GPGSV,3,3,11,11,06,338,20,01,,,21,03,14,055,33*71 +$GPRMC,222549.000,A,2734.89490,S,15305.81265,E,0.2,330.7,030308,11.2,W,A*3B +$GPVTG,330.7,T,341.9,M,0.2,N,0.3,K,A*2A +$GPGGA,222550.000,2734.89526,S,15305.81278,E,1,04,2.6,61.7,M,39.2,M,,*7F +$GPGLL,2734.89526,S,15305.81278,E,222550.000,A,A*42 +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.1,2.6,5.6*31 +$GPGST,222550.000,13.4,12.4,27.3,43.1,18.9,19.8,52.9*5A +$GPGSV,3,1,11,16,48,115,30,25,39,268,38,23,58,175,42,20,71,336,37*73 +$GPGSV,3,2,11,19,02,028,,04,06,241,25,13,31,223,36,27,19,284,31*7D +$GPGSV,3,3,11,11,06,338,,01,,,21,03,14,055,32*72 +$GPRMC,222550.000,A,2734.89526,S,15305.81278,E,0.1,350.7,030308,11.2,W,A*36 +$GPVTG,350.7,T,1.9,M,0.1,N,0.2,K,A*29 +$GPGGA,222551.000,2734.89528,S,15305.81279,E,1,05,2.3,61.7,M,39.2,M,,*75 +$GPGLL,2734.89528,S,15305.81279,E,222551.000,A,A*4C +$GPGSA,A,3,16,23,13,27,03,,,,,,,,4.6,2.3,3.9*39 +$GPGST,222551.000,13.7,31.0,11.1,60.5,16.5,25.2,39.3*5F +$GPGSV,3,1,11,16,48,115,30,25,39,268,39,23,58,175,41,20,71,336,35*73 +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,31,223,36,27,19,284,31*7B +$GPGSV,3,3,11,11,06,338,,01,,,20,03,14,055,30*71 +$GPRMC,222551.000,A,2734.89528,S,15305.81279,E,0.1,345.0,030308,11.2,W,A*3B +$GPVTG,345.0,T,356.2,M,0.1,N,0.2,K,A*20 +$GPGGA,222552.000,2734.89550,S,15305.81288,E,1,05,2.1,61.7,M,39.2,M,,*75 +$GPGLL,2734.89550,S,15305.81288,E,222552.000,A,A*4E +$GPGSA,A,3,16,25,23,13,27,,,,,,,,4.7,2.1,4.2*32 +$GPGST,222552.000,11.7,11.5,20.8,20.0,11.8,18.2,39.1*55 +$GPGSV,3,1,11,16,48,115,31,25,39,268,40,23,58,175,42,20,71,336,35*7F +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,31,223,38,27,19,284,31*75 +$GPGSV,3,3,11,11,06,338,,01,,,20,03,14,055,30*71 +$GPRMC,222552.000,A,2734.89550,S,15305.81288,E,0.1,11.2,030308,11.2,W,A*09 +$GPVTG,11.2,T,22.5,M,0.1,N,0.2,K,A*27 +$GPGGA,222553.000,2734.89573,S,15305.81294,E,1,05,2.1,61.5,M,39.2,M,,*7A +$GPGLL,2734.89573,S,15305.81294,E,222553.000,A,A*43 +$GPGSA,A,3,16,25,23,13,27,,,,,,,,4.7,2.1,4.2*32 +$GPGST,222553.000,9.8,10.3,17.6,19.1,10.4,15.6,33.7*6C +$GPGSV,3,1,10,16,48,115,29,25,39,268,38,23,58,175,41,20,71,336,37*79 +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,31,223,39,27,19,284,30*74 +$GPGSV,3,3,10,11,06,338,,03,14,055,29*7B +$GPRMC,222553.000,A,2734.89573,S,15305.81294,E,0.1,351.8,030308,11.2,W,A*39 +$GPVTG,351.8,T,3.0,M,0.1,N,0.2,K,A*2C +$GPGGA,222554.000,2734.89591,S,15305.81298,E,1,04,2.6,61.4,M,39.2,M,,*7A +$GPGLL,2734.89591,S,15305.81298,E,222554.000,A,A*44 +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.1,2.6,5.6*31 +$GPGST,222554.000,16.9,10.4,17.8,12.8,10.0,16.1,37.3*5F +$GPGSV,3,1,10,16,48,115,32,25,39,268,38,23,58,175,41,20,71,336,36*72 +$GPGSV,3,2,10,19,02,028,,04,06,241,23,13,31,223,38,27,19,284,31*74 +$GPGSV,3,3,10,11,06,338,,03,14,055,26*74 +$GPRMC,222554.000,A,2734.89591,S,15305.81298,E,0.1,334.9,030308,11.2,W,A*3C +$GPVTG,334.9,T,346.1,M,0.1,N,0.2,K,A*2D +$GPGGA,222555.000,2734.89607,S,15305.81301,E,1,04,2.6,61.2,M,39.2,M,,*70 +$GPGLL,2734.89607,S,15305.81301,E,222555.000,A,A*48 +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.1,2.6,5.6*31 +$GPGST,222555.000,14.4,11.9,23.3,40.8,16.2,17.6,44.5*56 +$GPGSV,3,1,11,16,48,115,32,25,39,268,37,23,58,175,40,20,71,336,38*73 +$GPGSV,3,2,11,19,02,028,,04,06,241,23,13,31,223,37,27,19,284,30*7B +$GPGSV,3,3,11,11,06,338,,01,,,20,03,14,055,25*75 +$GPRMC,222555.000,A,2734.89607,S,15305.81301,E,0.1,6.2,030308,11.2,W,A*39 +$GPVTG,6.2,T,17.4,M,0.1,N,0.2,K,A*16 +$GPGGA,222556.000,2734.89612,S,15305.81301,E,1,04,2.6,61.1,M,39.2,M,,*74 +$GPGLL,2734.89612,S,15305.81301,E,222556.000,A,A*4F +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.1,2.6,5.6*31 +$GPGST,222556.000,12.4,15.8,24.1,4.1,14.5,22.0,39.9*69 +$GPGSV,3,1,11,16,48,115,33,25,39,268,38,23,58,174,41,20,71,336,38*7D +$GPGSV,3,2,11,19,02,028,,04,06,242,23,13,31,223,38,27,19,284,32*75 +$GPGSV,3,3,11,11,06,338,,01,,,20,03,14,055,28*78 +$GPRMC,222556.000,A,2734.89612,S,15305.81301,E,0.1,21.8,030308,11.2,W,A*01 +$GPVTG,21.8,T,33.0,M,0.1,N,0.2,K,A*2B +$GPGGA,222557.000,2734.89635,S,15305.81337,E,1,05,2.1,61.0,M,39.2,M,,*72 +$GPGLL,2734.89635,S,15305.81337,E,222557.000,A,A*4E +$GPGSA,A,3,16,25,23,13,27,,,,,,,,4.7,2.1,4.2*32 +$GPGST,222557.000,10.3,13.0,15.0,5.2,11.9,13.7,32.7*6B +$GPGSV,3,1,10,16,48,115,33,25,39,268,38,23,58,174,41,20,71,336,36*72 +$GPGSV,3,2,10,19,02,028,,04,06,242,23,13,31,223,39,27,19,284,28*7E +$GPGSV,3,3,10,11,06,338,,03,14,055,31*72 +$GPRMC,222557.000,A,2734.89635,S,15305.81337,E,1.2,96.1,030308,11.2,W,A*07 +$GPVTG,96.1,T,107.3,M,1.2,N,2.2,K,A*1B +$GPGGA,222558.000,2734.89638,S,15305.81517,E,1,06,1.8,60.6,M,39.2,M,,*7A +$GPGLL,2734.89638,S,15305.81517,E,222558.000,A,A*48 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222558.000,18.6,12.9,7.5,72.4,7.5,11.4,21.9*57 +$GPGSV,3,1,10,16,48,115,39,25,39,268,38,23,58,174,37,20,71,336,26*78 +$GPGSV,3,2,10,19,02,028,,04,06,242,23,13,31,223,34,27,19,284,29*72 +$GPGSV,3,3,10,11,06,338,,03,14,055,30*73 +$GPRMC,222558.000,A,2734.89638,S,15305.81517,E,5.6,82.0,030308,11.2,W,A*05 +$GPVTG,82.0,T,93.2,M,5.6,N,10.3,K,A*10 +$GPGGA,222559.000,2734.89631,S,15305.81911,E,1,05,2.2,60.5,M,39.2,M,,*71 +$GPGLL,2734.89631,S,15305.81911,E,222559.000,A,A*4A +$GPGSA,A,3,16,25,23,20,27,,,,,,,,3.6,2.2,2.9*3A +$GPGST,222559.000,17.0,15.1,33.1,15.1,15.5,29.4,59.0*59 +$GPGSV,3,1,10,16,48,115,34,25,39,268,35,23,58,174,30,20,71,336,29*70 +$GPGSV,3,2,10,19,02,028,,04,06,242,23,13,31,223,35,27,19,284,28*72 +$GPGSV,3,3,10,11,06,338,,03,14,055,27*75 +$GPRMC,222559.000,A,2734.89631,S,15305.81911,E,12.5,87.6,030308,11.2,W,A*31 +$GPVTG,87.6,T,98.8,M,12.5,N,23.2,K,A*26 +$GPGGA,222600.000,2734.89436,S,15305.82359,E,1,06,1.8,61.2,M,39.2,M,,*72 +$GPGLL,2734.89436,S,15305.82359,E,222600.000,A,A*45 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.5,1.8,3.1*3A +$GPGST,222600.000,14.4,14.9,6.9,79.1,6.7,13.4,28.4*57 +$GPGSV,3,1,10,16,48,115,37,25,39,268,36,23,58,174,29,20,71,336,33*73 +$GPGSV,3,2,10,19,02,028,,04,06,242,23,13,31,223,39,27,19,284,28*7E +$GPGSV,3,3,10,11,06,338,,03,14,055,28*7A +$GPRMC,222600.000,A,2734.89436,S,15305.82359,E,15.9,62.5,030308,11.2,W,A*3D +$GPVTG,62.5,T,73.7,M,15.9,N,29.5,K,A*22 +$GPGGA,222601.000,2734.89190,S,15305.82850,E,1,06,1.8,60.5,M,39.2,M,,*7E +$GPGLL,2734.89190,S,15305.82850,E,222601.000,A,A*4F +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.6,1.8,3.1*39 +$GPGST,222601.000,11.5,13.4,6.1,78.5,6.0,12.0,24.9*56 +$GPGSV,3,1,10,16,48,115,40,25,39,268,27,23,58,174,35,20,71,336,28*74 +$GPGSV,3,2,10,19,02,028,,04,06,242,,13,31,223,39,27,19,284,27*70 +$GPGSV,3,3,10,11,06,338,,03,14,055,23*71 +$GPRMC,222601.000,A,2734.89190,S,15305.82850,E,18.0,58.9,030308,11.2,W,A*36 +$GPVTG,58.9,T,70.1,M,18.0,N,33.4,K,A*2C +$GPGGA,222602.000,2734.88904,S,15305.83361,E,1,05,1.6,60.0,M,39.2,M,,*79 +$GPGLL,2734.88904,S,15305.83361,E,222602.000,A,A*40 +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222602.000,11.3,17.1,6.5,54.9,10.2,13.2,18.6*62 +$GPGSV,3,1,10,16,48,115,27,25,39,268,29,23,58,174,33,20,71,336,33*77 +$GPGSV,3,2,10,19,02,028,,04,06,242,,13,31,223,35,27,19,284,32*78 +$GPGSV,3,3,10,11,06,338,,03,14,055,24*76 +$GPRMC,222602.000,A,2734.88904,S,15305.83361,E,19.8,55.1,030308,11.2,W,A*35 +$GPVTG,55.1,T,66.3,M,19.8,N,36.7,K,A*23 +$GPGGA,222603.000,2734.88556,S,15305.83944,E,1,04,3.8,58.8,M,39.2,M,,*70 +$GPGLL,2734.88556,S,15305.83944,E,222603.000,A,A*47 +$GPGSA,A,3,25,23,20,27,,,,,,,,,6.5,3.8,5.2*3C +$GPGST,222603.000,12.6,48.6,15.6,66.9,41.3,21.9,62.5*59 +$GPGSV,3,1,10,16,48,115,23,25,39,268,29,23,58,174,31,20,71,337,37*74 +$GPGSV,3,2,10,19,02,028,,04,06,242,,13,31,223,34,27,19,284,26*7C +$GPGSV,3,3,10,11,06,338,,03,14,055,28*7A +$GPRMC,222603.000,A,2734.88556,S,15305.83944,E,22.7,54.4,030308,11.2,W,A*31 +$GPVTG,54.4,T,65.6,M,22.7,N,42.1,K,A*23 +$GPGGA,222604.000,2734.88238,S,15305.84546,E,1,04,4.4,57.8,M,39.2,M,,*75 +$GPGLL,2734.88238,S,15305.84546,E,222604.000,A,A*46 +$GPGSA,A,3,25,20,13,27,,,,,,,,,7.2,4.4,5.7*37 +$GPGST,222604.000,10.4,46.8,10.9,81.3,42.4,11.8,57.5*57 +$GPGSV,3,1,10,16,48,115,27,25,39,268,32,23,58,174,32,20,71,337,37*79 +$GPGSV,3,2,10,19,02,028,,04,06,242,,13,31,223,34,27,19,284,34*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,29*7B +$GPRMC,222604.000,A,2734.88238,S,15305.84546,E,23.3,54.5,030308,11.2,W,A*34 +$GPVTG,54.5,T,65.7,M,23.3,N,43.2,K,A*24 +$GPGGA,222605.000,2734.87917,S,15305.85182,E,1,04,4.4,56.6,M,39.2,M,,*7F +$GPGLL,2734.87917,S,15305.85182,E,222605.000,A,A*43 +$GPGSA,A,3,25,20,13,27,,,,,,,,,7.2,4.4,5.7*37 +$GPGST,222605.000,14.3,40.3,10.1,81.5,36.5,10.7,49.8*58 +$GPGSV,3,1,10,16,48,115,24,25,39,268,32,23,58,174,33,20,71,337,37*7B +$GPGSV,3,2,10,19,02,028,,04,06,242,20,13,31,223,35,27,19,284,32*7A +$GPGSV,3,3,10,11,06,338,,03,14,055,26*74 +$GPRMC,222605.000,A,2734.87917,S,15305.85182,E,24.5,55.0,030308,11.2,W,A*34 +$GPVTG,55.0,T,66.2,M,24.5,N,45.3,K,A*20 +$GPGGA,222606.000,2734.87588,S,15305.85846,E,1,05,3.6,55.8,M,39.2,M,,*7E +$GPGLL,2734.87588,S,15305.85846,E,222606.000,A,A*4B +$GPGSA,A,3,25,23,20,13,27,,,,,,,,6.3,3.6,5.2*36 +$GPGST,222606.000,11.7,30.4,8.7,77.7,27.2,9.8,40.6*59 +$GPGSV,3,1,10,16,48,115,24,25,39,268,31,23,58,174,32,20,71,337,34*7A +$GPGSV,3,2,10,19,02,029,,04,06,242,20,13,31,223,35,27,19,284,34*7D +$GPGSV,3,3,10,11,06,338,,03,14,055,24*76 +$GPRMC,222606.000,A,2734.87588,S,15305.85846,E,25.3,55.9,030308,11.2,W,A*32 +$GPVTG,55.9,T,67.1,M,25.3,N,46.9,K,A*25 +$GPGGA,222607.000,2734.87218,S,15305.86543,E,1,06,1.8,55.5,M,39.2,M,,*78 +$GPGLL,2734.87218,S,15305.86543,E,222607.000,A,A*4F +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.6,1.8,3.1*39 +$GPGST,222607.000,11.2,13.8,8.5,86.1,7.8,12.6,27.3*52 +$GPGSV,3,1,10,16,48,115,29,25,39,268,26,23,58,174,34,20,71,337,32*71 +$GPGSV,3,2,10,19,02,029,,04,06,242,27,13,31,223,36,27,19,284,30*7D +$GPGSV,3,3,10,11,06,338,,03,14,055,24*76 +$GPRMC,222607.000,A,2734.87218,S,15305.86543,E,26.0,57.6,030308,11.2,W,A*3B +$GPVTG,57.6,T,68.8,M,26.0,N,48.1,K,A*28 +$GPGGA,222608.000,2734.86867,S,15305.87251,E,1,06,1.8,55.1,M,39.2,M,,*75 +$GPGLL,2734.86867,S,15305.87251,E,222608.000,A,A*46 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.6,1.8,3.1*39 +$GPGST,222608.000,15.1,15.8,7.1,68.8,8.0,13.6,36.7*5C +$GPGSV,3,1,10,16,48,115,39,25,39,268,28,23,58,174,35,20,71,337,30*7D +$GPGSV,3,2,10,19,02,029,,04,06,242,27,13,31,223,40,27,19,284,28*75 +$GPGSV,3,3,10,11,06,338,,03,14,055,28*7A +$GPRMC,222608.000,A,2734.86867,S,15305.87251,E,25.9,60.7,030308,11.2,W,A*3D +$GPVTG,60.7,T,71.9,M,25.9,N,47.9,K,A*29 +$GPGGA,222609.000,2734.86555,S,15305.87973,E,1,06,1.8,54.7,M,39.2,M,,*74 +$GPGLL,2734.86555,S,15305.87973,E,222609.000,A,A*40 +$GPGSA,A,3,16,25,23,13,27,03,,,,,,,3.6,1.8,3.1*39 +$GPGST,222609.000,10.9,10.9,5.1,85.4,4.7,10.0,22.0*55 +$GPGSV,3,1,10,16,48,116,34,25,39,268,39,23,58,174,29,20,71,337,33*7D +$GPGSV,3,2,10,19,02,029,,04,06,242,24,13,31,223,42,27,19,284,23*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,26*74 +$GPRMC,222609.000,A,2734.86555,S,15305.87973,E,25.7,64.3,030308,11.2,W,A*35 +$GPVTG,64.3,T,75.6,M,25.7,N,47.5,K,A*20 +$GPGGA,222610.000,2734.86253,S,15305.88695,E,1,05,1.9,54.1,M,39.2,M,,*71 +$GPGLL,2734.86253,S,15305.88695,E,222610.000,A,A*41 +$GPGSA,A,3,16,25,23,13,03,,,,,,,,3.7,1.9,3.1*3C +$GPGST,222610.000,11.1,14.6,7.4,64.7,8.3,12.4,28.7*57 +$GPGSV,3,1,10,16,48,116,29,25,39,268,42,23,58,174,28,20,71,337,32*7D +$GPGSV,3,2,10,19,02,029,,04,06,242,24,13,31,223,42,27,19,284,23*7F +$GPGSV,3,3,10,11,06,338,,03,14,055,24*76 +$GPRMC,222610.000,A,2734.86253,S,15305.88695,E,25.3,65.0,030308,11.2,W,A*32 +$GPVTG,65.0,T,76.3,M,25.3,N,46.8,K,A*2C +$GPGGA,222611.000,2734.85924,S,15305.89387,E,1,05,2.2,53.4,M,39.2,M,,*75 +$GPGLL,2734.85924,S,15305.89387,E,222611.000,A,A*4F +$GPGSA,A,3,16,25,23,20,13,,,,,,,,5.3,2.2,4.8*39 +$GPGST,222611.000,17.7,8.4,21.7,17.4,9.4,19.0,57.8*57 +$GPGSV,3,1,10,16,48,116,39,25,39,268,32,23,58,174,35,20,71,337,26*72 +$GPGSV,3,2,10,19,02,029,,04,06,242,31,13,31,223,39,27,19,284,24*70 +$GPGSV,3,3,10,11,06,338,,03,14,055,26*74 +$GPRMC,222611.000,A,2734.85924,S,15305.89387,E,24.9,61.4,030308,11.2,W,A*37 +$GPVTG,61.4,T,72.6,M,24.9,N,46.1,K,A*2F +$GPGGA,222612.000,2734.85516,S,15305.90007,E,1,07,1.2,53.3,M,39.2,M,,*7E +$GPGLL,2734.85516,S,15305.90007,E,222612.000,A,A*42 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222612.000,15.5,16.3,8.2,77.8,8.0,14.7,27.8*50 +$GPGSV,3,1,10,16,48,116,29,25,39,268,29,23,58,174,30,20,71,337,34*7F +$GPGSV,3,2,10,19,02,029,,04,06,242,27,13,31,223,35,27,19,284,28*77 +$GPGSV,3,3,10,11,06,338,,03,14,055,25*77 +$GPRMC,222612.000,A,2734.85516,S,15305.90007,E,24.5,53.1,030308,11.2,W,A*32 +$GPVTG,53.1,T,64.3,M,24.5,N,45.4,K,A*23 +$GPGGA,222613.000,2734.85043,S,15305.90565,E,1,05,1.9,53.2,M,39.2,M,,*73 +$GPGLL,2734.85043,S,15305.90565,E,222613.000,A,A*47 +$GPGSA,A,3,16,25,20,13,27,,,,,,,,3.7,1.9,3.2*3A +$GPGST,222613.000,21.1,11.0,20.9,21.8,11.7,18.1,48.5*55 +$GPGSV,3,1,10,16,48,116,30,25,39,268,32,23,58,174,24,20,71,337,36*7A +$GPGSV,3,2,10,19,02,029,,04,06,242,22,13,31,223,35,27,19,284,29*73 +$GPGSV,3,3,10,11,06,338,,03,14,055,29*7B +$GPRMC,222613.000,A,2734.85043,S,15305.90565,E,24.9,45.4,030308,11.2,W,A*39 +$GPVTG,45.4,T,56.6,M,24.9,N,46.1,K,A*2F +$GPGGA,222614.000,2734.84523,S,15305.91064,E,1,05,1.9,53.2,M,39.2,M,,*73 +$GPGLL,2734.84523,S,15305.91064,E,222614.000,A,A*47 +$GPGSA,A,3,16,25,20,13,27,,,,,,,,3.7,1.9,3.2*3A +$GPGST,222614.000,18.8,16.8,28.3,28.1,18.2,24.0,43.4*54 +$GPGSV,3,1,10,16,48,116,27,25,39,268,30,23,58,174,32,20,71,337,35*7A +$GPGSV,3,2,10,19,02,029,,04,06,242,28,13,31,223,26,27,19,284,32*71 +$GPGSV,3,3,10,11,06,338,,03,14,055,30*73 +$GPRMC,222614.000,A,2734.84523,S,15305.91064,E,24.7,40.2,030308,11.2,W,A*34 +$GPVTG,40.2,T,51.4,M,24.7,N,45.7,K,A*22 +$GPGGA,222615.000,2734.84002,S,15305.91547,E,1,07,1.2,53.0,M,39.2,M,,*7B +$GPGLL,2734.84002,S,15305.91547,E,222615.000,A,A*44 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222615.000,19.7,18.9,7.9,71.0,8.8,16.5,18.9*52 +$GPGSV,3,1,10,16,48,116,25,25,39,268,26,23,58,174,35,20,71,337,34*79 +$GPGSV,3,2,10,19,02,029,,04,06,242,24,13,31,223,25,27,19,284,30*7C +$GPGSV,3,3,10,11,06,338,,03,14,055,29*7B +$GPRMC,222615.000,A,2734.84002,S,15305.91547,E,24.1,38.7,030308,11.2,W,A*3B +$GPVTG,38.7,T,49.9,M,24.1,N,44.7,K,A*2B +$GPGGA,222616.000,2734.83488,S,15305.92024,E,1,07,1.2,53.1,M,39.2,M,,*7B +$GPGLL,2734.83488,S,15305.92024,E,222616.000,A,A*45 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222616.000,18.1,15.8,11.2,70.8,10.8,14.1,19.9*51 +$GPGSV,3,1,10,16,48,116,27,25,39,268,29,23,58,174,34,20,71,337,30*71 +$GPGSV,3,2,10,19,02,029,,04,06,242,27,13,31,223,24,27,19,284,28*77 +$GPGSV,3,3,10,11,06,338,,03,14,055,32*71 +$GPRMC,222616.000,A,2734.83488,S,15305.92024,E,24.0,39.3,030308,11.2,W,A*3E +$GPVTG,39.3,T,50.5,M,24.0,N,44.5,K,A*29 +$GPGGA,222617.000,2734.82955,S,15305.92505,E,1,07,1.2,53.2,M,39.2,M,,*73 +$GPGLL,2734.82955,S,15305.92505,E,222617.000,A,A*4E +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222617.000,14.7,13.3,9.2,70.7,8.9,11.8,16.8*5B +$GPGSV,3,1,10,16,48,116,23,25,39,268,30,23,58,174,35,20,71,337,33*7F +$GPGSV,3,2,10,19,02,029,,04,06,242,25,13,31,223,25,27,19,284,26*7A +$GPGSV,3,3,10,11,06,338,,03,14,055,32*71 +$GPRMC,222617.000,A,2734.82955,S,15305.92505,E,24.7,38.8,030308,11.2,W,A*38 +$GPVTG,38.8,T,50.0,M,24.7,N,45.7,K,A*22 +$GPGGA,222618.000,2734.82405,S,15305.92991,E,1,07,1.2,53.5,M,39.2,M,,*72 +$GPGLL,2734.82405,S,15305.92991,E,222618.000,A,A*48 +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222618.000,13.7,14.7,7.8,77.2,7.6,13.2,24.3*54 +$GPGSV,3,1,10,16,48,116,27,25,39,268,30,23,58,174,36,20,71,337,32*79 +$GPGSV,3,2,10,19,02,029,,04,06,242,31,13,31,223,25,27,19,283,23*7D +$GPGSV,3,3,10,11,06,338,,03,14,056,32*72 +$GPRMC,222618.000,A,2734.82405,S,15305.92991,E,25.3,38.3,030308,11.2,W,A*30 +$GPVTG,38.3,T,49.5,M,25.3,N,46.8,K,A*2D +$GPGGA,222619.000,2734.81867,S,15305.93485,E,1,07,1.2,53.8,M,39.2,M,,*7C +$GPGLL,2734.81867,S,15305.93485,E,222619.000,A,A*4B +$GPGSA,A,3,16,25,23,20,13,27,03,,,,,,2.1,1.2,1.7*33 +$GPGST,222619.000,20.5,18.3,9.9,85.5,9.1,16.7,27.9*5A +$GPGSV,3,1,10,16,48,116,27,25,39,268,30,23,58,174,35,20,71,337,33*7B +$GPGSV,3,2,10,19,02,029,,04,06,242,29,13,31,223,23,27,19,283,23*72 +$GPGSV,3,3,10,11,06,338,,03,14,056,32*72 +$GPRMC,222619.000,A,2734.81867,S,15305.93485,E,25.3,39.2,030308,11.2,W,A*33 +$GPVTG,39.2,T,50.4,M,25.3,N,46.8,K,A*24 +$GPGGA,222620.000,2734.81344,S,15305.93979,E,1,05,1.6,53.8,M,39.2,M,,*74 +$GPGLL,2734.81344,S,15305.93979,E,222620.000,A,A*45 +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222620.000,18.2,14.7,21.1,9.8,19.1,13.7,29.8*64 +$GPGSV,3,1,10,16,48,116,26,25,39,268,30,23,58,174,33,20,71,337,34*7B +$GPGSV,3,2,10,19,02,029,,04,06,242,24,13,31,223,25,27,19,283,29*73 +$GPGSV,3,3,10,11,06,338,,03,14,056,33*73 +$GPRMC,222620.000,A,2734.81344,S,15305.93979,E,24.7,39.5,030308,11.2,W,A*3F +$GPVTG,39.5,T,50.7,M,24.7,N,45.8,K,A*26 +$GPGGA,222621.000,2734.80838,S,15305.94469,E,1,06,1.3,53.5,M,39.2,M,,*74 +$GPGLL,2734.80838,S,15305.94469,E,222621.000,A,A*4E +$GPGSA,A,3,16,25,23,20,13,03,,,,,,,2.3,1.3,1.9*3B +$GPGST,222621.000,14.6,11.8,13.4,39.2,11.7,11.4,21.8*5D +$GPGSV,3,1,10,16,48,116,25,25,39,268,31,23,58,174,33,20,71,337,37*7A +$GPGSV,3,2,10,19,03,029,,04,06,242,24,13,31,223,24,27,19,283,36*7D +$GPGSV,3,3,10,11,06,338,,03,14,056,32*72 +$GPRMC,222621.000,A,2734.80838,S,15305.94469,E,24.1,40.1,030308,11.2,W,A*38 +$GPVTG,40.1,T,51.3,M,24.1,N,44.7,K,A*21 +$GPGGA,222622.000,2734.80354,S,15305.94956,E,1,06,1.7,53.3,M,39.2,M,,*75 +$GPGLL,2734.80354,S,15305.94956,E,222622.000,A,A*4D +$GPGSA,A,3,16,25,23,20,13,27,,,,,,,3.3,1.7,2.9*3B +$GPGST,222622.000,13.2,10.2,17.1,41.6,12.5,13.2,30.8*59 +$GPGSV,3,1,10,16,48,116,26,25,39,268,31,23,58,174,26,20,71,337,39*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,24,13,31,223,28,27,19,283,36*71 +$GPGSV,3,3,10,11,06,338,,03,14,056,35*75 +$GPRMC,222622.000,A,2734.80354,S,15305.94956,E,23.6,41.3,030308,11.2,W,A*38 +$GPVTG,41.3,T,52.5,M,23.6,N,43.7,K,A*20 +$GPGGA,222623.000,2734.79878,S,15305.95470,E,1,05,1.9,52.8,M,39.2,M,,*78 +$GPGLL,2734.79878,S,15305.95470,E,222623.000,A,A*47 +$GPGSA,A,3,16,25,20,13,27,,,,,,,,3.7,1.9,3.2*3A +$GPGST,222623.000,14.7,24.8,16.6,50.3,19.9,18.6,39.3*5E +$GPGSV,3,1,11,16,48,116,24,25,39,268,32,23,58,174,24,20,71,337,38*70 +$GPGSV,3,2,11,19,03,029,,04,06,242,24,13,31,223,32,27,19,283,34*79 +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,34*7D +$GPRMC,222623.000,A,2734.79878,S,15305.95470,E,24.0,43.4,030308,11.2,W,A*36 +$GPVTG,43.4,T,54.6,M,24.0,N,44.4,K,A*25 +$GPGGA,222624.000,2734.79400,S,15305.96019,E,1,05,1.9,52.3,M,39.2,M,,*7F +$GPGLL,2734.79400,S,15305.96019,E,222624.000,A,A*4B +$GPGSA,A,3,16,25,20,27,03,,,,,,,,2.7,1.9,2.0*39 +$GPGST,222624.000,12.3,24.0,7.9,80.2,8.0,21.7,15.3*5C +$GPGSV,3,1,11,16,48,116,23,25,39,268,32,23,58,174,26,20,71,337,37*7A +$GPGSV,3,2,11,19,03,029,,04,06,242,24,13,31,223,35,27,19,283,25*7E +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,31*78 +$GPRMC,222624.000,A,2734.79400,S,15305.96019,E,24.7,45.3,030308,11.2,W,A*3C +$GPVTG,45.3,T,56.6,M,24.7,N,45.7,K,A*23 +$GPGGA,222625.000,2734.78953,S,15305.96595,E,1,05,1.9,51.8,M,39.2,M,,*7D +$GPGLL,2734.78953,S,15305.96595,E,222625.000,A,A*41 +$GPGSA,A,3,16,25,20,13,27,,,,,,,,3.7,1.9,3.2*3A +$GPGST,222625.000,24.0,12.2,19.9,37.5,14.2,16.0,36.1*57 +$GPGSV,3,1,11,16,48,116,30,25,39,268,32,23,58,174,23,20,71,337,37*7D +$GPGSV,3,2,11,19,03,029,,04,06,242,25,13,31,223,36,27,19,283,25*7C +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,24*7C +$GPRMC,222625.000,A,2734.78953,S,15305.96595,E,24.8,47.9,030308,11.2,W,A*31 +$GPVTG,47.9,T,59.1,M,24.8,N,46.0,K,A*28 +$GPGGA,222626.000,2734.78516,S,15305.97172,E,1,05,2.5,51.1,M,39.2,M,,*79 +$GPGLL,2734.78516,S,15305.97172,E,222626.000,A,A*43 +$GPGSA,A,3,16,25,20,04,13,,,,,,,,4.2,2.5,3.3*37 +$GPGST,222626.000,20.2,12.6,23.1,19.8,13.0,20.2,38.4*5F +$GPGSV,3,1,11,16,48,116,31,25,39,268,32,23,58,174,25,20,71,337,38*75 +$GPGSV,3,2,11,19,03,029,,04,06,242,25,13,31,223,36,27,19,283,23*7A +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,24*7C +$GPRMC,222626.000,A,2734.78516,S,15305.97172,E,24.7,48.3,030308,11.2,W,A*39 +$GPVTG,48.3,T,59.5,M,24.7,N,45.7,K,A*22 +$GPGGA,222627.000,2734.78079,S,15305.97737,E,1,04,2.5,50.5,M,39.2,M,,*77 +$GPGLL,2734.78079,S,15305.97737,E,222627.000,A,A*49 +$GPGSA,A,3,16,23,20,13,,,,,,,,,5.8,2.5,5.2*39 +$GPGST,222627.000,16.3,12.4,42.2,11.3,13.5,37.9,90.0*51 +$GPGSV,3,1,11,16,48,116,28,25,39,268,32,23,58,174,25,20,71,337,37*72 +$GPGSV,3,2,11,19,03,029,,04,06,242,29,13,31,223,37,27,19,283,30*75 +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,24*7C +$GPRMC,222627.000,A,2734.78079,S,15305.97737,E,24.3,48.1,030308,11.2,W,A*35 +$GPVTG,48.1,T,59.3,M,24.3,N,45.1,K,A*24 +$GPGGA,222628.000,2734.77637,S,15305.98293,E,1,07,1.3,50.2,M,39.2,M,,*7E +$GPGLL,2734.77637,S,15305.98293,E,222628.000,A,A*41 +$GPGSA,A,3,16,25,23,04,13,27,03,,,,,,2.2,1.3,1.8*38 +$GPGST,222628.000,13.2,14.5,8.8,76.9,8.4,13.0,22.0*5F +$GPGSV,3,1,11,16,48,116,30,25,39,268,32,23,58,174,27,20,71,337,37*79 +$GPGSV,3,2,11,19,03,029,,04,06,242,32,13,31,223,37,27,19,283,28*76 +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,25*7D +$GPRMC,222628.000,A,2734.77637,S,15305.98293,E,23.9,48.5,030308,11.2,W,A*34 +$GPVTG,48.5,T,59.7,M,23.9,N,44.3,K,A*2A +$GPGGA,222629.000,2734.77226,S,15305.98850,E,1,08,1.1,49.5,M,39.2,M,,*7C +$GPGLL,2734.77226,S,15305.98850,E,222629.000,A,A*41 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222629.000,11.0,9.5,7.3,89.6,6.7,8.6,14.3*5E +$GPGSV,3,1,11,16,48,116,31,25,39,268,32,23,58,174,25,20,71,337,36*7B +$GPGSV,3,2,11,19,03,029,,04,06,242,30,13,31,223,37,27,19,283,28*74 +$GPGSV,3,3,11,11,06,338,,01,,,18,03,14,056,27*7F +$GPRMC,222629.000,A,2734.77226,S,15305.98850,E,23.5,49.4,030308,11.2,W,A*38 +$GPVTG,49.4,T,60.6,M,23.5,N,43.5,K,A*2C +$GPGGA,222630.000,2734.76859,S,15305.99361,E,1,04,3.5,49.4,M,39.2,M,,*74 +$GPGLL,2734.76859,S,15305.99361,E,222630.000,A,A*42 +$GPGSA,A,3,16,25,20,27,,,,,,,,,4.9,3.5,3.4*39 +$GPGST,222630.000,13.4,7.9,50.0,19.9,17.0,43.1,69.5*66 +$GPGSV,3,1,11,16,48,116,31,25,39,268,30,23,58,174,22,20,71,337,36*7E +$GPGSV,3,2,11,19,03,029,,04,06,242,32,13,31,223,35,27,19,283,24*78 +$GPGSV,3,3,11,11,06,338,18,01,,,18,03,14,056,29*78 +$GPRMC,222630.000,A,2734.76859,S,15305.99361,E,21.1,50.3,030308,11.2,W,A*32 +$GPVTG,50.3,T,61.5,M,21.1,N,39.1,K,A*2E +$GPGGA,222631.000,2734.76498,S,15305.99809,E,1,08,1.1,48.2,M,39.2,M,,*7C +$GPGLL,2734.76498,S,15305.99809,E,222631.000,A,A*47 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222631.000,18.4,10.8,5.8,77.6,5.6,9.7,13.2*63 +$GPGSV,3,1,11,16,48,116,32,25,39,268,31,23,58,174,22,20,71,337,35*7F +$GPGSV,3,2,11,19,03,029,,04,06,242,30,13,31,223,36,27,19,283,25*78 +$GPGSV,3,3,11,11,06,338,18,01,,,18,03,14,056,33*73 +$GPRMC,222631.000,A,2734.76498,S,15305.99809,E,19.4,47.4,030308,11.2,W,A*38 +$GPVTG,47.4,T,58.6,M,19.4,N,35.9,K,A*2C +$GPGGA,222632.000,2734.76359,S,15306.00162,E,1,08,1.1,49.6,M,39.2,M,,*77 +$GPGLL,2734.76359,S,15306.00162,E,222632.000,A,A*49 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222632.000,18.1,14.9,6.7,53.4,9.5,11.5,16.1*5A +$GPGSV,3,1,11,16,48,116,30,25,39,268,31,23,58,174,31,20,71,337,31*7B +$GPGSV,3,2,11,19,03,029,,04,06,242,22,13,31,223,37,27,19,283,29*76 +$GPGSV,3,3,11,11,06,338,24,01,,,18,03,14,056,25*7B +$GPRMC,222632.000,A,2734.76359,S,15306.00162,E,12.4,65.5,030308,11.2,W,A*3C +$GPVTG,65.5,T,76.7,M,12.4,N,22.9,K,A*2D +$GPGGA,222633.000,2734.76254,S,15306.00553,E,1,08,1.1,49.0,M,39.2,M,,*7A +$GPGLL,2734.76254,S,15306.00553,E,222633.000,A,A*42 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222633.000,13.9,12.3,5.8,55.3,7.8,9.7,13.7*62 +$GPGSV,3,1,10,16,48,116,35,25,39,268,35,23,58,174,30,20,71,337,35*7E +$GPGSV,3,2,10,19,03,029,,04,06,242,26,13,31,223,39,27,19,283,26*72 +$GPGSV,3,3,10,11,06,338,24,03,14,056,30*76 +$GPRMC,222633.000,A,2734.76254,S,15306.00553,E,12.9,72.5,030308,11.2,W,A*3C +$GPVTG,72.5,T,83.7,M,12.9,N,23.9,K,A*2D +$GPGGA,222634.000,2734.76305,S,15306.00850,E,1,08,1.1,48.4,M,39.2,M,,*73 +$GPGLL,2734.76305,S,15306.00850,E,222634.000,A,A*4E +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222634.000,11.3,10.3,5.3,58.0,6.5,8.4,12.0*62 +$GPGSV,3,1,10,16,48,116,33,25,39,268,38,23,58,174,30,20,71,337,30*70 +$GPGSV,3,2,10,19,03,029,,04,06,242,29,13,31,223,34,27,19,283,30*77 +$GPGSV,3,3,10,11,06,338,23,03,14,056,25*75 +$GPRMC,222634.000,A,2734.76305,S,15306.00850,E,9.4,99.3,030308,11.2,W,A*04 +$GPVTG,99.3,T,110.5,M,9.4,N,17.3,K,A*2D +$GPGGA,222635.000,2734.76418,S,15306.01089,E,1,08,1.1,47.9,M,39.2,M,,*76 +$GPGLL,2734.76418,S,15306.01089,E,222635.000,A,A*49 +$GPGSA,A,3,16,25,23,20,04,13,27,03,,,,,1.7,1.1,1.3*35 +$GPGST,222635.000,13.4,9.3,7.7,66.3,7.3,8.3,14.0*50 +$GPGSV,3,1,10,16,48,116,36,25,39,268,31,23,58,174,37,20,71,337,36*7D +$GPGSV,3,2,10,19,03,029,,04,06,242,31,13,31,223,34,27,19,283,31*7F +$GPGSV,3,3,10,11,06,338,23,03,14,056,23*73 +$GPRMC,222635.000,A,2734.76418,S,15306.01089,E,8.3,116.7,030308,11.2,W,A*37 +$GPVTG,116.7,T,127.9,M,8.3,N,15.4,K,A*14 +$GPGGA,222636.000,2734.76577,S,15306.01258,E,1,07,1.7,47.9,M,39.2,M,,*7A +$GPGLL,2734.76577,S,15306.01258,E,222636.000,A,A*4C +$GPGSA,A,3,16,25,23,20,04,13,27,,,,,,2.8,1.7,2.3*3F +$GPGST,222636.000,10.6,11.9,8.1,45.4,9.3,9.3,18.8*65 +$GPGSV,3,1,10,16,48,116,41,25,39,268,35,23,58,174,40,20,71,337,33*7C +$GPGSV,3,2,10,19,03,029,,04,06,242,32,13,31,223,28,27,19,283,34*74 +$GPGSV,3,3,10,11,06,338,25,03,14,056,23*75 +$GPRMC,222636.000,A,2734.76577,S,15306.01258,E,7.6,135.7,030308,11.2,W,A*39 +$GPVTG,135.7,T,146.9,M,7.6,N,14.1,K,A*1C +$GPGGA,222637.000,2734.76759,S,15306.01422,E,1,07,1.7,47.8,M,39.2,M,,*7F +$GPGLL,2734.76759,S,15306.01422,E,222637.000,A,A*48 +$GPGSA,A,3,16,25,23,20,04,13,27,,,,,,2.8,1.7,2.3*3F +$GPGST,222637.000,8.9,7.2,10.9,44.4,8.4,8.5,17.1*59 +$GPGSV,3,1,10,16,48,116,44,25,39,268,36,23,58,174,33,20,71,337,33*7E +$GPGSV,3,2,10,19,03,029,,04,06,242,24,13,31,223,29,27,19,283,36*70 +$GPGSV,3,3,10,11,06,338,25,03,14,056,23*75 +$GPRMC,222637.000,A,2734.76759,S,15306.01422,E,8.0,140.6,030308,11.2,W,A*37 +$GPVTG,140.6,T,151.8,M,8.0,N,14.8,K,A*18 +$GPGGA,222638.000,2734.76957,S,15306.01592,E,1,06,2.0,47.6,M,39.2,M,,*71 +$GPGLL,2734.76957,S,15306.01592,E,222638.000,A,A*4D +$GPGSA,A,3,16,25,23,20,04,13,,,,,,,3.2,2.0,2.6*30 +$GPGST,222638.000,10.4,8.9,16.3,14.1,8.7,14.6,19.9*51 +$GPGSV,3,1,10,16,48,116,38,25,39,268,30,23,58,174,29,20,71,337,29*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,29*7B +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222638.000,A,2734.76957,S,15306.01592,E,8.8,142.8,030308,11.2,W,A*36 +$GPVTG,142.8,T,154.0,M,8.8,N,16.2,K,A*19 +$GPGGA,222639.000,2734.77109,S,15306.01748,E,1,07,1.7,47.8,M,39.2,M,,*7C +$GPGLL,2734.77109,S,15306.01748,E,222639.000,A,A*4B +$GPGSA,A,3,16,25,23,20,04,13,27,,,,,,2.8,1.7,2.3*3F +$GPGST,222639.000,9.5,9.6,14.7,43.8,11.3,11.5,19.8*51 +$GPGSV,3,1,10,16,48,116,37,25,39,268,32,23,58,174,37,20,71,337,29*71 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,27*75 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222639.000,A,2734.77109,S,15306.01748,E,7.1,137.2,030308,11.2,W,A*3E +$GPVTG,137.2,T,148.4,M,7.1,N,13.1,K,A*18 +$GPGGA,222640.000,2734.77216,S,15306.02018,E,1,04,2.6,47.8,M,39.2,M,,*7F +$GPGLL,2734.77216,S,15306.02018,E,222640.000,A,A*49 +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.2,2.6,5.6*32 +$GPGST,222640.000,20.0,11.7,22.3,7.0,10.9,20.3,46.8*65 +$GPGSV,3,1,10,16,48,116,32,25,39,268,29,23,58,174,24,20,71,337,25*70 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,25*77 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222640.000,A,2734.77216,S,15306.02018,E,9.4,114.2,030308,11.2,W,A*36 +$GPVTG,114.2,T,125.4,M,9.4,N,17.4,K,A*18 +$GPGGA,222641.000,2734.77543,S,15306.02149,E,1,04,2.6,47.7,M,39.2,M,,*73 +$GPGLL,2734.77543,S,15306.02149,E,222641.000,A,A*4A +$GPGSA,A,3,16,25,23,13,,,,,,,,,6.2,2.6,5.6*32 +$GPGST,222641.000,18.3,40.3,13.2,79.5,13.7,36.3,59.1*5E +$GPGSV,3,1,10,16,48,116,34,25,39,268,23,23,58,174,26,20,71,337,27*7C +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222641.000,A,2734.77543,S,15306.02149,E,12.5,160.9,030308,11.2,W,A*06 +$GPVTG,160.9,T,172.1,M,12.5,N,23.1,K,A*2E +$GPGGA,222642.000,2734.77709,S,15306.02300,E,1,04,2.6,47.7,M,39.2,M,,*73 +$GPGLL,2734.77709,S,15306.02300,E,222642.000,A,A*4A +$GPGSA,A,3,16,20,04,13,,,,,,,,,4.3,2.6,3.4*35 +$GPGST,222642.000,15.8,14.5,71.8,20.7,26.3,61.6,97.2*58 +$GPGSV,3,1,10,16,48,116,41,25,40,268,23,23,58,174,27,20,71,337,34*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222642.000,A,2734.77709,S,15306.02300,E,7.5,140.7,030308,11.2,W,A*3E +$GPVTG,140.7,T,151.9,M,7.5,N,13.9,K,A*14 +$GPGGA,222643.000,2734.77831,S,15306.02427,E,1,04,2.6,47.5,M,39.2,M,,*76 +$GPGLL,2734.77831,S,15306.02427,E,222643.000,A,A*4D +$GPGSA,A,3,16,20,04,13,,,,,,,,,4.3,2.6,3.4*35 +$GPGST,222643.000,12.9,15.5,112.8,21.4,39.9,96.1,154.3*5C +$GPGSV,3,1,10,16,48,116,41,25,40,268,23,23,58,174,26,20,71,337,35*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,23*71 +$GPRMC,222643.000,A,2734.77831,S,15306.02427,E,5.6,136.2,030308,11.2,W,A*3C +$GPVTG,136.2,T,147.4,M,5.6,N,10.4,K,A*15 +$GPGGA,222644.000,2734.77900,S,15306.02522,E,1,04,2.5,47.4,M,39.2,M,,*74 +$GPGLL,2734.77900,S,15306.02522,E,222644.000,A,A*4D +$GPGSA,A,3,16,23,20,13,,,,,,,,,5.8,2.5,5.2*39 +$GPGST,222644.000,11.9,32.3,39.9,23.1,35.5,30.7,165.7*69 +$GPGSV,3,1,10,16,48,116,38,25,40,268,23,23,58,174,25,20,71,337,37*7C +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,26*74 +$GPRMC,222644.000,A,2734.77900,S,15306.02522,E,3.7,127.8,030308,11.2,W,A*31 +$GPVTG,127.8,T,139.0,M,3.7,N,6.9,K,A*2F +$GPGGA,222645.000,2734.77991,S,15306.02594,E,1,04,3.4,47.4,M,39.2,M,,*70 +$GPGLL,2734.77991,S,15306.02594,E,222645.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.4,5.0*30 +$GPGST,222645.000,15.3,40.1,15.0,66.6,34.1,19.2,69.1*50 +$GPGSV,3,1,10,16,48,116,33,25,40,268,23,23,58,174,23,20,71,337,35*73 +$GPGSV,3,2,10,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*71 +$GPGSV,3,3,10,11,06,338,21,03,14,056,30*73 +$GPRMC,222645.000,A,2734.77991,S,15306.02594,E,3.9,145.4,030308,11.2,W,A*33 +$GPVTG,145.4,T,156.6,M,3.9,N,7.2,K,A*2C +$GPGGA,222646.000,2734.78074,S,15306.02652,E,1,04,3.4,47.4,M,39.2,M,,*77 +$GPGLL,2734.78074,S,15306.02652,E,222646.000,A,A*4E +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.4,5.0*30 +$GPGST,222646.000,14.8,53.5,15.6,78.9,48.1,16.9,76.9*50 +$GPGSV,3,1,11,16,48,116,32,25,40,268,23,23,58,174,26,20,71,337,32*71 +$GPGSV,3,2,11,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*70 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,34*4D +$GPRMC,222646.000,A,2734.78074,S,15306.02652,E,3.5,149.5,030308,11.2,W,A*35 +$GPVTG,149.5,T,160.7,M,3.5,N,6.6,K,A*2C +$GPGGA,222647.000,2734.78140,S,15306.02704,E,1,04,3.4,47.3,M,39.2,M,,*75 +$GPGLL,2734.78140,S,15306.02704,E,222647.000,A,A*4B +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.4,5.0*30 +$GPGST,222647.000,11.7,42.4,13.1,77.7,38.0,14.3,60.9*53 +$GPGSV,3,1,11,16,48,116,37,25,40,268,23,23,58,174,31,20,71,337,36*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*70 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,34*4D +$GPRMC,222647.000,A,2734.78140,S,15306.02704,E,2.8,145.4,030308,11.2,W,A*31 +$GPVTG,145.4,T,156.6,M,2.8,N,5.1,K,A*2D +$GPGGA,222648.000,2734.78183,S,15306.02753,E,1,04,3.5,47.2,M,39.2,M,,*77 +$GPGLL,2734.78183,S,15306.02753,E,222648.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222648.000,11.3,35.2,16.9,76.3,31.5,16.9,53.8*53 +$GPGSV,3,1,11,16,48,116,35,25,40,267,23,23,58,174,37,20,71,337,35*7E +$GPGSV,3,2,11,19,03,029,,04,06,242,28,13,31,223,31,27,19,283,23*70 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,35*4C +$GPRMC,222648.000,A,2734.78183,S,15306.02753,E,2.1,135.8,030308,11.2,W,A*31 +$GPVTG,135.8,T,147.1,M,2.1,N,3.9,K,A*26 +$GPGGA,222649.000,2734.78197,S,15306.02773,E,1,04,3.5,46.8,M,39.2,M,,*7A +$GPGLL,2734.78197,S,15306.02773,E,222649.000,A,A*4F +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222649.000,13.9,60.8,14.8,84.0,55.3,14.7,79.7*52 +$GPGSV,3,1,11,16,48,116,31,25,40,267,23,23,58,174,36,20,71,337,31*7F +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,19,283,23*78 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,29*41 +$GPRMC,222649.000,A,2734.78197,S,15306.02773,E,0.6,148.6,030308,11.2,W,A*36 +$GPVTG,148.6,T,159.8,M,0.6,N,1.2,K,A*28 +$GPGGA,222650.000,2734.78195,S,15306.02785,E,1,04,3.5,46.4,M,39.2,M,,*75 +$GPGLL,2734.78195,S,15306.02785,E,222650.000,A,A*4C +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222650.000,11.4,48.0,12.9,83.3,43.6,12.8,63.8*5B +$GPGSV,3,1,11,16,48,116,30,25,40,267,23,23,58,174,33,20,71,337,30*7A +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,19,283,23*78 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,26*4E +$GPRMC,222650.000,A,2734.78195,S,15306.02785,E,0.2,6.4,030308,11.2,W,A*38 +$GPVTG,6.4,T,17.6,M,0.2,N,0.3,K,A*10 +$GPGGA,222651.000,2734.78191,S,15306.02798,E,1,04,3.5,45.9,M,39.2,M,,*72 +$GPGLL,2734.78191,S,15306.02798,E,222651.000,A,A*45 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222651.000,9.8,40.0,12.0,82.4,36.3,11.9,53.8*6E +$GPGSV,3,1,11,16,48,116,28,25,40,267,,23,58,174,35,20,71,337,26*73 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,19,283,*79 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,28*40 +$GPRMC,222651.000,A,2734.78191,S,15306.02798,E,0.1,352.6,030308,11.2,W,A*32 +$GPVTG,352.6,T,3.8,M,0.1,N,0.3,K,A*28 +$GPGGA,222652.000,2734.78198,S,15306.02797,E,1,04,3.5,45.9,M,39.2,M,,*77 +$GPGLL,2734.78198,S,15306.02797,E,222652.000,A,A*40 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222652.000,21.7,41.2,15.0,83.8,37.5,14.2,91.6*58 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,23,20,71,337,26*78 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,19,283,*79 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,24*4C +$GPRMC,222652.000,A,2734.78198,S,15306.02797,E,0.2,263.5,030308,11.2,W,A*34 +$GPVTG,263.5,T,274.7,M,0.2,N,0.3,K,A*26 +$GPGGA,222653.000,2734.78226,S,15306.02793,E,1,04,3.5,45.9,M,39.2,M,,*74 +$GPGLL,2734.78226,S,15306.02793,E,222653.000,A,A*43 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222653.000,18.8,36.4,20.7,81.4,33.0,19.3,78.6*5F +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,25,20,71,337,25*7D +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,24*4C +$GPRMC,222653.000,A,2734.78226,S,15306.02793,E,0.8,188.1,030308,11.2,W,A*3F +$GPVTG,188.1,T,199.3,M,0.8,N,1.5,K,A*2D +$GPGGA,222654.000,2734.78231,S,15306.02789,E,1,04,3.5,45.9,M,39.2,M,,*7E +$GPGLL,2734.78231,S,15306.02789,E,222654.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222654.000,14.4,23.3,16.5,69.8,20.7,16.0,57.9*5D +$GPGSV,3,1,11,16,48,116,34,25,40,267,,23,58,174,34,20,71,337,31*79 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,31*48 +$GPRMC,222654.000,A,2734.78231,S,15306.02789,E,0.1,145.6,030308,11.2,W,A*3A +$GPVTG,145.6,T,156.8,M,0.1,N,0.2,K,A*2C +$GPGGA,222655.000,2734.78251,S,15306.02806,E,1,04,3.5,45.8,M,39.2,M,,*70 +$GPGLL,2734.78251,S,15306.02806,E,222655.000,A,A*46 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222655.000,12.0,28.1,14.0,78.7,25.3,13.6,52.5*54 +$GPGSV,3,1,11,16,48,116,40,25,40,267,,23,58,174,38,20,71,337,35*72 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,36*4F +$GPRMC,222655.000,A,2734.78251,S,15306.02806,E,0.7,135.5,030308,11.2,W,A*37 +$GPVTG,135.5,T,146.8,M,0.7,N,1.2,K,A*2E +$GPGGA,222656.000,2734.78273,S,15306.02823,E,1,04,3.5,45.7,M,39.2,M,,*7B +$GPGLL,2734.78273,S,15306.02823,E,222656.000,A,A*42 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222656.000,9.9,24.8,12.2,76.6,22.2,12.0,44.0*69 +$GPGSV,3,1,11,16,48,116,38,25,40,267,,23,58,174,36,20,71,337,30*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,35*4C +$GPRMC,222656.000,A,2734.78273,S,15306.02823,E,0.5,135.5,030308,11.2,W,A*31 +$GPVTG,135.5,T,146.7,M,0.5,N,1.0,K,A*21 +$GPGGA,222657.000,2734.78312,S,15306.02858,E,1,04,3.5,45.5,M,39.2,M,,*72 +$GPGLL,2734.78312,S,15306.02858,E,222657.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222657.000,8.4,22.4,10.9,74.9,19.9,11.0,38.1*60 +$GPGSV,3,1,11,16,48,116,37,25,40,267,,23,58,174,36,20,71,337,30*79 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,21,08,00,298,,03,14,056,34*4D +$GPRMC,222657.000,A,2734.78312,S,15306.02858,E,1.3,137.6,030308,11.2,W,A*3C +$GPVTG,137.6,T,148.8,M,1.3,N,2.4,K,A*21 +$GPGGA,222658.000,2734.78370,S,15306.02910,E,1,04,3.5,45.4,M,39.2,M,,*75 +$GPGLL,2734.78370,S,15306.02910,E,222658.000,A,A*4F +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222658.000,11.5,25.4,19.7,45.8,20.9,20.7,46.1*53 +$GPGSV,3,1,11,16,48,116,34,25,40,267,18,23,58,174,36,20,71,337,32*71 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,32*48 +$GPRMC,222658.000,A,2734.78370,S,15306.02910,E,2.7,141.8,030308,11.2,W,A*32 +$GPVTG,141.8,T,153.0,M,2.7,N,5.0,K,A*28 +$GPGGA,222659.000,2734.78463,S,15306.02956,E,1,04,3.5,45.4,M,39.2,M,,*73 +$GPGLL,2734.78463,S,15306.02956,E,222659.000,A,A*49 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222659.000,10.9,34.8,17.8,79.2,31.4,17.1,52.2*5E +$GPGSV,3,1,11,16,48,116,32,25,40,267,18,23,58,174,37,20,71,337,32*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,26*4D +$GPRMC,222659.000,A,2734.78463,S,15306.02956,E,3.6,157.2,030308,11.2,W,A*39 +$GPVTG,157.2,T,168.4,M,3.6,N,6.7,K,A*2D +$GPGGA,222700.000,2734.78553,S,15306.02974,E,1,04,3.5,45.3,M,39.2,M,,*7B +$GPGLL,2734.78553,S,15306.02974,E,222700.000,A,A*46 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222700.000,13.4,30.5,15.4,80.9,27.6,14.6,58.2*5C +$GPGSV,3,1,11,16,48,116,38,25,40,267,18,23,58,174,42,20,71,337,34*78 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,30*4A +$GPRMC,222700.000,A,2734.78553,S,15306.02974,E,3.1,171.1,030308,11.2,W,A*36 +$GPVTG,171.1,T,182.3,M,3.1,N,5.7,K,A*2D +$GPGGA,222701.000,2734.78678,S,15306.02887,E,1,05,1.6,45.4,M,39.2,M,,*7A +$GPGLL,2734.78678,S,15306.02887,E,222701.000,A,A*40 +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222701.000,18.6,22.3,33.4,25.2,29.0,22.6,46.2*53 +$GPGSV,3,1,11,16,48,116,30,25,40,267,18,23,58,174,33,20,71,337,27*74 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,20,27,20,283,*71 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,27*4C +$GPRMC,222701.000,A,2734.78678,S,15306.02887,E,5.1,212.6,030308,11.2,W,A*37 +$GPVTG,212.6,T,223.8,M,5.1,N,9.5,K,A*27 +$GPGGA,222702.000,2734.78726,S,15306.02769,E,1,04,3.5,45.3,M,39.2,M,,*7B +$GPGLL,2734.78726,S,15306.02769,E,222702.000,A,A*46 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.0*31 +$GPGST,222702.000,14.7,49.5,20.8,84.3,45.1,19.5,72.8*5F +$GPGSV,3,1,11,16,48,116,36,25,40,267,18,23,58,174,40,20,71,337,31*71 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,20,27,20,283,*71 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,28*43 +$GPRMC,222702.000,A,2734.78726,S,15306.02769,E,4.2,246.4,030308,11.2,W,A*30 +$GPVTG,246.4,T,257.6,M,4.2,N,7.7,K,A*27 +$GPGGA,222703.000,2734.78745,S,15306.02617,E,1,05,1.6,45.3,M,39.2,M,,*77 +$GPGLL,2734.78745,S,15306.02617,E,222703.000,A,A*4A +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222703.000,12.3,16.0,23.0,21.5,20.3,15.6,33.1*53 +$GPGSV,3,1,11,16,48,116,31,25,40,267,18,23,58,174,29,20,70,337,23*7B +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,27*4C +$GPRMC,222703.000,A,2734.78745,S,15306.02617,E,4.9,265.5,030308,11.2,W,A*37 +$GPVTG,265.5,T,276.7,M,4.9,N,9.1,K,A*26 +$GPGGA,222704.000,2734.78730,S,15306.02555,E,1,04,3.5,45.3,M,39.2,M,,*77 +$GPGLL,2734.78730,S,15306.02555,E,222704.000,A,A*4A +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.1*30 +$GPGST,222704.000,9.5,34.0,22.1,80.5,30.8,20.6,55.7*69 +$GPGSV,3,1,11,16,48,116,31,25,40,267,18,23,58,174,29,20,70,337,23*7B +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,31*4B +$GPRMC,222704.000,A,2734.78730,S,15306.02555,E,2.1,286.5,030308,11.2,W,A*34 +$GPVTG,286.5,T,297.7,M,2.1,N,3.9,K,A*28 +$GPGGA,222705.000,2734.78698,S,15306.02452,E,1,04,3.5,45.3,M,39.2,M,,*73 +$GPGLL,2734.78698,S,15306.02452,E,222705.000,A,A*4E +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.1*30 +$GPGST,222705.000,93.8,65.1,31.9,84.0,59.3,29.7,94.1*5F +$GPGSV,3,1,11,16,48,116,29,25,40,267,18,23,58,174,29,20,70,337,23*72 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,30*4A +$GPRMC,222705.000,A,2734.78698,S,15306.02452,E,3.6,290.3,030308,11.2,W,A*37 +$GPVTG,290.3,T,301.5,M,3.6,N,6.8,K,A*27 +$GPGGA,222706.000,2734.78686,S,15306.02339,E,1,04,3.5,45.3,M,39.2,M,,*75 +$GPGLL,2734.78686,S,15306.02339,E,222706.000,A,A*48 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.1*30 +$GPGST,222706.000,114.3,62.0,48.3,70.3,55.4,45.7,116.3*5B +$GPGSV,3,1,11,16,48,116,24,25,40,267,18,23,58,174,29,20,70,337,23*7F +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222706.000,A,2734.78686,S,15306.02339,E,3.4,277.7,030308,11.2,W,A*3E +$GPVTG,277.7,T,288.9,M,3.4,N,6.3,K,A*2F +$GPGGA,222707.000,2734.78679,S,15306.02251,E,1,04,3.5,45.3,M,39.2,M,,*7B +$GPGLL,2734.78679,S,15306.02251,E,222707.000,A,A*46 +$GPGSA,A,3,16,23,20,03,,,,,,,,,6.1,3.5,5.1*30 +$GPGST,222707.000,128.0,90.0,67.0,53.0,75.4,69.6,158.6*55 +$GPGSV,3,1,11,16,48,116,24,25,40,267,18,23,58,174,29,20,70,337,23*7F +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,223,22,27,20,283,*73 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222707.000,A,2734.78679,S,15306.02251,E,,,030308,,,A*79 +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222708.000,2734.78673,S,15306.02181,E,1,05,1.6,45.3,M,39.2,M,,*70 +$GPGLL,2734.78673,S,15306.02181,E,222708.000,A,A*4D +$GPGSA,A,3,16,23,20,13,03,,,,,,,,2.5,1.6,1.9*3F +$GPGST,222708.000,66.8,93.0,70.5,62.6,69.3,81.1,141.7*6F +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,29,20,70,337,23*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222708.000,A,2734.78673,S,15306.02181,E,,,030308,,,A*72 +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222709.000,2734.78668,S,15306.02124,E,1,05,1.6,45.3,M,39.2,M,,*74 +$GPGLL,2734.78668,S,15306.02124,E,222709.000,A,A*49 +$GPGSA,A,2,16,23,20,13,03,,,,,,,,1.8,1.6,0.9*31 +$GPGST,222709.000,89.5,61.2,117.7,37.9,91.7,79.5,4.3*54 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,29,20,70,337,23*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222709.000,A,2734.78668,S,15306.02124,E,,,030308,,,A*76 +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222710.000,2734.78664,S,15306.02080,E,1,05,1.6,45.3,M,39.2,M,,*7F +$GPGLL,2734.78664,S,15306.02080,E,222710.000,A,A*42 +$GPGSA,A,2,16,23,20,13,03,,,,,,,,1.8,1.6,0.9*31 +$GPGST,222710.000,117.0,82.3,157.6,39.0,121.7,107.9,3.9*62 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,29,20,70,337,23*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222710.000,A,2734.78664,S,15306.02080,E,,,030308,,,A*7D +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222711.000,2734.78660,S,15306.02044,E,1,05,1.6,45.3,M,39.2,M,,*72 +$GPGLL,2734.78660,S,15306.02044,E,222711.000,A,A*4F +$GPGSA,A,2,16,23,20,13,03,,,,,,,,1.8,1.6,0.9*31 +$GPGST,222711.000,128.0,107.6,205.2,40.2,156.7,142.6,3.5*58 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,174,29,20,70,337,23*76 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222711.000,A,2734.78660,S,15306.02044,E,,,030308,,,A*70 +$GPVTG,,T,,M,,N,,K,N*2C +$GPGGA,222712.000,2734.78658,S,15306.02015,E,1,05,1.6,45.3,M,39.2,M,,*7E +$GPGLL,2734.78658,S,15306.02015,E,222712.000,A,A*43 +$GPGSA,A,2,16,23,20,13,03,,,,,,,,1.8,1.6,0.9*31 +$GPGST,222712.000,128.0,137.2,261.1,41.4,197.4,183.9,3.2*51 +$GPGSV,3,1,11,16,48,116,24,25,40,267,,23,58,173,29,20,70,337,23*71 +$GPGSV,3,2,11,19,03,029,,04,06,242,,13,31,222,22,27,20,283,*72 +$GPGSV,3,3,11,11,06,338,,08,00,298,,03,14,056,24*4F +$GPRMC,222712.000,A,2734.78658,S,15306.02015,E,,,030308,,,A*7C \ No newline at end of file diff --git a/src/location/doc/snippets/declarative/places.qml b/src/location/doc/snippets/declarative/places.qml new file mode 100644 index 0000000..7dab804 --- /dev/null +++ b/src/location/doc/snippets/declarative/places.qml @@ -0,0 +1,453 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [QtQuick import] +import QtQuick 2.0 +//! [QtQuick import] +import QtPositioning 5.5 +import QtLocation 5.6 + +Item { + width: 400; height: 400; + Plugin { + id: myPlugin + } + + Place { + id: place + } + + //! [Category] + Category { + id: category + + plugin: myPlugin + name: "New Category" + visibility: Category.PrivateVisibility + } + //! [Category] + + function saveCategory() { + //! [Category save] + category.save(); + //! [Category save] + } + + //! [CategoryView] + ListView { + model: CategoryModel { + plugin: myPlugin + hierarchical: false + } + delegate: Text { text: category.name } + } + //! [CategoryView] + + //! [ExtendedAttributes] + ListView { + model: place.extendedAttributes.keys() + delegate: Text { + text: "" + place.extendedAttributes[modelData].label + ": " + + place.extendedAttributes[modelData].text + } + } + //! [ExtendedAttributes] + + //! [ExtendedAttributes read] + function printExtendedAttributes(extendedAttributes) { + var keys = extendedAttributes.keys(); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (extendedAttributes[key].label !== "") + console.log(extendedAttributes[key].label + ": " + extendedAttributes[key].text); + } + } + //! [ExtendedAttributes read] + + function writeExtendedAttributes() { + //! [ExtendedAttributes write] + //assign a new attribute to a place + var smokingAttrib = Qt.createQmlObject('import QtLocation 5.3; PlaceAttribute {}', place); + smokingAttrib.label = "Smoking Allowed" + smokingAttrib.text = "No" + place.extendedAttributes.smoking = smokingAttrib; + + //modify an existing attribute + place.extendedAttributes.smoking.text = "Yes" + //! [ExtendedAttributes write] + } + + Icon { + id: icon + } + //! [Icon] + Image { + source: icon.url(Qt.size(64, 64)) + } + //! [Icon] + + Image { + //! [Icon default] + source: icon.url() + //! [Icon default] + } + + //! [SearchSuggestionModel] + PlaceSearchSuggestionModel { + id: suggestionModel + + plugin: myPlugin + + // Brisbane + searchArea: QtPositioning.circle(QtPositioning.coordinate(-27.46778, 153.02778)) + + onSearchTermChanged: update() + } + + ListView { + model: suggestionModel + delegate: Text { text: suggestion } + } + //! [SearchSuggestionModel] + + //! [EditorialModel] + EditorialModel { + id: editorialModel + batchSize: 3 + place: place + } + + ListView { + model: editorialModel + delegate: Item { + anchors.fill: parent + + Column { + width: parent.width + clip: true + + Text { + text: title + width: parent.width + wrapMode: Text.WordWrap + font.pixelSize: 24 + } + + Text { + text: text + width: parent.width + wrapMode: Text.WordWrap + font.pixelSize: 20 + } + + Row { + Image { + width: 16 + height: 16 + + source: supplier.icon.url(Qt.size(width, height), Icon.List) + } + + Text { + text: "Provided by " + supplier.name + font.pixelSize: 16 + } + } + + Text { + text: "Contributed by " + user.name + font.pixelSize: 16 + } + + Text { + text: attribution + font.pixelSize: 8 + } + } + } + } + //! [EditorialModel] + + //! [ImageModel] + ImageModel { + id: imageModel + batchSize: 3 + place: place + } + + ListView { + anchors.top: parent.top + width: parent.width + spacing: 10 + + model: imageModel + orientation: ListView.Horizontal + snapMode: ListView.SnapOneItem + + delegate: Item { + width: listView.width + height: listView.height + + Image { + anchors.fill: parent + source: url + fillMode: Image.PreserveAspectFit + } + + Text { + text: supplier.name + "\n" + supplier.url + width: parent.width + anchors.bottom: parent.bottom + } + } + } + //! [ImageModel] + + //! [Supplier] + Supplier { + id: placeSupplier + name: "Example" + url: "http://www.example.com/" + } + + Text { + text: "This place is was provided by " + placeSupplier.name + "\n" + placeSupplier.url + } + //! [Supplier] + + //! [Ratings] + Text { + text: "This place is rated " + place.ratings.average + " out of " + place.ratings.maximum + " stars." + } + //! [Ratings] + + //! [ContactDetails read] + function printContactDetails(contactDetails) { + var keys = contactDetails.keys(); + for (var i = 0; i < keys.length; ++i) { + var contactList = contactDetails[keys[i]]; + for (var j = 0; j < contactList.length; ++j) { + console.log(contactList[j].label + ": " + contactList[j].value); + } + } + } + //! [ContactDetails read] + + //! [ContactDetails write single] + function writeSingle() { + var phoneNumber = Qt.createQmlObject('import QtLocation 5.3; ContactDetail {}', place); + phoneNumber.label = "Phone"; + phoneNumber.value = "555-5555" + place.contactDetails.phone = phoneNumber; + } + //! [ContactDetails write single] + + //! [ContactDetails write multiple] + function writeMultiple() { + var bob = Qt.createQmlObject('import QtLocation 5.3; ContactDetail {}', place); + bob.label = "Bob"; + bob.value = "555-5555" + + var alice = Qt.createQmlObject('import QtLocation 5.3; ContactDetail {}', place); + alice.label = "Alice"; + alice.value = "555-8745" + + var numbers = new Array(); + numbers.push(bob); + numbers.push(alice); + + place.contactDetails.phone = numbers; + } + //! [ContactDetails write multiple] + + //! [ContactDetails phoneList] + ListView { + model: place.contactDetails.phone; + delegate: Text { text: modelData.label + ": " + modelData.value } + } + //! [ContactDetails phoneList] + + //! [Place savePlace def] + Place { + id: myPlace + plugin: myPlugin + + name: "Brisbane Technology Park" + location: Location { + address: Address { + street: "53 Brandl Street" + city: "Eight Mile Plains" + postalCode: "4113" + country: "Australia" + } + coordinate { + latitude: -27.579646 + longitude: 153.100308 + } + } + + visibility: Place.PrivateVisibility + } + //! [Place savePlace def] + + function fetchDetails() { + //! [Place fetchDetails] + if (!place.detailsFetched) + place.getDetails(); + //! [Place fetchDetails] + } + + function savePlace() { + //! [Place savePlace] + myPlace.save(); + //! [Place savePlace] + } + + function createAndSavePlace() { + //! [Place createAndSavePlace] + //creating and saving a place + var place = Qt.createQmlObject('import QtLocation 5.3; Place { }', parent); + place.plugin = myPlugin; + place.name = "New York"; + place.location.coordinate.latitude = 40.7 + place.location.coordinate.longitude = -74.0 + place.save(); + //! [Place createAndSavePlace] + } + + function removePlace() { + //! [Place removePlace] + //removing a place + place.remove(); + //! [Place removePlace] + } + + function saveToNewPlugin() { + //! [Place save to different plugin] + var place = Qt.createQmlObject('import QtLocation 5.3; Place { }', parent); + place.plugin = destinationPlugin; + place.copyFrom(originalPlace); + place.save(); + //! [Place save to different plugin] + } + + function getPlaceForId() { + //! [Place placeId] + place.plugin = myPlugin; + place.placeId = "known-place-id"; + place.getDetails(); + //! [Place placeId] + } + + function primaryContacts() { + //! [Place primaryPhone] + var primaryPhone; + if (place.contactDetails["phone"].length > 0) + primaryPhone = place.contactDetails["phone"][0].value; + //! [Place primaryPhone] + //! [Place primaryFax] + var primaryFax; + if (place.contactDetails["fax"].length > 0) + primaryFax = place.contactDetails["fax"][0].value; + //! [Place primaryFax] + //! [Place primaryEmail] + var primaryEmail; + if (place.contactDetails["email"].length > 0) + primaryEmail = place.contactDetails["email"][0].value; + //! [Place primaryEmail] + //! [Place primaryWebsite] + var primaryWebsite; + if (place.contactDetails["website"].length > 0) + primaryWebsite = place.contactDetails["website"][0].value; + //! [Place primaryWebsite] + } + + //! [Place favorite] + Text { text: place.favorite ? place.favorite.name : place.name } + //! [Place favorite] + + function saveFavorite() { + var place = Qt.createQmlObject('import QtLocation 5.3; Place { }', parent); + var destinationPlugin + //! [Place saveFavorite] + place.initializeFavorite(destinationPlugin); + //if necessary customizations to the favorite can be made here. + //... + place.favorite.save(); + //! [Place saveFavorite] + } + + function removeFavorite() { + var place; + //! [Place removeFavorite 1] + place.favorite.remove(); + //! [Place removeFavorite 1] + + //! [Place removeFavorite 2] + //check successful removal of the favorite by monitoring its status. + //once that is done we can assign null to the favorite + place.favorite = null; + //! [Place removeFavorite 2] + } + + function connectStatusChangedHandler() { + //! [Place checkStatus] + place.statusChanged.connect(statusChangedHandler); + //! [Place checkStatus] + } + + //! [Place checkStatus handler] + function statusChangedHandler() { + if (statusChangedHandler.prevStatus === Place.Saving) { + switch (place.status) { + case Place.Ready: + console.log('Save successful'); + break; + case Place.Error: + console.log('Save failed'); + break; + default: + break; + } + } + statusChangedHandler.prevStatus = place.status; + } + //! [Place checkStatus handler] +} diff --git a/src/location/doc/snippets/declarative/places_loader.qml b/src/location/doc/snippets/declarative/places_loader.qml new file mode 100644 index 0000000..a52a4b0 --- /dev/null +++ b/src/location/doc/snippets/declarative/places_loader.qml @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtPositioning 5.2 +import QtLocation 5.3 + +Rectangle { + width: 360 + height: 360 + property variant startCoordinate: QtPositioning.coordinate(-27.46778, 153.02778) + + Plugin { + id: myPlugin + name: "osm" + //specify plugin parameters if necessary + //PluginParameter {...} + //PluginParameter {...} + //... + } + + PlaceSearchModel { + id: searchModel + + plugin: myPlugin + + searchTerm: "pizza" + searchArea: QtPositioning.circle(startCoordinate) + + Component.onCompleted: update() + } + + //! [Handle Result Types] + Component { + id: resultDelegate + Loader { + Component { + id: placeResult + + Column { + Text { text: title } + Text { text: place.location.address.text } + } + } + + Component { + id: otherResult + Text { text: title } + } + + sourceComponent: type == PlaceSearchModel.PlaceResult ? placeResult : + otherResult + } + } + //! [Handle Result Types] + + ListView { + anchors.fill: parent + model: searchModel + delegate: resultDelegate + spacing: 10 + } + + Connections { + target: searchModel + onStatusChanged: { + if (searchModel.status == PlaceSearchModel.Error) + console.log(searchModel.errorString()); + } + } +} diff --git a/src/location/doc/snippets/declarative/plugin.qml b/src/location/doc/snippets/declarative/plugin.qml new file mode 100644 index 0000000..4428210 --- /dev/null +++ b/src/location/doc/snippets/declarative/plugin.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +//! [Plugin import] +import QtLocation 5.3 +//! [Plugin import] + +Item { + //! [Plugin locale] + //single locale + Plugin { + locales: "en_US" + } + + //multiple locales + Plugin { + locales: ["fr_FR","en_US"] + } + //! [Plugin locale] +} diff --git a/src/location/doc/snippets/declarative/routing.qml b/src/location/doc/snippets/declarative/routing.qml new file mode 100644 index 0000000..643722b --- /dev/null +++ b/src/location/doc/snippets/declarative/routing.qml @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [QtQuick import] +import QtQuick 2.3 +//! [QtQuick import] +import QtPositioning 5.5 +import QtLocation 5.6 + +Item { + width: 1000 + height: 400 + + Plugin { + id: aPlugin + name: "osm" + } + + RouteQuery { + id: aQuery + waypoints: [ + { latitude: -27.575, longitude: 153.088}, + { latitude: -27.465, longitude: 153.023} + ] + travelModes: RouteQuery.CarTravel + routeOptimizations: RouteQuery.ShortestRoute + } + + //! [Route Maneuver List1] + RouteModel { + id: routeModel + // model initialization + //! [Route Maneuver List1] + plugin: aPlugin + autoUpdate: true + query: aQuery + //! [Route Maneuver List2] + } + + + ListView { + id: listview + anchors.fill: parent + spacing: 10 + model: routeModel.status == RouteModel.Ready ? routeModel.get(0).segments : null + visible: model ? true : false + delegate: Row { + width: parent.width + spacing: 10 + property bool hasManeuver : modelData.maneuver && modelData.maneuver.valid + visible: hasManeuver + Text { text: (1 + index) + "." } + Text { text: hasManeuver ? modelData.maneuver.instructionText : "" } + //! [Route Maneuver List2] + property RouteManeuver routeManeuver: modelData.maneuver + property RouteSegment routeSegment: modelData + + //! [RouteManeuver] + Text { + text: "Distance till next maneuver: " + routeManeuver.distanceToNextInstruction + + " meters, estimated time: " + routeManeuver.timeToNextInstruction + " seconds." + } + //! [RouteManeuver] + + //! [RouteSegment] + Text { + text: "Segment distance " + routeSegment.distance + " meters, " + routeSegment.path.length + " points." + } + //! [RouteSegment] + //! [Route Maneuver List3] + } + } + //! [Route Maneuver List3] +} diff --git a/src/location/doc/snippets/places/main.cpp b/src/location/doc/snippets/places/main.cpp new file mode 100644 index 0000000..8820fbc --- /dev/null +++ b/src/location/doc/snippets/places/main.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "requesthandler.h" + +int main(int /*argc*/, char ** /*argv*/) +{ + return 0; +} + diff --git a/src/location/doc/snippets/places/places.pro b/src/location/doc/snippets/places/places.pro new file mode 100644 index 0000000..9fa4c7f --- /dev/null +++ b/src/location/doc/snippets/places/places.pro @@ -0,0 +1,5 @@ +TEMPLATE=app +TARGET=placescppsnippet +QT = core location +SOURCES+=main.cpp +HEADERS += requesthandler.h diff --git a/src/location/doc/snippets/places/requesthandler.h b/src/location/doc/snippets/places/requesthandler.h new file mode 100644 index 0000000..04b1b05 --- /dev/null +++ b/src/location/doc/snippets/places/requesthandler.h @@ -0,0 +1,580 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class RequestHandler : public QObject +{ +public: + void initializeManager() { + //! [Initialize Manager] + //The "provider name" is used to select a particular provider + QGeoServiceProvider *provider = new QGeoServiceProvider("provider name"); + QPlaceManager *manager = provider->placeManager(); + //! [Initialize Manager] + Q_UNUSED(provider); + Q_UNUSED(manager); + } + + void simpleSearch() + { + //! [Simple search] + //1) Make an appropriate request + QPlaceSearchRequest searchRequest; + searchRequest.setSearchTerm("ice cream"); + searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(12.34, 56.78))); + + //2) Use the manager to initiate a request and retrieve a reply object + QPlaceSearchReply * searchReply = manager->search(searchRequest); + + //3) Connect the reply object to a slot which is invoked upon operation completion + connect(searchReply, SIGNAL(finished()), this, SLOT(processSearchReply())); + //! [Simple search] + } + + void search() + { + //! [Search for places cpp] + + //instantiate request and set parameters + QPlaceSearchRequest searchRequest; + searchRequest.setSearchTerm("ice cream"); + searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(12.34, 56.78))); + + //send off a search request + /*QPlaceSearchReply * */ searchReply = manager->search(searchRequest); + + //connect a slot to handle the reply + connect(searchReply, SIGNAL(finished()), this, SLOT(handleSearchReply())); + + //! [Search for places cpp] + } + + void searchPaging() + { + //! [Search paging] + QPlaceSearchRequest searchRequest; + searchRequest.setLimit(15); //specify how many results are to be retrieved. + //! [Search paging] + } + + void details() + { + QPlace place; + //! [Details check] + if (!place.detailsFetched()) { + /*QPlaceDetailsReply * */ detailsReply = manager->getPlaceDetails(place.placeId()); + connect(detailsReply, SIGNAL(finished()), this, SLOT(handleDetailsReply())); + } + //! [Details check] + } + + void images() + { + QPlace place; + + //! [Image request] + QPlaceContentRequest request; + request.setContentType(QPlaceContent::ImageType); + request.setPlaceId(place.placeId()); + request.setLimit(5); + /*QPlaceContentReply * */ contentReply = manager->getPlaceContent(request); + connect(contentReply, SIGNAL(finished()), this, SLOT(handleImagesReply())); + //! [Image request] + } + + + void suggestion() + { + //! [Suggestion request] + QPlaceSearchRequest request; + request.setSearchTerm("piz"); + request.setSearchArea(QGeoCircle(QGeoCoordinate(12.34, 56.78))); + /* QPlaceSearchSuggestion * */suggestionReply = manager->searchSuggestions(request); + connect(suggestionReply, SIGNAL(finished()), this, SLOT(handleSuggestionReply())); + //! [Suggestion request] + } + + void savePlace() + { + //! [Save place pt1] + QPlace place; + place.setName( "Fred's Ice Cream Parlor" ); + + QGeoLocation location; + location.setCoordinate(QGeoCoordinate(12.34, 56.78)); + + QGeoAddress address; + address.setStreet("111 Nother Street"); + //! [Save place pt1] + + //! [Save place pt2] + location.setAddress(address); + place.setLocation(location); + + /* QPlaceIdReply * */savePlaceReply = manager->savePlace(place); + connect(savePlaceReply, SIGNAL(finished()), this, SLOT(handleSavePlaceReply())); + //! [Save place pt2] + } + + void removePlace() + { + QPlace place; + //! [Remove place] + /* QPlaceIdReply * */removePlaceReply = manager->removePlace(place.placeId()); + connect(removePlaceReply, SIGNAL(finished()), this, SLOT(handleRemovePlaceReply())); + //! [Remove place] + } + + void initializeCategories() + { + //! [Initialize categories] + /* QPlaceReply * */initCatReply = manager->initializeCategories(); + connect(initCatReply, SIGNAL(finished()), this, SLOT(handleInitCatReply())); + //! [Initialize categories] + } + + void saveCategory() + { + //! [Save category] + QPlaceCategory fastFood; + + QPlaceCategory category; + category.setName("pizza"); + /*QPlaceIdReply */ saveCategoryReply = manager->saveCategory(category); + connect(saveCategoryReply, SIGNAL(finished()), this, SLOT(handleSaveCategoryReply())); + + //we could have saved a category as a child by supplying a parent identifier. + saveCategoryReply = manager->saveCategory(category, fastFood.categoryId()); + //! [Save category] + } + + void removeCategory() + { + QPlaceCategory category; + //! [Remove category] + /* QPlaceIdReply * */removeCategoryReply = manager->removeCategory(place.placeId()); + connect(removeCategoryReply, SIGNAL(finished()), this, SLOT(handleRemoveCategoryReply())); + //! [Remove category] + } + + void searchRequest() { + QPlaceCategory diner; + QPlaceCategory restaurant; + + //! [Search request] + QPlaceSearchRequest searchRequest; + searchRequest.setSearchTerm("Fast food"); //search term for what we are interested in + + //set a search center + searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(2.3, 48.87))); + + //set a distance hint as a relevancy hint. + //closer places have greater weighting in the ranking of results. + searchRequest.setRelevanceHint(QPlaceSearchRequest::DistanceHint); + + //use limit to adjust pagination. + //this limits the number of place results to 5 per page. + searchRequest.setLimit(5); + + //provide some categories to narrow down search + QList categories; + categories << diner << restaurant; + searchRequest.setCategories(categories); + //! [Search request] + } + + void content() { + QPlace place; + //! [Content request] + QPlaceContentRequest request; + request.setContentType(QPlaceContent::ImageType); + request.setPlaceId(place.placeId()); + request.setLimit(5); + + QPlaceContentReply *contentReply = manager->getPlaceContent(request); + //..connect signals..// + + //! [Content request] + Q_UNUSED(contentReply); + } + + void contentConversion() + { + //! [Content conversion] + QPlaceImage image; + image.setUrl(QUrl("www.example.com")); + + QPlaceContent content = image; + + QPlaceImage image2; + image2 = content; + qDebug() << image2.url(); //image2.url() == "www.example.com" + //! [Content conversion] + } + + void icon() { + QPlace place; + //! [icon] + QUrl iconSourceUrl = place.icon().url(QSize(32,32)); + + //A default icon may also be requested like so + iconSourceUrl = place.icon().url(); + //! [icon] + } + + void saveBetweenManagers() { + QPlaceResult result; + QPlaceIdReply *saveReply; + //! [ Save to different manager] + //result retrieved from a different manager) + QPlace place = manager->compatiblePlace(result.place()); + saveReply = manager->savePlace(place); + //! [ Save to different manager] + saveReply->abort();//needed to avoid warnings + } + + void ratings() { + //! [Ratings] + qDebug() << QString("This place rated ") + place.ratings().average() + + "out of " + place.ratings().maximum() + "stars"; + //! [Ratings] + } + + void matchPlaces() { + QList results; + //! [Match places] + QPlaceMatchRequest request; + request.setResults(results); + QVariantMap parameters; + parameters.insert(QPlaceMatchRequest::AlternativeId, "x_id_here"); + request.setParameters(parameters); + matchReply = manager->matchingPlaces(request); + //! [Match places] + } + +public slots: + // ![Simple search handler] + //4) Have the slot appropriately process the results of the operation + void processSearchReply() { + if (searchReply->error() == QPlaceReply::NoError) { + foreach (const QPlaceSearchResult &result, searchReply->results()) { + if (result.type() == QPlaceSearchResult::PlaceResult) + qDebug() << "Title:" << result.title(); + } + } + + //5) Discard the rely object when done. + searchReply->deleteLater(); + searchReply = 0; + } + // ![Simple search handler] + + //! [Search for places handler cpp] + void handleSearchReply() { + if (searchReply->error() == QPlaceReply::NoError) { + foreach (const QPlaceSearchResult &result, searchReply->results()) { + if (result.type() == QPlaceSearchResult::PlaceResult) { + QPlaceResult placeResult = result; + qDebug() << "Name: " << placeResult.place().name(); + qDebug() << "Coordinate " << placeResult.place().location().coordinate().toString(); + qDebug() << "Street: " << placeResult.place().location().address().street(); + qDebug() << "Distance: " << placeResult.distance(); + } + } + } + searchReply->deleteLater(); //discard reply + searchReply = 0; + } + //! [Search for places handler cpp] + + //! [Details handler cpp] + void handleDetailsReply() { + QPlace place; + if (detailsReply->error() == QPlaceReply::NoError) + place = detailsReply->place(); + + detailsReply->deleteLater(); //discard reply + detailsReply = 0; + } + //! [Details handler cpp] + + //! [Image handler] + void handleImagesReply() { + if (contentReply->error() == QPlaceReply::NoError) { + QMapIterator iter(contentReply->content()); + while (iter.hasNext()) { + qDebug() << "Index: " << iter.key(); + QPlaceImage image = iter.value(); + qDebug() << image.url(); + qDebug() << image.mimeType(); + } + + //alternatively if indexes are irrelevant + foreach (const QPlaceImage &image, contentReply->content()) { + qDebug() << image.url(); + qDebug() << image.mimeType(); + } + + //we can assign content to the place that it belongs to. + //the place object serves as a container where we can retrieve + //content that has already been fetched + place.insertContent(contentReply->request().contentType(), contentReply->content()); + place.setTotalContentCount(contentReply->request().contentType(), contentReply->totalCount()); + } + + contentReply->deleteLater(); + contentReply = 0; + } + //! [Image handler] + + //! [Suggestion handler] + void handleSuggestionReply() { + if (suggestionReply->error() == QPlaceReply::NoError) { + foreach (const QString &suggestion, suggestionReply->suggestions()) + qDebug() << suggestion; + } + + suggestionReply->deleteLater(); //discard reply + suggestionReply = 0; + } + + //! [Suggestion handler] + + //! [Save place handler] + void handleSavePlaceReply() { + if (savePlaceReply->error() == QPlaceReply::NoError) + qDebug() << savePlaceReply->id(); + + savePlaceReply->deleteLater(); //discard reply + savePlaceReply = 0; + } + //! [Save place handler] + + //! [Remove place handler] + void handleRemovePlaceReply() { + if (removePlaceReply->error() == QPlaceReply::NoError) + qDebug() << "Removal of place identified by" + << removePlaceReply->id() << "was successful"; + + removePlaceReply->deleteLater(); //discard reply + removePlaceReply = 0; + } + //! [Remove place handler] + + //! [Initialize categories reply] + void handleInitCatReply() { + if (initCatReply->error() == QPlaceReply::NoError) + qDebug() << "Categories initialized"; + else + qDebug() << "Failed to initialize categories"; + + initCatReply->deleteLater(); + initCatReply = 0; + } + //! [Initialize categories reply] + + void categories() { + QPlaceCategory pizza; + //! [Top level categories] + QList topLevelCategories = manager->childCategories(); + foreach (const QPlaceCategory &category, topLevelCategories) + qDebug() << category.name(); + //! [Top level categories] + + //! [Child categories] + QList childCategories = manager->childCategories(pizza.categoryId()); + //! [Child categories] + } + + //! [Save category handler] + void handleSaveCategoryReply() { + if (saveCategoryReply->error() == QPlaceReply::NoError) { + qDebug() << "Saved category id =" << saveCategoryReply->id(); + } + + saveCategoryReply->deleteLater(); + saveCategoryReply = 0; + } + //! [Save category handler] + + //! [Remove category handler] + void handleRemoveCategoryReply() { + if (removeCategoryReply->error() == QPlaceReply::NoError) + qDebug() << "Removal of category identified by" + << removeCategoryReply->id() << "was successful"; + + removeCategoryReply->deleteLater(); //discard reply + removeCategoryReply = 0; + } + //! [Remove category handler] + + //! [Content handler] + void contentHandler() { + if (contentReply->error() == QPlaceReply::NoError) { + place.insertContent(contentReply->request().contentType(), + contentReply->content()); + } + } + //! [Content handler] + + void phoneNumbers() { + //! [Phone numbers] + if (place.contactTypes().contains(QPlaceContactDetail::Phone)) { + foreach (const QPlaceContactDetail &number, place.contactDetails(QPlaceContactDetail::Phone)) + qDebug() << number.label() << ":" << number.value(); + } + //! [Phone numbers] + } + + + void openingHours() { + //! [Opening hours] + if (place.extendedAttributeTypes().contains(QPlaceAttribute::OpeningHours)) + qDebug() << place.extendedAttribute(QPlaceAttribute::OpeningHours).text(); + //! [Opening hours] + } + + //! [Match places handler] + void matchHandler() { + if (matchReply->error() == QPlaceReply::NoError) { + foreach (const QPlace place, matchReply->places()) { + if (place != QPlace()) + qDebug() << "Place is a favorite with name" << place.name(); + else + qDebug() << "Place is not a favorite"; + } + } + + matchReply->deleteLater(); + matchReply = 0; + } + //! [Match places handler] + + void convertSearchResult() { + QPlaceSearchResult result; + //! [Convert search result] + if (result.type() == QPlaceSearchResult::PlaceResult) { + QPlaceResult placeResult = result; + qDebug() << placeResult.place().name(); + qDebug() << placeResult.place().location().coordinate(); + qDebug() << placeResult.distance(); + } + //! [Convert search result] + } + +QPlaceSearchReply *searchReply; +QPlaceManager *manager; +QPlaceDetailsReply *detailsReply; +QPlaceContentReply *contentReply; +QPlaceSearchSuggestionReply *suggestionReply; +QPlaceIdReply *savePlaceReply; +QPlaceIdReply *removePlaceReply; +QPlaceIdReply *saveCategoryReply; +QPlaceIdReply *removeCategoryReply; +QPlaceReply *initCatReply; +QPlaceMatchReply *matchReply; +QPlace place; +}; + +class ManagerEngine : public QObject +{ +}; + +//! [Implement reply pt1] +class SearchReply : public QPlaceSearchReply +{ +public: + explicit SearchReply(ManagerEngine *engine) + : QPlaceSearchReply(engine), m_engine(engine){} + + ~SearchReply(); + void setResults(const QList &results); + void setRequest(const QPlaceSearchRequest &request); +//! [Implement reply pt1] + +//! [Implement reply pt2] + void triggerDone(QPlaceReply::Error error = QPlaceReply::NoError, + const QString &errorString = QString()); + + ManagerEngine *m_engine; +}; +//! [Implement reply pt2] + +class SearchSuggestionReply : public QPlaceSearchSuggestionReply +{ +public: + void triggerDone(QPlaceReply::Error error = QPlaceReply::NoError, + const QString &errorString = QString()); + + ManagerEngine *m_engine; + +}; + +//! [Trigger done] +void SearchSuggestionReply::triggerDone(QPlaceReply::Error error, + const QString &errorString) +{ + if (error != QPlaceReply::NoError) { + this->setError(error,errorString); + QMetaObject::invokeMethod(m_engine, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply *,this), + Q_ARG(QPlaceReply::Error, error), + Q_ARG(QString, errorString)); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, error), + Q_ARG(QString, errorString)); + } + + this->setFinished(true); + QMetaObject::invokeMethod(m_engine, "finished", Qt::QueuedConnection, + Q_ARG(QPlaceReply *,this)); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); +} +//! [Trigger done] diff --git a/src/location/doc/snippets/snippets.pro b/src/location/doc/snippets/snippets.pro new file mode 100644 index 0000000..e4946c8 --- /dev/null +++ b/src/location/doc/snippets/snippets.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += places declarative cpp diff --git a/src/location/doc/src/cpp-qml.qdoc b/src/location/doc/src/cpp-qml.qdoc new file mode 100644 index 0000000..f20e147 --- /dev/null +++ b/src/location/doc/src/cpp-qml.qdoc @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page location-cpp-qml.html +\title Interfaces between C++ and QML Code in Qt Location + +\brief Some of the location QML types providing interfaces to access and modify properties in C++. + +\section2 Category - QPlaceCategory +The \l {Category::category} {Category.category} property is used to provide an interface between C++ and QML code. First a pointer to a +Category object must be obtained from C++, then use the \l {QObject::property()}{property()} and +\l {QObject::setProperty()}{setProperty()} functions to get and set the \c category property. +The following gets the QPlaceCategory representing this object from C++: +\snippet cpp/cppqml.cpp Category get +The following sets the properties of this object based on a QPlaceCategory object from C++: +\snippet cpp/cppqml.cpp Category set + + +\section2 ContactDetail - QDeclarativeContactDetail +The \l {ContactDetail::contactDetail} {ContactDetail.contactDetail} property is used to provide an interface between C++ and QML code. First a pointer to a ContactDetail object must be obtained from C++, then use the +\l {QObject::property()}{property()} and \l {QObject::setProperty()}{setProperty()} functions +to get and set the \c contactDetail property. +The following gets the QPlaceContactDetail representing this object from C++: +\snippet cpp/cppqml.cpp ContactDetail get +The following sets the properties of this object based on a QPlaceContactDetail object from +C++: +\snippet cpp/cppqml.cpp ContactDetail set + + +\section2 Place - QPlace +The \l {Place::place} {Place.place} property is used to provide an interface between C++ and QML code. First a pointer to a Place object must be obtained from C++, then use the +\l {QObject::property()}{property()} and \l {QObject::setProperty()}{setProperty()} functions +to get and set the \c place property. +The following gets the QPlace representing this object from C++: +\snippet cpp/cppqml.cpp Place get +The following sets the properties of this object based on a QPlace object from C++: +\snippet cpp/cppqml.cpp Place set + + + +\section2 PlaceAttribute - QPlaceAttribute +The \l {PlaceAttribute::attribute} {PlaceAttribute.attribute} property is used to provide an interface between C++ and QML code. First a pointer to a +PlaceAttribute object must be obtained from C++, then use the +\l {QObject::property()}{property()} and \l {QObject::setProperty()}{setProperty()} functions +to get and set the \c attribute property. +The following gets the QPlaceAttribute representing this object from C++: +\snippet cpp/cppqml.cpp PlaceAttribute get +The following sets the properties of this object based on a QPlaceAttribute object from C++: +\snippet cpp/cppqml.cpp PlaceAttribute set + + +\section2 Icon - QPlaceIcon +The \l {Icon::icon} {Icon.icon} property is used to provide an interface between C++ and QML code. First a pointer to a Icon object must be obtained from C++, then use the \l {QObject::property()}{property()} and +\l {QObject::setProperty()}{setProperty()} functions to get and set the \c icon property. +The following gets the QPlaceIcon representing this object from C++: +\snippet cpp/cppqml.cpp Icon get +The following sets the properties of this object based on a QPlaceIcon object from C++: +\snippet cpp/cppqml.cpp Icon set + + +\section2 User - QPlaceUser +The \l {User::user} {User.user} property is used to provide an interface between C++ and QML code. First a pointer to a +User object must be obtained from C++, then use the \l {QObject::property()}{property()} and +\l {QObject::setProperty()}{setProperty()} functions to get and set the \c user property. +The following gets the QPlaceUser representing this object from C++: +\snippet cpp/cppqml.cpp User get +The following sets the properties of this object based on a QPlaceUser object from C++: +\snippet cpp/cppqml.cpp User set + + +\section2 Ratings - QPlaceRatings +The \l {Ratings::ratings} {Ratings.ratings} property is used to provide an interface between C++ and QML code. First a pointer to a +Ratings object must be obtained from C++, then use the \l {QObject::property()}{property()} and +\l {QObject::setProperty()}{setProperty()} functions to get and set the \c ratings property. +The following gets the QPlaceRating representing this object from C++: +\snippet cpp/cppqml.cpp Ratings get +The following sets the properties of this object based on a QPlaceRatings object from C++: +\snippet cpp/cppqml.cpp Ratings set + + +\section2 Supplier - QPlaceSupplier +The \l {Supplier::supplier} {Supplier.supplier} property is used to provide an interface between C++ and QML code. First a pointer to a +Supplier object must be obtained from C++, then use the \l {QObject::property()}{property()} and +\l {QObject::setProperty()}{setProperty()} functions to get and set the \c supplier property. +The following gets the QPlaceSupplier representing this object from C++: +\snippet cpp/cppqml.cpp Supplier get +The following sets the properties of this object based on a QPlaceSupplier object from C++: +\snippet cpp/cppqml.cpp Supplier set + +*/ diff --git a/src/location/doc/src/example-parameters.qdocinc b/src/location/doc/src/example-parameters.qdocinc new file mode 100644 index 0000000..2ae351b --- /dev/null +++ b/src/location/doc/src/example-parameters.qdocinc @@ -0,0 +1,12 @@ +The example can work with any of the available geo services plugins. However, some +plugins may require additional \l {QtLocation::PluginParameter}{plugin parameters} in order to +function correctly. \l {QtLocation::PluginParameter}{Plugin parameters} can be passed on the +command line using the \c {--plugin} argument, which takes the form: + +\badcode + --plugin. +\endcode + +Refer to the documentation for each of the geo services plugins for details on what plugin +parameters they support. The default plugin used by this example is +\l {Qt Location Open Street Map Plugin}, which does not require any parameters. diff --git a/src/location/doc/src/maps.qdoc b/src/location/doc/src/maps.qdoc new file mode 100644 index 0000000..759394e --- /dev/null +++ b/src/location/doc/src/maps.qdoc @@ -0,0 +1,250 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +/*! +\page location-maps-qml.html +\title Maps and Navigation (QML) + +\brief Provides QtQuick user interfaces for displaying, navigating and + interacting with maps, as well as geocoding and navigation. + +\b{Maps and Navigation} provides QtQuick user interface types for +displaying geographic information on a map, as well as allowing user +interaction with map overlay objects and the display itself. It also +contains utilities for geocoding (finding a geographic coordinate from a +street address) and navigation (including driving and walking directions). + +It builds upon the API concepts and types in the \l{Positioning (QML)}{QML Positioning API}. +A more hands-on introduction of the Maps and Navigation types can be found in the +\l {QML Maps}{Maps and Navigation tutorial}. + +\section1 Maps + +\section2 Displaying Maps + +Displaying a map is done using the \l{QtLocation::Map}{Map} QML types. The Map type supports +user interaction through the \l{QtLocation::MapGestureArea}{MapGestureArea} QML type. The Map +object draws the map on-screen using OpenGL (ES), allowing for hardware-accelerated rendering +where available. + +\b{Key Types} +\table + \row + \li \l{QtLocation::Plugin}{Plugin} + \li A location-based services plugin provides data including map data which is then displayed in a Map object. + \row + \li \l{QtLocation::Map}{Map} + \li QtQuick item to display a map on-screen. + \row + \li \l{QtLocation::MapGestureArea}{MapGestureArea} + \li Interaction helper for panning, flicking and pinch-to-zoom gesture on a Map. +\endtable + +Note that the client must create a \l{QtLocation::Plugin}{Plugin} object +prior to using a \l{QtLocation::Map}{Map} type in order to have access +to map data to display. + +\section2 Putting Objects on a Map (Map Overlay Objects) + +Maps can also contain map overlay objects, which are used to display information +on its surface. There is a set of basic pre-defined map overlay objects, as well +as the ability to implement custom map overlay objects using the +\l{QtLocation::MapQuickItem}{MapQuickItem} type, which can contain any +standard QtQuick item. + +\b{Key Types} +\table + \row + \li \l{QtLocation::MapCircle}{MapCircle} + \li A geographic circle (all points at a set distance from a center), optionally with a border. + \row + \li \l{QtLocation::MapRectangle}{MapRectangle} + \li A rectangle whose top left and bottom right points are specified as + \l {coordinate} types, optionally with a border. + \row + \li \l{QtLocation::MapPolygon}{MapPolygon} + \li A polygon made of an arbitrary list of \l {coordinate}{coordinates}. + \row + \li \l{QtLocation::MapPolyline}{MapPolyline} + \li A polyline made of an arbitrary list of \l {coordinate}{coordinates}. + \row + \li \l{QtLocation::MapQuickItem}{MapQuickItem} + \li Turns any arbitrary QtQuick Item into a map overlay object. MapQuickItem is an enabler for specifying custom map overlay objects. +\endtable + +\section2 Model-View Design with Map Overlay Objects + +To automatically generate map overlay objects based on the contents of a QtQuick +model (for example a ListModel item), the \l{QtLocation::MapItemView}{MapItemView} +type is available. It accepts any map overlay object as its delegate, and can +only be created within a \l{QtLocation::Map}{Map}. + +\b{Key Types} +\table + \row + \li \l{QtLocation::MapItemView}{MapItemView} + \li Populates a Map with map overlay objects based on the data provided by a model. +\endtable + +\section2 Interaction with Map Overlay Objects + +Properties of map overlay objects that influence their appearance on the display can +be changed at any time, and many can also be used in animations. Animating +coordinate-based map overlay objects, such as MapPolygon and MapPolyline, is not yet +available. + +\section1 Geocoding -- Address to Coordinate and Vice Versa + +Geocoding is the translation of geographic coordinates into addresses, or vice +versa. Such a translation usually involves sending the source data to a server +which then performs the translation and returns the results, although some +location-based service provider \l{QtLocation::Plugin}{plugins} may be able to +provide some geocoding functionality without sending data to a remote server. +The availability and accuracy of the translation usually depends on the location +or address being translated, as different areas of the Earth are mapped to +varying degrees of accuracy. + +A geocoding query in QML is performed using the +\l{QtLocation::GeocodeModel}{GeocodeModel} type. For an address-to-coordinate +query, its \c{query} property may be set to either an +\l [QtPositioning]{Address} object or a string containing the textual +form of the address to search for. To perform the reverse, the same property +can be set to a \l {coordinate} instead. Results are made available in the +contents of the model. + +\b{Key Types} +\table + \row + \li \l{QtLocation::Plugin}{Plugin} + \li A location-based services plugin provides data including geocoding translation results which are exposed to clients via a GeocodeModel. + \row + \li \l{QtLocation::GeocodeModel}{GeocodeModel} + \li Queries the Plugin for geocoding translations and provides access to results via indexes in the model. + \row + \li \l[QtPositioning]{Address} + \li Structured address for use in queries and results of geocoding. +\endtable + +Note that the client must create a \l{QtLocation::Plugin}{Plugin} object +prior to using a \l{QtLocation::GeocodeModel}{GeocodeModel} object. This +will enable access to geocoding translation services and thus data to display. + +\section1 Routing and Navigation + +Routing is the determination of a navigable path from one point to another on +a map. Given a map that is aware of features that aid or hinder navigation, such as +bridges, waterways and so on, a series of segments that make +up the journey can be constructed. If these \l {RouteSegment}s are simple then we can +add navigation information at the connecting points, \l {RouteManeuver}s, +between the segments. + +\b{Key Types} +\table + \row + \li \l{QtLocation::Route}{Route} + \li The entire path to be navigated. + \row + \li \l{QtLocation::RouteSegment}{RouteSegment} + \li The individual components of a route. + \row + \li \l{QtLocation::RouteManeuver}{RouteManeuver} + \li The navigation information that joins segments. + \row + \li \l{QtLocation::RouteModel}{RouteModel} + \li The means of making requests on the backend to supply route + information. +\endtable + + + + + + +*/ + + +/*! +\page location-maps-cpp.html +\title Maps and Navigation (C++) + +\brief Provides C++ classes for Geocoding and Navigation. + +\b{Maps and Navigation} provides C++ utilities for geocoding (finding a +geographic coordinate from a street address) and navigation (including driving +and walking directions). + +Currently it is not possible to interact with maps via C++. Mapping applications +must use the \l {Maps and Navigation (QML)} API. + + +\section1 Geocoding + +In C++, an address-to-coordinate query is performed using the +\l{QGeoCodingManager::geocode()}{geocode()} method of the QGeoCodingManager +class. For coordinate-to-address queries, the +\l{QGeoCodingManager::reverseGeocode()}{reverseGeocode()} method is available +on the same class. Instances of QGeoCodingManager are available via +\l{QGeoServiceProvider}. + +\b{Key Classes} +\table + \row + \li \l{QGeoServiceProvider} + \li Provides a QGeoCodingManager instance ready for use. + \row + \li \l{QGeoCodingManager} + \li Accepts queries and produces QGeoCodeReply objects. + \row + \li \l{QGeoCodeReply} + \li Contains the results of a geocoding query. +\endtable + +\section1 Navigation + +In C++, a route query is performed using the \l{QGeoRoutingManager::calculateRoute()}{calculate()} +method of the QGeoRoutingManager class. The returned route reply can contain +multiple routes to the same destination. + +\b{Key Classes} +\table + \row + \li \l{QGeoServiceProvider} + \li Provides a QGeoCodingManager instance ready for use. + \row + \li \l{QGeoRoutingManager} + \li Accepts queries and produces QGeoRouteReply objects. + \row + \li \l{QGeoRouteReply} + \li Contains the results of a routing query. + \row + \li \l{QGeoRoute} + \li Contains information about a route. +\endtable + + +*/ diff --git a/src/location/doc/src/place-caveats.qdocinc b/src/location/doc/src/place-caveats.qdocinc new file mode 100644 index 0000000..d3d9bd0 --- /dev/null +++ b/src/location/doc/src/place-caveats.qdocinc @@ -0,0 +1,21 @@ + The Places API is currently designed for only saving \a {core} details. Saving rich content like + images and reviews or details like supplier and rating is not a supported use case. Typically a manager + will generally ignore these fields upon save and may produce a warning message if they are populated. + + The Places API only supports saving of the following \e {core details}: + \list + \li name + \li place id + \li location + \li contact details + \li icon + \li categories (tag-like names to describe a place) + \li visibility scope + \endlist + + It is possible that providers may only support a subset of these. + See the \l {Qt Location#Plugin References and Parameters}{plugin documentation} for more + details. + + Saving of properties such as the rating, extended attributes, + images, reviews, editorials and supplier is explicitly not supported by the Places API. diff --git a/src/location/doc/src/place-crossref.qdocinc b/src/location/doc/src/place-crossref.qdocinc new file mode 100644 index 0000000..f0502f4 --- /dev/null +++ b/src/location/doc/src/place-crossref.qdocinc @@ -0,0 +1,7 @@ + \code + origin R/O manager(here) destination R/W manager (places_jsondb) + Save + Place id: ae246 ---> Place id: 0001 + Attribute type: x_provider Attribute type: x_id_here + Attribute value: here Attribute text value: ae246 + \endcode diff --git a/src/location/doc/src/place-definition.qdocinc b/src/location/doc/src/place-definition.qdocinc new file mode 100644 index 0000000..2398775 --- /dev/null +++ b/src/location/doc/src/place-definition.qdocinc @@ -0,0 +1,27 @@ +A place is a point of interest, it could be a favorite restaurant, a park or someone's home. +A QPlace object represents a place by acting as a container for various information about that place. + +This information can be divided into 2 broad classifications + +\list +\li Details +\li Rich content +\endlist + +The place details consist of properties of the place, such as the name, +location, contact information and so on. When a place is returned during a +search, these details are filled in. Sometimes in order to save bandwidth, +there are further details about the place that can be retrieved on an +individual place by place basis, if the user is interested. The +QPlace::detailsFetched() function can be queried to see if all available +details have been fetched, and if not, QPlaceManager::getPlaceDetails() can +be used to retrieve them. Precisely which details are populated during a +search and which need to be fetched individually may vary from provider to +provider. See \l {Qt Location#Plugin References and Parameters}{plugin documentation} for +more details. + +The rich content of a place consists of items such as images, reviews and +editorials. Potentially there may be many rich content items, so they are +treated separately from the place details. They can be retrieved in a paged +fashion via QPlaceManager::getPlaceContent(). If necessary, the content may +be assigned to a place so it can act as a convenient container. diff --git a/src/location/doc/src/places.qdoc b/src/location/doc/src/places.qdoc new file mode 100644 index 0000000..72e31c9 --- /dev/null +++ b/src/location/doc/src/places.qdoc @@ -0,0 +1,433 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page location-places-qml.html + \title QML Places API + + \section1 Overview + + The Places API allows users to discover places of interest and view + details about them, such as address and contact information. Some places may have + additional content associated with them, such as images and reviews. + The Places API also facilitates management of places and + categories, allowing users to save and remove them. + + \section1 Introductory Concepts + + \section2 Plugin + A \l Plugin is an abstraction for a backend. One \l Plugin might access places from a + REST server while another may access places from a local database. The following + instantiates a \l Plugin object by providing a name of "osm". The \l Plugin name + identifies which backend to choose from. Plugins may also be provided with a set of + \l {PluginParameter} {parameters}, which essentially takes the form of a set of + key-value pairs. The \l {PluginParameter} {parameters} that can be specified vary + among the different \l Plugin backends. For documentation on the possible \l + {PluginParameter} {parameters} and nuances of each \l Plugin, see the \l {Plugin + references and parameters}{Plugin References}. + + \snippet places_list/places_list.qml Initialize Plugin + + \note The HERE plugin must be supplied with some mandatory parameters as outlined + in the \l {Mandatory Parameters} {HERE Plugin} documentation. + + \section2 Models, Views and Delegates + The QML Places API is built around the notion of models, views and delegates. + + \table + \row + \li \b Model + \li A model holds data items and maintains their structure. + The model is also responsible for retrieving the items from a data source. + \row + \li \b View + \li A view is a visual container that displays the data and manages how visual + items are shown such as in a list or a grid. The view may also + be responsible for navigating the data, for example, scrolling through + the visual items during a flicking motion. + \row + \li \b Delegate + \li A delegate defines how individual data elements should appear + as visual items in the view. The models expose a set of data roles + and the delegate uses them to construct a visual item. The delegate + may also define behaviour such as an operation to invoke when a visual + item is clicked. + \endtable + + The Common Use Cases section below demonstrates concrete examples of how + these concepts fit together. + + \section1 Common Use Cases + + \section2 Searching for Places + Searching is accomplished via the \l PlaceSearchModel. The \l + {PlaceSearchModel::plugin} {plugin} property specifies which backend to + perform search operations against. Search parameters may be provided + through properties such as the \l {PlaceSearchModel::searchTerm} + {searchTerm} and \l {PlaceSearchModel::searchArea} {searchArea}. A search + operation can then be started by invoking the \l {PlaceSearchModel::update} + {update()} method. For simplicity, the snippet below invokes \l + {PlaceSearchModel::update} {update()} once construction of the model as + been completed, typically \l {PlaceSearchModel::update} {update()} would be + invoked in response to a user action such as a button click. While the + search operation is underway the \l {PlaceSearchModel::status} property + transitions into the \c Loading state and when successfully completed moves + into the \c Ready state. + + \snippet places_list/places_list.qml PlaceSearchModel + + \section2 Display Search Results using a ListView + A \l ListView can be used to show the search results found by the model. + It defines the visual region for where the results are shown, and in the + case below fills the entirety of its parent. The \l ListView has built in + behavior that enables the region to respond to flicking events and to + scroll appropriately. + + In the snippet below, the search model has been assigned to the ListView's + \l {ListView::model} {model} property. When the model is updated with new + results, the \l ListView is automatically updated to reflect the model's new + data items. + + A simple delegate has been bound to the \l {ListView}'s \l + {ListView::delegate} {delegate} property. The \l PlaceSearchModel exposes + a set of \l {PlaceSearchModel Roles} {roles} of which the \e title and \e + place roles have been used below, these are of type string and \l Place + respectively. Essentially for each data item that should be visible in the + view, the view invokes the delegate to create a visual representation of + the item. + + \table + \row + \li + \snippet places_list/places_list.qml Places ListView + \li + \inlineimage places_list.png + \endtable + + \note For simplicty's sake we have assumed that every search result is of + \l {Search Result Types} {type} \c PlaceSearchResult and so always have + access to the \e place role, other search result types may not have a + \e place role. + + See the \l {Places List(QML)} {Places List} example for full source code. + + \section2 Display Search Results using a MapItemView + Instead of a \l ListView, the \l PlaceSearchModel can be used in + conjunction with a \l MapItemView to display markers on a map. Firstly a + \l Map is used to define the visual region occupied by the map, in this + case it fills the entirety of its parent. Other properties are specified + such as the \l {Map::plugin} {plugin} providing the maps, and the map's \l + {Map::center} {center} and \l {Map::zoomLevel} {zoomLevel}. + + Inside the \l Map, a \l MapItemView is declared, where the \l + {MapItemView::model} {model} property has been set to the search model and + a \l {MapItemView::delegate} {delegate} consisting of a \l MapQuickItem is + used to display a marker image. A marker is shown for every place that + was found by the search model. The delegate uses the \e place role + to position the marker. + + \table + \row + \li + \snippet places_map/places_map.qml Places MapItemView + \li + \inlineimage places_map.png + \endtable + + \note For simplicty's sake we have assumed that every search result is of + \l {Search Result Types} {type} \c PlaceSearchResult and so always have + access to the \e place role, other search result types may not have a + \e place role. + + See the \l {Places Map(QML)} {Places Map} example for full source code. + + \section2 Fetching Place Details + In order to save bandwidth, sometimes a backend will only return places which + are partially populated with details. This can be checked with the + Place::detailsFetched property which indicates whether all availalable details + have been fetched or not. If not, the Place::getDetails() method can be invoked + to fetch the remaining details. + + \snippet declarative/places.qml Place fetchDetails + + \section2 Saving and Removing Places + Some backends may support saving and removing places. This can be done by + calling the Place::save() and Place::remove() methods respectively. Note + that in order to save a \l Place, a \l Plugin must be assigned to specify + which backend we are saving to. The \l {Place::status} {status} property will + transition into the \c Saving state while the save operation is happening and on + successful completion will move to the \c Ready state. The following + snippet shows how to save and remove a place using javascript. + + \snippet declarative/places.qml Place createAndSavePlace + \codeline + \snippet declarative/places.qml Place removePlace + + \section2 Learn More + The above snippets only exhibit a small subset of Places functionality. + Refer to the \l {Places Types} shown below for richer content such as \l {ImageModel} {images}, \l {ReviewModel} {reviews} etc, as well as more indepth descriptions and explanations. + + See also the \l {Places (QML)}{Places (QML)} example for a more comprehensive demonstration on + how to use the API. + + \section1 Places Types + \section2 Data Types + \annotatedlist qml-QtLocation5-places-data + + \section2 Models + \annotatedlist qml-QtLocation5-places-models +*/ + +/*! + \page location-places-cpp.html + \title Places (C++) + + \section1 Overview + + The Places API allows users to discover places/points of interest + and view details about them such as address and contact information; + some places may even have rich content such as images and reviews. + The Places API also facilitates management of places and + categories, allowing users to save and remove them. + + \section1 Place Definition + \include place-definition.qdocinc + + \section1 Common Operations + + \section2 Initializing a Manager + All places functionality is facilitated by a QPlaceManager instance. One must specify + a QGeoServiceProvider in order to create the QPlaceManager + + \snippet places/requesthandler.h Initialize Manager + + \section2 Discovery/Search + + In order to perform a search operation we simply create a QPlaceSearchRequest + and set the desired search parameters, such as a search term and search center. + + \snippet places/requesthandler.h Search for places cpp + + The request is an asynchronous operation so we need a slot to handle the + completion of the request. In the handler we check that there are no errors and that our search result + type is a place. If so we can then retrieve some of the core details of the + place. At the end of the slot, we delete the reply since they are for single use only. + + \snippet places/requesthandler.h Search for places handler cpp + + \b {Note:} Depending upon the plugin backend that was chosen, the search results may contain places + which have further details that can be fetched on a place by place basis. To fetch these other details + see \l {Fetching Place Details}. + + \section3 Recommendations + Recommendations can be retrieved by supplying a place id via QPlaceSearchRequest::setRecommendationId(). + Any places similar to the given place are retrieved. + + \section3 Paging + If the plugin supports paging, the limit parameter may be provided to the search request. + \snippet places/requesthandler.h Search paging + + \section2 Fetching Place Details + A place that has been returned from a search request may have more details + that can be fetched. The following demonstrates how to check if there + are further details and if so how to request them. + + \snippet places/requesthandler.h Details check + \dots + \dots + \snippet places/requesthandler.h Details handler cpp + + \section2 Fetching Rich Content + Rich content such as images and reviews is retrieved through the manager and then if required assigned to a place. + \snippet places/requesthandler.h Image request + + We can handle the content request as shown below. + \snippet places/requesthandler.h Image handler + + It is important to note that the results in the QPlaceContentReply, + is a QPlaceContent::Collection which is essentially a QMap. The key \c {int} in this case is the + index of the content, and the value is the content itself. Due to the way Content is implemented + it is possible to convert a content type as follows + \code + QPlaceImage image = content; //provided that 'content' has a type QPlace::ImageType + \endcode + + The usage of the QPlaceContent::Collection and the conversion between content and its subtypes means + that code for handling the mechanics of paging reviews, images and editorials can be easily shared. + + \section2 Search Suggestions + The retrieval of search term suggestions is very similar to performing a place search. A QPlaceSearchRequest + is used just like a place search, the only difference being that the search term is set to a + partially completed string. + + \snippet places/requesthandler.h Suggestion request + And when the request is done, we can use the reply to show the suggestions. + \snippet places/requesthandler.h Suggestion handler + + \target Saving a place cpp + \section2 Saving a Place + The saving of a new place is performed as follows, we create a QPlace instance + and populate it with information such as a name, address and coordinate. Once + done we can invoke QPlaceManager::savePlace() to begin a save operation. + \snippet places/requesthandler.h Save place pt1 + \dots + \snippet places/requesthandler.h Save place pt2 + + Once a place is saved the reply contains the new identifier for that place. + \snippet places/requesthandler.h Save place handler + + Note that to save an already \e existing place, the QPlace::placeId() must + be filled in with the correct identifier. Otherwise a new place will be created if empty or the + wrong place overwritten if the identifier is incorrect. + + When a place is saved, the QPlaceManager may emit QPlaceManager::placedAdded() or QPlaceManager::placeUpdated() + signals. However whether a manager does so or not is provider specific, managers accessing places + from a web service will typically not emit these signals while managers accessing places locally stored generally will. + + \section3 Caveats + \input place-caveats.qdocinc + + \section3 Saving Between Managers + When saving places between managers, there are a few things to be aware of. + Some fields of a place such as the id, categories and icons are manager specific entities + for example the categories in one manager may not be recognized in another. + Therefore trying to save a place directly from one manager to another is not possible. + + The typical approach is to use the QPlaceManager::compatiblePlace() function, + it creates a copy of a place, but only copies data that the manager supports. + Manager specific data such as the place identifier is not copied over. The new + copy is now suitable for saving into the manager. If the manager supports matching by alternative + identifiers, an alternative identifier attribute is assigned to the copy (see \l {Matching places between managers}) + + \snippet places/requesthandler.h Save to different manager + + \target Removing a place cpp + \section2 Removing a Place + The removal of a place is performed as follows: + \snippet places/requesthandler.h Remove place + \dots + \dots + \snippet places/requesthandler.h Remove place handler + + When a place is removed, the QPlaceManager may emit the QPlaceManager::placeRemoved() signal. Whether a + manager does so is provider specific. Managers accessing places from a web service will typically not emit + these signals, while managers accessing places stored locally generally will. + + \section2 Using Categories + + Categories are keywords that can describe a place. For example, 'park', 'theater', + 'restaurant'. A place could be described by many categories, it could be a park and a music venue and a ferry or bus stop. + + To use categories they must first be initialized. + \snippet places/requesthandler.h Initialize categories + \dots + \dots + \snippet places/requesthandler.h Initialize categories reply + + After the categories have been initialized we can then use these category functions. + \list + \li QPlaceManager::childCategories() + \li QPlaceManager::category() + \li QPlaceManager::parentCategoryId() + \li QPlaceManager::childCategoryIds(); + \endlist + + To retrieve the top level categories + we use the QPlaceManager::childCategories() function but do not provide + a category identifier. + + \snippet places/requesthandler.h Top level categories + + If we did provide an identifier then we could retrieve a category's children. + + \snippet places/requesthandler.h Child categories + + \section2 Saving a Category + The following shows how to save a category + \snippet places/requesthandler.h Save category + \dots + \dots + \snippet places/requesthandler.h Save category handler + + When a category is saved, the QPlaceManager may emit QPlaceManager::categoryAdded() or QPlaceManager::categoryUpdated() + signals. However whether a manager does so or not is provider specific, managers accessing places + from a web service will typically not emit these signals while managers accessing places locally stored generally will. + + + \section2 Removing a Category + Category removal is very similar to removing a place + \snippet places/requesthandler.h Remove category + \dots + \dots + \snippet places/requesthandler.h Remove category handler + + When a category is removed, the QPlaceManager may emit the QPlaceManager::categoryRemoved() signal. Whether a + manager does so is provider specific. Managers accessing places from a web service will typically not emit + these signals, while managers accessing places stored locally generally will. + + \section2 Matching Places Between Managers + Sometimes you may want to cross reference whether places from one manager match those from another manager. + Such a situation may arise where one manager provides read-only access to places (origin manager) while another second r/w + manager (destination manager) is used to save selected favorites from the first. During a search + of the origin manager we may want to know which ones have been 'favorited' into the destination manager and perhaps display + a customized favorite name rather than the original name. + + The matching mechanism can vary between managers, but is typically accomplished through an alternative identifier. + As part of the save process, the place identifier from the origin manager is saved as an alternative identifier attribute in the destination manager + (which can have its own place identifier scheme). In the following example, the origin manager is from the 'here' QGeoServiceProider, therefore + as part of the saving process an alternative identifier attribute, x_id_here, is set for the place saved into the destination manager + (when QPlaceManager::compatiblePlace() is called) + + \input place-crossref.qdocinc + + In order to perform the matching, we create a QPlaceMatchRequest and assign it the search results from the origin manager. + The QPlaceMatchRequest will be used on the destination manager to return corresponding places. We also specify + matching parameters which are key value pairs. As mentioned previously, this can vary depending on the manager but typically + the key is QPlaceMatchRequest::AlternativeId to indicate we are matching by alternative id, the value in this case would be + x_id_here which specifies which alternative identifier attribute we are using to do the matching. + + \snippet places/requesthandler.h Match places + \dots + \dots + \snippet places/requesthandler.h Match places handler + + \section1 Classes in Places + + \section2 Data Classes + \annotatedlist QtLocation-places-data + + \section2 Request Classes + \annotatedlist QtLocation-places-requests + + \target Places Reply Classes + \section2 Reply classes + \annotatedlist QtLocation-places-replies + + \section2 Manager Classes + \annotatedlist QtLocation-places-manager +*/ + diff --git a/src/location/doc/src/plugins/mapbox.qdoc b/src/location/doc/src/plugins/mapbox.qdoc new file mode 100644 index 0000000..6cd326b --- /dev/null +++ b/src/location/doc/src/plugins/mapbox.qdoc @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Canonical Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page location-plugin-mapbox.html +\title Qt Location Mapbox Plugin +\ingroup QtLocation-plugins + +\brief Uses Mapbox for location services. + +\section1 Overview + +This geo services plugin allows applications to access +\l {http://mapbox.com}{Mapbox} location based services using the Qt Location API. +The use of these services is governed by the \l {https://www.mapbox.com/tos}{Mapbox terms of service}. +An access token is required to use these services. +Data is provided by \l {https://www.mapbox.com/about/maps}{OpenStreetMap and others}. + +The Mapbox geo services plugin can be loaded by using the plugin key "mapbox". + +\section1 Parameters + +\section2 Mandatory parameters +The following table lists mandatory parameters that \e must be passed to the Mapbox plugin. +\table +\header + \li Parameter + \li Description +\row + \li mapbox.access_token + \li \l{https://www.mapbox.com/help/define-access-token/}{Access token} provided by Mapbox. +\row + \li mapbox.map_id + \li \l{https://www.mapbox.com/help/define-map-id/}{ID} of the Mapbox map to show. An example ID is "examples.map-zr0njcqy". +\endtable + +The Mapbox geo services plugin requires an access token and map ID to use the +Mapbox services. To create a Mapbox account visit +\l{https://www.mapbox.com/#signup}. + +\section2 Optional parameters +The following table lists optional parameters that can be passed to the Mapbox plugin. +\table +\header + \li Parameter + \li Description +\row + \li mapbox.format + \li Data format to download tiles in, available values are "png", "png32", + "png64", "png128", "png256", (PNG with full, 32, 64, 128 and 256 color palette) + "jpg70", "jpg80", "jpg90" (JPEG with 70%, 80% and 90% compression). + Defaults to "png". +\row + \li useragent + \li User agent string set when making network requests. +\endtable +*/ diff --git a/src/location/doc/src/plugins/nokia.qdoc b/src/location/doc/src/plugins/nokia.qdoc new file mode 100644 index 0000000..1ed5e6e --- /dev/null +++ b/src/location/doc/src/plugins/nokia.qdoc @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page location-plugin-here.html +\title Qt Location HERE Plugin +\ingroup QtLocation-plugins + +\brief Uses the relevant services provided by HERE. + +\section1 Overview + +Included with Qt Location is a geo services plugin which accesses the relevant HERE services +provided by HERE/Nokia. The use of these services is governed by the terms and conditions +available at \l {https://developer.here.com/terms-conditions}. + +Note that accepting the terms and conditions only applies those terms and conditions to the use of +the HERE geo services plugin and does not limit the use of the other geo services plugins that may +be included with Qt. + +The HERE geo services plugin can be loaded by using the plugin key "here". + +The online plugin uses the tiled map classes, which caches tile data in heap memory and texture +memory. + +\section1 Parameters + +\section2 Mandatory parameters +The following table lists mandatory parameters that \e must be passed to the HERE plugin. +\table +\header + \li Parameter + \li Description +\row + \li here.app_id + \li Client \e app_id part of the app_id/token pair used for authentication by all managers. +\row + \li here.token + \li Client \e token part of the app_id/token pair for the service used for authentication by all managers. +\endtable + +The HERE geo services plugin requires an application id and token pair to authenticate the +application with the HERE services. To obtain an application id and token pair visit +\l{https://developer.here.com/} + +\section2 Optional parameters +The following table lists optional parameters that can be passed to the HERE plugin. + +\note Since Qt 5.5 all parameters below must be prefixed with \c here. Previous versions did not require +a prefix. + +\table +\header + \li Parameter + \li Description +\row + \li here.proxy + \li Proxy server URL used by all managers. For usage of the system proxy just pass "system" as value. + + \note See the notes in \l{QNetworkProxyFactory::systemProxyForQuery()} for further information. +\row + \li here.mapping.host + \li Base map tile service URL used by mapping manager. +\row + \li here.mapping.host.aerial + \li Aerial map tile service URL used by mapping manager. For all satellite, hybrid and terrain schemes. +\row + \li here.mapping.cache.directory + \li Absolute path to map tile cache directory used as network disk cache. + + The default place for the cache is \c{QtLocation/here} directory in \l {QStandardPaths::writableLocation()} {QStandardPaths::writableLocation}(\l{QStandardPaths::GenericCacheLocation}). + On systems that have no concept of a shared cache, the application-specific \l{QStandardPaths::CacheLocation} is used instead. + +\row + \li here.mapping.cache.disk.size + \li Map tile disk cache size in bytes. Default size of the cache is 20MB. +\row + \li here.mapping.cache.memory.size + \li Map tile memory cache size in bytes. Default size of the cache is 3MB. +\row + \li here.mapping.cache.texture.size + \li Map tile texture cache size in bytes. Default size of the cache is 6MB. Note that the texture cache has a hard minimum size which depends on the size of the map viewport (it must contain enough data to display the tiles currently visible on the display). This value is the amount of cache to be used in addition to the bare minimum. +\row + \li here.geocoding.host + \li Geocoding service URL used by geocoding manager. +\row + \li here.routing.host + \li Routing service URL used by routing manager. +\row + \li here.places.host + \li Search service URL used by search manager. +\row + \li here.places.api_version + \li Version of the REST API used by the places manager. Currently versions 1 and 2 are + supported. The version 1 is deprecated and will not be part of the final Qt release. The default is version 2. +\endtable + +\section1 Parameter Usage Example + +The following two examples show how to create a HERE plugin instance with +parameters supplied for an application id and token, which is required for +authentication. + +\section2 QML + +\code +Plugin { + name: "here" + PluginParameter { name: "here.app_id"; value: "myapp" } + PluginParameter { name: "here.token"; value: "abcdefg12345" } +} +\endcode + +\section2 C++ + +\code +QMap params; +params["here.app_id"] = "myapp"; +params["here.token"] = "abcdefg12345"; + +QGeoServiceProvider *gsp = new QGeoServiceProvider("here", params); +\endcode + +\section1 Places +The HERE provider remotely accesses places (read-only) from a REST based server. The specific capabilities +and behaviours are outlined below: + +\section2 Capabilities +\table + \row + \li Storage + \li remote + \row + \li Read/Write + \li read-only + \row + \li Icons + \li yes + \row + \li Search term suggestions + \li yes + \row + \li Recommendations + \li yes + \row + \li Category structure + \li Hierarchical + \row + \li (Rich) Content images + \li yes + \row + \li (Rich) Content reviews + \li yes + \row + \li (Rich) Content editorials + \li yes + \row + \li All details fetched during search + \li no + \row + \li Paging offset index + \li no + \row + \li Paging limit + \li yes + \row + \li Distance relevance hint + \li no + \row + \li Lexical name relevance hint + \li no + \row + \li Extended Attributes + \li yes + \row + \li Notifications for added/removed places/categories + \li no + \row + \li visibility scopes + \li public + \row + \li favorites matching/(usable as favoritesPlugin) + \li no +\endtable + +\section2 Plugin Specific Behaviors and Limitations. +\section3 Search +The following list shows what core place data is returned during a place search: +\list +\li name +\li location +\li contact information +\li attribution +\li categories +\li rating +\li visibility +\endlist + +The following list shows further details that may be retrieved +via QPlaceManager::getDetails() +\list +\li supplier +\li extended attributes +\endlist + +\section3 Searching for Places +\section4 Search Term and Categories +The HERE plugin supports searching with a \e {search term} and \e {category or categories}, however +both are not supported simultaneously. + +\list + \li Valid usage: \e {search term} + \e {search center} + \li Valid usage: \e {category} + \e {search center} + \li Invalid usage: \e {search term} + \e {category} + \e {search center} +\endlist + +This limitation applies when using the HERE plugin with \l PlaceSearchModel and QPlaceManager::search(). + +\section4 Search Area +The HERE plugin only supports provision of a \e {search center} when searching for places via \l PlaceSearchModel +and QPlaceManager::search(). A search center can be provided via a bounding circle, however the +radius should be kept at the default value of -1. Typically a developer should not have to set the radius at all. +If a developer sets a radius, it is ignored by the plugin and the boundaries are not honored. + +In a similar manner only the center of a bounding box is taken into consideration when searching. The boundaries +of the box are not honored. + +A search center \e {must} be provided for all searches. + +\section4 Relevancy Hints +The HERE plugin does not support relevancy hints. Any relevancy hints supplied to +a search request are consequently ignored. + +\section3 Search Term suggestions +Only a partial \e {search term} and \e {search center} is supported when retrieving suggestions. +This limitation applies when using the HERE plugin with the \l PlaceSearchSuggestionModel and QPlaceManager::searchSuggestions(). + +Both search term and search center \e {must} be provided when retrieving search term suggestions. + +\section3 Recommendations +Only a given \e {place identifier} is supported as a parameter for a recommendations. No other parameters +such as limit, offset, and search area are supported. This limitation applies when using the +HERE plugin with \l PlaceSearchModel and QPlaceManager::search(). + +\section3 Extended Attributes +The supported set of attributes provided by the HERE plugin are not fixed and +may grow over time. Also the attributes provided may vary according to a place +by place basis, e.g one place may provide opening hours while another does not. +At the time of writing, it is known that some places provide \c openingHours +(QPlaceAttribute::OpeningHours) and \c payment (QPlaceAttribute::Payment) +methods but other attributes may be made available by the backend server. All +places provided by the plugin will have the \c x_provider +(QPlaceAttribute::Provider) attribute set to \c here. + +\section3 Restrictions of Usage - ExtendedAttributes and Content +The extended attributes and rich content of places are not permitted +to be saved. For QML this is related to \l Place::extendedAttributes, \l ImageModel, +\l ReviewModel, and \l EditorialModel. For C++ this relates to QPlace::extendedAttribute(), +QPlace::content() and QPlaceManager::getPlaceContent(). + +(Note that the HERE plugin is a read-only source of places and +does not support saving functionality at all.) +*/ diff --git a/src/location/doc/src/plugins/osm.qdoc b/src/location/doc/src/plugins/osm.qdoc new file mode 100644 index 0000000..a0f2bc2 --- /dev/null +++ b/src/location/doc/src/plugins/osm.qdoc @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Aaron McCarthy +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page location-plugin-osm.html +\title Qt Location Open Street Map Plugin +\ingroup QtLocation-plugins + +\brief Uses Open Street Map and related services. + +\section1 Overview + +This geo services plugin allows applications to access +\l {http://openstreetmap.org}{Open Street Map} location based services using the Qt Location API. + +Data, imagery and map information provided by \l {http://korona.geog.uni-heidelberg.de/}{OpenMapSurfer}, +\l {http://www.thunderforest.com/}{ThunderForest}, OpenStreetMap and contributors. The data is +available under the \l {http://www.opendatacommons.org/licenses/odbl}{Open Database License}. + +The Open Street Map geo services plugin can be loaded by using the plugin key "osm". + +\note Since Qt 5.6.2, the available map types offered by this plugin may change without notice depending on the +actual availability of each provider. To prevent these changes, either a different geo service plugin should be used, or the plugin +parameter \e osm.mapping.providersrepository.address should be set to a user-specified repository, in order to take full control over +(and accept \b responsibility for) selecting the provider that is used for each map type. + +\section1 Parameters + +\section2 Optional parameters +The following table lists optional parameters that can be passed to the Open Street Map plugin. + +\note Since Qt 5.5 all parameters below must be prefixed with \c osm. Previous versions did not require +a prefix. + +\table +\header + \li Parameter + \li Description +\row + \li osm.useragent + \li User agent string set when making network requests. This parameter should be set to a + value that uniquely identifies the application. Note that providers might block applications not setting this + parameter, leaving it to the stock plugin user agent (e.g., \l {http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy}{Nominatim} + for geocoding) +\row + \li osm.mapping.custom.host + \li Url string set when making network requests to the tile server. This parameter should be set to a + valid server url with the correct osm api and the \l{Map::activeMapType} to the corresponding \l{MapType}.CustomMap. + The CustomMap will only be available if this parameter is set. + \note Setting the mapping.custom.host parameter to a new server renders the map tile cache useless for the old custommap style. +\row + \li osm.mapping.custom.mapcopyright + \li Custom map copryright string is used when setting the \l{Map::activeMapType} to \l{MapType}.CustomMap via urlprefix parameter. + This copyright will only be used when using the CustomMap from above. If empty no map copyright will be displayed for the custom map. +\row + \li osm.mapping.custom.datacopyright + \li Custom data copryright string is used when setting the \l{Map::activeMapType} to \l{MapType}.CustomMap via urlprefix parameter. + This copyright will only be used when using the CustomMap from above. If empty no data copyright will be displayed for the custom map. +\row + \li osm.mapping.providersrepository.address + \li The OpenStreetMap plugin retrieves the provider's information from a remote repository. This is done to prevent using hardcoded + servers by default, which may become unavailable. By default this information is fetched from \l {http://maps-redirect.qt.io} {maps-redirect.qt.io}. + Setting this parameter changes the provider repository address to a user-specified one, which must contain the files + \tt{street}, \tt{satellite}, \tt{cycle}, \tt{transit}, \tt{night-transit}, \tt{terrain} and \tt{hiking}, each of which must contain valid provider information. +\row + \li osm.mapping.providersrepository.disabled + \li By default, the OpenStreetMap plugin retrieves the provider's information from a remote repository to avoid a loss of service due to unavailability of hardcoded services. + The plugin, however, still contains fallback hardcoded provider data, in case the provider repository becomes unreachable. + Setting this parameter to \b true makes the plugin use the hardcoded urls only and therefore prevents the plugin from fetching provider data from the remote repository. +\row + \li osm.routing.host + \li Url string set when making network requests to the routing server. This parameter should be set to a + valid server url with the correct osrm API. If not specified the default \l {http://router.project-osrm.org/route/v1/driving/}{url} will be used. + \note The API documentation and sources are available at \l {http://project-osrm.org/}{Project OSRM}. + +\row + \li osm.routing.apiversion + \li String defining the api version of the (custom) OSRM server. Valid values are \b{v4} and \b{v5}. The default is \b{v5}. + This parameter should be set only if \tt{osm.routing.host} is set, and is an OSRM v4 server. + +\row + \li osm.geocoding.host + \li Url string set when making network requests to the geocoding server. This parameter should be set to a + valid server url with the correct osm API. If not specified the default \l {http://nominatim.openstreetmap.org/}{url} will be used. + \note The API documentation is available at \l {https://wiki.openstreetmap.org/wiki/Nominatim}{Project OSM Nominatim}. +\row + \li osm.places.host + \li Url string set when making network requests to the places server. + This parameter should be set to a valid server url with the correct osm API. + If not specified the default \l {http://nominatim.openstreetmap.org/search}{url} + will be used. + \note The API documentation is available at \l {https://wiki.openstreetmap.org/wiki/Nominatim}{Project OSM Nominatim}. +\endtable + +\section1 Parameter Usage Example + +The following example shows how to create an OSM plugin instance with +parameters supplied for an useragent, and if necessary, a custom server url plus the corresponding copyright information for the tile provider. +Additionally, it is possible to choose another routing server than the public osrm one. + +\section2 QML + +\code +Plugin { + name: "osm" + PluginParameter { name: "osm.useragent"; value: "My great Qt OSM application" } + PluginParameter { name: "osm.mapping.host"; value: "http://osm.tile.server.address/" } + PluginParameter { name: "osm.mapping.copyright"; value: "All mine" } + PluginParameter { name: "osm.routing.host"; value: "http://osrm.server.address/viaroute" } + PluginParameter { name: "osm.geocoding.host"; value: "http://geocoding.server.address" } +} +\endcode + +\section1 Other Plugin-specific Information + +\section2 Tile cache + +The tiles are cached in a \c{QtLocation/osm} directory in \l {QStandardPaths::writableLocation()}{QStandardPaths::writableLocation} +(\l{QStandardPaths::GenericCacheLocation}). On systems that have no concept of a shared cache, the application-specific +\l{QStandardPaths::CacheLocation} is used instead. +*/ diff --git a/src/location/doc/src/plugins/places-backend.qdoc b/src/location/doc/src/plugins/places-backend.qdoc new file mode 100644 index 0000000..b6de60e --- /dev/null +++ b/src/location/doc/src/plugins/places-backend.qdoc @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page location-places-backend.html +\title Places Backend + +\brief The Places backend is responsible for managing a places datastore whether + it is located remotely or locally + +\section1 Overview + +The QPlaceManager interface, provided to clients to allow access to place information, +depends directly on an implementation of QPlaceManagerEngine. The engine provides +the backend function implementations which are called by the manager. + +A places backend implementer needs to derive from QPlaceManagerEngine and provide implementations +for the virtual functions relevant for their backend. Most of these functions are asynchronous and +so implementers will also need to derive the appropriate \l {Places Reply Classes}{reply classes}. +The reply objects are responsible for managing an asynchronous request; they are used to notify +when a request is complete and hold the results of that request. QPlaceManagerEngine provides a +default implementation for all virtual functions. The default implementations for the asynchronous +functions return a reply that will emit the error() and finished() signals at the next iteration +through the event loop. + +\section1 Implementing/Inheriting Reply Objects +A reply object would be inherited as follows: +\snippet places/requesthandler.h Implement reply pt1 +\dots +\snippet places/requesthandler.h Implement reply pt2 + +The implementation of a QPlaceManagerEngine must ensure that any signals emitted by the reply +objects are delayed until the request functions have returned and the application code has a chance +to connect those signals to slots. The typical approach is to use \l {QMetaObject::invokeMethod()} +with a \l {Qt::QueuedConnection} to emit the signals. + +\snippet places/requesthandler.h Trigger done + +Note that the \c finished signals should always be emitted when a reply is complete, even if +an error has been encountered, that is, if there is an error, both the \c error and \c finished signals +should be emitted while if there is no error, only the \c finished signals are emitted. + +The protected functions of QPlaceSearchReply::setResults() and QPlaceSearchReply::setRequest() +are made publicly accessible so the plugin can assign results and requests. Because +these functions are not publically exported, accessibility is not so much of an issue. +An alternative would have been to declare a friend class in SearchReply. + +Typically the engine instance would be made the \c parent of the reply. If the developer +fails to discard the replies when finished, the engine can clean those upon destruction. +Commonly, the reply also has a pointer reference back to the engine, which may be used +to emit the QPlaceManagerEngine::finished() and QPlaceManagerEngine::error() signals. This is +just one of many ways the reply could be implemented. + +\section1 Icon URLs +Icon URLs are provided through the QPlaceManagerEngine::constructIconUrl() function. +The expected behaviour is that the engine will use the QPlaceIcon::parameters() +in order to construct an appropriate URL. When a QPlace object is returned +from the manager either from a search or a query to get place details, +it is expected the engine will correctly populate the parameters as necessary. + +The backend is free to choose what the parameter key and values are, however +if a backend only ever has one URL per icon it is recommended that the QPlaceIcon::SingleUrl +be used as the key. + +\section1 Categories +The categories of a manager engine are relatively static entities; for engines accessing +remote place datastores it may be desirable to cache the category structure rather than +querying a server every time QPlaceManagerEngine::initializeCategories() is called. +Depending on how dynamic the categories are, always downloading the freshest +set of categories may be more appropriate. + +\section1 Saving Places to the Manager +A place generally cannot be saved directly between managers as is because it contains manager specific data such as icons +and categories. In order to facilitate saving to one's own manager, engine implementers should implement +the QPlaceManagerEngine::compatiblePlace() function. This function returns a copy of the input place +with properties pruned or modified as necessary such that the copy can be saved into manager. + +Construction of a compatible place may involve ignoring certain properties from the +original place, for example if contact details are not supported, these are left out of the +compatible place. Other times it may involve modifying certain properties, for example +modifying the icon parameters to facilitate copying or downloading of the original +place's icon to a location that the backend can access. + +\section1 Cross-Referencing Places Between Managers +Sometimes a situation may arise where we wish to cross-reference and match places between managers. +Such a situation may arise where one manager provides read-only access to places (origin manager), while another second r/w +manager (destination manager) is used to save selected favorites from the first. During a search of the origin manager, we may want to +know which ones have been 'favorited' into the destination manager and perhaps display the customized favorite name +rather than the original name. + +\section2 Alternative Identifier Cross-Referencing +In order to accomplish cross-referencing, there needs to be a link between the original place and the favorited place +and this is typically handled via an alternative identifier attribute. The favorited place contains an alternative identifier attribute which has the identifier of the original place. + +\include place-crossref.qdocinc + +There are 3 prerequisites for implementing cross-referencing by alternative identifier. The first is that the origin manager must provide the x_provider attribute +with the value being the name of the manager's QGeoServiceProvider. The attribute label should be kept empty, indicating the attribute should not +be displayed to users. \note It is generally expected that all managers should set the \c x_provider attribute. + +The second is that QPlaceManager::compatiblePlace() of the destination manager use the \c x_provider attribute of the initial place +and set an alternative identifier attribute of the place to be saved. The key of the alternative identifier attribute is \c x_id_ and +the text value is the identifier of the initial place. The \c x_provider attribute should not be passed to the compatible place. When +it is saved, the x_provider of the saved place is considered to be the destination manager. + +The third is that QPlaceManager::matchingPlaces() of the destination manager accept the QPlaceMatchRequest::AlternativeId as a parameter key +and the alternative identifier attribute key as the value, in this case \c x_id_ would be the expected value. +This indicates that the identifiers of places in the QPlaceMatchRequest should be matched against the \c x_id_ alternative identifier attributes. + +Note that if the destination manager is to facilitate saving and cross-referencing from any arbitrary manager, it internally must +accommodate saving of arbitrary key value pairs since we cannot know the provider names before hand, nor can we know what structure the +ids will be. + +\section3 Other Methods of Linking +If an origin manager does not supply a place id, it may be necessary to provide some other means of cross-referencing/matching. +One approach might be to do so via the place coordinates, if the coordinate of a place in the origin manager is identical or close +to a place in the destination manager, there is a high likelihood that they are the same place. +In this case, the manager might implement QPlaceManager::matchingPlaces() to accept a QPlaceMatchRequest with a parameter key of 'proximity' +and a parameter value of the distance two places must be in order to detect a match. for example if an origin place and destination place are within 50m +of each other, they can be considered the same place. + +Generally however it is recommended that cross referencing be implemented via alternative identifiers as mentioned above. + +\section3 User Readable vs Non-User Readable Extended Attributes +If an attribute is not intended to be readable by end users, the label field should be kept +empty as an indicator of this fact. +*/ diff --git a/src/location/doc/src/qml-maps.qdoc b/src/location/doc/src/qml-maps.qdoc new file mode 100644 index 0000000..ecc2167 --- /dev/null +++ b/src/location/doc/src/qml-maps.qdoc @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \group qml-QtLocation5-maps + \title QML Maps Plugin + QML Support for the Qt Location API. +*/ + + +/*! +\page qml-location5-maps.html +\title QML Maps + +\brief Maps deals with maps, their contents and navigation. + +\section1 Overview + +The \l Map type allows the display of a map and placing objects within the map. +Various points of interest can be defined and added to the map for display. +Also the \l Map has features to control how the map is displayed. With the +Map item you can center the map, zoom, pinch and make the item flickable. + +The places to be added to the map are +\l {Maps and Navigation (QML)#Putting Objects on a Map (Map Overlay Objects)}{MapItems}. The item's +position is defined by a \l {coordinate} which includes latitude, +longitude and altitude. The item is then displayed automatically after it is added to the \l Map. + +\section2 Position on map + +All position APIs are part of the \l {QtPositioning} module. +The basic piece of position information is the \l {coordinate}. A +coordinate encapsulates data for the latitude, longitude and altitude of the location. Altitude is +in meters. It also has a method to determine distance to another +\l {coordinate}. The \l {coordinate} type may +also be held within a \l [QtPositioning]{Location} element, this will also have information +on a bounding box size to determine sufficient proximity to the location and a location address. + + +Here is an example of a client that uses a \l{PositionSource}{position source} +to center a \l{Map}{map} on the current position: + +\code + Rectangle { + + import QtPositioning 5.2 + import QtLocation 5.3 + ... + + Map { + id: map + // initialize map + ... + } + + PositionSource { + onPositionChanged: { + // center the map on the current position + map.center = position.coordinate + } + } + } +\endcode + +\section2 Geocoding + +\l {http://en.wikipedia.org/wiki/Geocoding}{Geocoding} is the derivation of +geographical coordinates (latitude and longitude) from other geographical references +to the locations. For example, this can be a street address. Reverse geocoding is also possible with +a street address being used to determine a geographical coordinate. Geocoding +is performed by using the \l [QML]{GeocodeModel} type. + +The following code examples are a small part of the \c map component in the +\l {Map Viewer (QML)}{Map Viewer (QML)} example. The snippets +demonstrate the declaration of the \l GeocodeModel component. + +In the snippet we see that the [QML]{GeocodeModel} contains the plugin +and two signal handlers. One for changes in status \l [QML]{GeocodeModel::status}{\c onStatusChanged} and +the other to update the centering of the Map object \l [QML]{GeocodeModel::locationsChanged}{\c onLocationsChanged}. + +\snippet mapviewer/map/MapComponent.qml geocodemodel0 +\codeline +\snippet mapviewer/map/MapComponent.qml geocodeview + +The geocoding features are called from a higher level piece of code. In this +snippet we see an \l [QML]{Address} object filled with the desired parameters. + +\snippet mapviewer/mapviewer.qml geocode0 + +The \l [QML]{Address} is later used in a query for the \l GeocodeModel to +process and determine the geographical \l [QML]{coordinate}{coordinates}. + +\snippet mapviewer/map/MapComponent.qml geocode1 + + +\section2 Navigation + +A very important function of the \l Map type is navigation +from one place to a destination with possible waypoints along the route. The +route will be divided up into a series of segments. At the end of each segment +is a vertex called a \e maneuver. The \e segments contain information about +the time and distance to the end of the segment. The \e maneuvers contain information +about what to do next, how to get onto the next segment, if there is one. So +a \e maneuver contains navigational information, for example "turn right now". + +To find a suitable route we will need to use a \l RouteQuery to define the +selection criteria and adding any required waypoints. +The \l RouteModel should return a list of \l {RouteSegment}s that defines the +route to the destination complete with navigation advice at the joins between +segments, called \l {RouteManeuver}s + +There are many options that you can add to the query to narrow the criteria. +The \l RouteQuery properties can include + +\table 60% + \row + \li \l {RouteQuery::}{numberAlternativeRoutes} + \li The number of alternative routes + \row + \li \l {RouteQuery::}{travelModes} + \li Travel modes + \row + \li \l {RouteQuery::}{routeOptimizations} + \li Required route optimizations + \row + \li \l {RouteQuery::}{segmentDetail} + \li Level of detail in segments + \row + \li \l {RouteQuery::}{maneuverDetail} + \li Level of detail in maneuvers between segments + \row + \li \l {RouteQuery::}{waypoints} + \li A list of waypoints + \row + \li \l {RouteQuery::}{excludedAreas} + \li A list of excluded areas that the route must not cross + \row + \li \l {RouteQuery::}{featureTypes} + \li Relevant map features, for example highway, ferry +\endtable + + +In the following example a default \l [QML]{RouteQuery} is declared within \l [QML]{RouteModel}. + +\snippet mapviewer/map/MapComponent.qml routemodel0 + +The user enters some information such as the starting point +of the route, some waypoints and the destination. All of these locations are +waypoints so the locations from start to finish will be entered as a sequence +of waypoints. Then other query properties can be set that may be specific to +this trip. + +\snippet mapviewer/map/MapComponent.qml routerequest0 +\snippet mapviewer/map/MapComponent.qml routerequest1 + +The \c routeInfoModel \l {Models and Views in Qt Quick#ListModel}{ListModel} is used to grab the +results of the query and construct a suitable list for display. +\snippet mapviewer/forms/RouteList.qml routeinfomodel0 +\snippet mapviewer/forms/RouteList.qml routeinfomodel1 +\snippet mapviewer/forms/RouteList.qml routeinfomodel3 + +The \l {Models and Views in Qt Quick#ListModel}{ListModel} \c routeInfoModel can be filled +with values using a code, that loops through the segments extracting the segment length, +instruction text and distance to the next instruction. The extracted data is formatted +for display as it is retrieved. + +\snippet mapviewer/forms/RouteList.qml routeinfomodel2 + +For more information on the example see the \l {Map Viewer (QML)}{Map Viewer (QML)} example. + + +\section2 Zoom, Pinch and Flickable + +The \l Map item also supports user interface interactions with the map using +tactile and mouse gestures. That is features such as swiping to pan, +pinching to zoom. + +Enabling and configuring pinch and flickable is easy within the \l Map type. + +\snippet mapviewer/map/MapComponent.qml top +\snippet mapviewer/map/MapComponent.qml mapnavigation +\snippet mapviewer/map/MapComponent.qml end + +Zoom can also be controlled by other objects like sliders, with binding +to the Map \l {QtLocation::Map::}{zoomLevel}. + +\section1 QML Types + +\section3 Maps +\annotatedlist qml-QtLocation5-maps + +\section3 Geocoding +\annotatedlist qml-QtLocation5-geocoding + +\section3 Routing +\annotatedlist qml-QtLocation5-routing + + + +\section1 Example + +The above snippets are taken from the \l {Map Viewer (QML)}{Map Viewer (QML)} example. + +*/ + diff --git a/src/location/doc/src/qtlocation-changes.qdoc b/src/location/doc/src/qtlocation-changes.qdoc new file mode 100644 index 0000000..1330412 --- /dev/null +++ b/src/location/doc/src/qtlocation-changes.qdoc @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page qtlocation-changes.html +\title Qt Location QML API changes since 5.4 +\brief Information about the Qt Location QML API changes since 5.4 + +This page lists the QtLocation QML API changes since the first Qt Location Technology Preview +in Qt 5.4. Since Qt 5.6 this API is considered to be final and subsequent releases will +not break the given API anymore. + +\note The public C++ API remained binary compatible since Qt 5.4. + +\b{\l{QtLocation::Map}{Map} Component} +\list + \li removed wheelAngleChanged() signal + \li added \l[QML]{QtLocation::Map::}{error} property + \li added \l[QML]{QtLocation::Map::}{errorString} property + \li added \l[QML]{QtLocation::Map::}{copyrightLinkActivated} signal + \li removed toScreenPosition() method + \li added \l[QML]{QtLocation::Map::}{fromCoordinate}() method + \li replaced cameraStopped() method with \l[QML]{QtLocation::Map::}{prefetchData} method + \li replaced fitViewportToGeoShape() method with \l[QML]{QtLocation::Map::}{visibleRegion} property + \li added \l[QML]{QtLocation::Map::}{color} property + \li added \l[QML]{QtLocation::Map::}{clearData} method +\endlist + +\b{\l{QtLocation::MapGestureArea}{MapGestureArea} Component} +\list + \li removed movementStopped() signal + \li replaced isPanActive and isPinchActive properties with \l[QML]{QtLocation::MapGestureArea::}{panActive} + and \l[QML]{QtLocation::MapGestureArea::}{pinchActive} properties + \li replaced activeGestures with \l[QML]{QtLocation::MapGestureArea::}{acceptedGestures} + \li replaced MapGestureArea.ZoomGesture with \l[QML]{QtLocation::MapGestureArea::acceptedGestures}{MapGestureArea.PinchGesture} + \li removed properties panEnabled and pinchEnabled, please use \l[QML]{QtLocation::MapGestureArea::}{acceptedGestures} instead +\endlist + +\b{\l{QtLocation::MapPolyline}{MapPolyline} Component} +\list + \li added \l[QML]{QtLocation::MapPolyline::}{containsCoordinate} method + \li added \l[QML]{QtLocation::MapPolyline::}{coordinateAt} method + \li added \l[QML]{QtLocation::MapPolyline::}{insertCoordinate} method + \li added \l[QML]{QtLocation::MapPolyline::}{replaceCoordinate} method + \li added \l[QML]{QtLocation::MapPolyline::}{removeCoordinate} method +\endlist + +\b Geoservice's plugin parameters +\list + \li the \l{Qt Location HERE Plugin}{HERE} plugin uses the \c here prefix in front of each plugin parameter name + \li the \l{Qt Location Open Street Map Plugin}{OSM} plugin uses the \c osm prefix in front of each plugin parameter name +\endlist +*/ diff --git a/src/location/doc/src/qtlocation-cpp.qdoc b/src/location/doc/src/qtlocation-cpp.qdoc new file mode 100644 index 0000000..82ac766 --- /dev/null +++ b/src/location/doc/src/qtlocation-cpp.qdoc @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page qtlocation-cpp.html +\title Qt Location C++ API +\brief Information about the Qt Location C++ API + +The Location API provides a library for mapping, navigation and place information. + +\tableofcontents + +The Qt Location API provides the developer with a set of functions to interact +with maps, navigational data and places of interest. This is particularly useful +when associated with current position information which can be retrieved via the +\l QtPositioning module. + +With the Maps API we can associate a position with a map in various formats supplied by a backend. +Then the Places API could be used to populate places on the Map or even +specify the current position as a place of interest and associate it with +an icon, contact details and other information. + +The following table provides links to more detailed information on sections of the +Qt Location C++ API. + +\table + \row + \li \l {Maps and Navigation (C++)}{Maps and Navigation} + \li Displaying maps and finding routes. + \row + \li \l {Places (C++)} {Places} + \li Searching for and managing points of interest. + \row + \li \l {Qt Location GeoServices}{Geoservices Plugin Implementation} + \li Implement new geoservices and positioning plugins. +\endtable + + +\section1 Geoservice Provider Classes + + \annotatedlist QtLocation-common + + +\section1 Maps and Navigation Classes + +Currently it is not possible to interact with maps data via C++. The only available interface is the \l {Maps and Navigation (QML)} API. + + \annotatedlist QtLocation-maps + + \annotatedlist QtLocation-routing + + \annotatedlist QtLocation-geocoding + + +\section1 Places Classes + + \annotatedlist QtLocation-places + + +\section1 Geoservices and Positioning Plugin Classes + + \annotatedlist QtLocation-impl + +*/ + diff --git a/src/location/doc/src/qtlocation-examples.qdoc b/src/location/doc/src/qtlocation-examples.qdoc new file mode 100644 index 0000000..6155a6f --- /dev/null +++ b/src/location/doc/src/qtlocation-examples.qdoc @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \group qtlocation-examples + \title Qt Location Examples + \brief Examples for the Qt Location module + \ingroup all-examples + \ingroup qtlocation + + These examples show a range of different uses for \l{Qt Location}, + such as displaying a map within a QML user interface, implementing basic routing and + place search, as well as integrating positioning data types. + + These examples can work with any of the available geo services plugins. However, some plugins may + require additional \l {QtLocation::PluginParameter}{plugin parameters} in order to function correctly. + The default plugin used by these examples is \l {Qt Location Open Street Map Plugin}, which does not + require any parameters. + +*/ + diff --git a/src/location/doc/src/qtlocation-geoservices.qdoc b/src/location/doc/src/qtlocation-geoservices.qdoc new file mode 100644 index 0000000..008f98a --- /dev/null +++ b/src/location/doc/src/qtlocation-geoservices.qdoc @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page qtlocation-geoservices.html +\title Qt Location GeoServices +\brief Implementing Qt Location GeoService plugins + +The Qt Location provides the majority of its functionality through GeoService plugins. This +document outlines how to develop a new GeoService plugin. + +\section1 Plugin Description + +Each plugin is described by a json file. The json describes the plugins capabilities and +version. Below is an example of a json file used by the OpenStreenMap plugin: + + +\quotefile ../../../plugins/geoservices/osm/osm_plugin.json + +The entries have the following meaning: + +\table + \header + \li Key + \li Description + \row + \li Keys + \li The unique name/key of the plugin. Each GeoService plugin must have a unique name. + \row + \li Provider + \li The provider name of the services. Multiple plugins may have the same name. + In such cases the Version string will be used to further distinguish the plugins. + \row + \li Experimental + \li Marks the service plugin as experimental. API developers may choose to ignore + such plugins when instanciating \l QGeoServiceProvider::QGeoServiceProvider(). + \row + \li Version + \li The plugin version. If multiple plugins have the same provider name, the plugin + with the higest version will be used. + \row + \li Features + \li List of features provided by the plugin/service. Each feature is a string + representation of the corresponding features in \l QGeoServiceProvider. For more + details see \l QGeoServiceProvider::routingFeatures(), + \l QGeoServiceProvider::geocodingFeatures() and \l QGeoServiceProvider::placesFeatures(). + +\endtable + +\section1 Implementing Plugins + +A plugin implementer needs to subclass QGeoServiceProviderFactory and as +many of the ManagerEngine classes as they want to provide implementations for. + +Subclassing QGeoServiceProviderFactory will only involves overriding of one of the following +methods: + +\list + \li \l QGeoServiceProviderFactory::createGeocodingManagerEngine() + \li \l QGeoServiceProviderFactory::createRoutingManagerEngine() + \li \l QGeoServiceProviderFactory::createPlaceManagerEngine() +\endlist + +If a plugin does not provide an engine the relevant function should return 0. + +\annotatedlist QtLocation-impl + +*/ diff --git a/src/location/doc/src/qtlocation-qml.qdoc b/src/location/doc/src/qtlocation-qml.qdoc new file mode 100644 index 0000000..37d21dc --- /dev/null +++ b/src/location/doc/src/qtlocation-qml.qdoc @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \qmlmodule QtLocation 5.3 + \title Qt Location QML Types + \ingroup qmlmodules + \brief Provides QML types for mapping and location information + +\section1 Overview + +Provided that a position has been obtained, this module can add a +\l{QtLocation::Map}{Map} with Places of Interest (POI) and +\l{QtLocation::Place}{Places}. The user can be made aware of nearby features +and related information, displayed graphically. Features on the \l Map can be +places of business, entertainment, and so on. They may include paths, roads, +or forms of transport, enabling navigation optimization and assistance. + +To perform navigation we need \l {Route}s from start to destination. These routes +are made up of segments, where each \l {QtLocation::RouteSegment}{RouteSegment} +can be considered a navigation subtask: drive 100 meters, turn left. The beginning and +end of each segment is a \e waypoint, that is, one part of our journey. + +A typical use case for the API is a user looking for a particular type of +place, say a restaurant. The user could enter a search string into the map +application and respond to a list or display of results for restaurants +"near" the device. The application could then be used to navigate to the +restaurant using an optimized route that is aware of features in the +environment that can help or hinder the journey. The navigation then +proceeds with the user's progress monitored by means of the current +\l Location. In the context of this API the map application would be aware +of the location and size of various places and the location of the user. +Plugins would supply the data required by the application to determine routes +and navigation instructions. The \l Place types would hold information about the +destination and surrounding objects including displayable representations. +The \l Map type would enable this information to be displayed, panned, +zoomed and so on. The \l Route would be determined by a plugin with each +\l RouteSegment holding the navigation instructions guided by the updated +current \l Location. + +\l {Plugin}s are a means of specifying which location-based service to use. For +example, a plugin may allow connection to a provider's service that provides +geocoding and routing information, which can be consumed by the application. +There may be various GeoServices plugins for various tasks with some plugins +providing more than one service. One QML \l Plugin must be created for each +required GeoService plugin. Plugins are required for maps, routing and geocoding, +and places, however the default plugin handles all four of these services. A plugin may +require online access or may support on-board maps and data. + +\note Plugins may not provide features such as paging or relevance hints. + +The following links provide more detailed information about maps and places: + +\table + \row + \li \l {Maps and Navigation (QML)}{Maps and Navigation} + \li Displaying maps and finding routes. + \row + \li \l {QML PLaces API} {Places} + \li Searching for and managing points of interest. +\endtable + +\section1 Common QML Types + +\annotatedlist qml-QtLocation5-common + +\section1 Maps QML Types + +\annotatedlist qml-QtLocation5-maps + +\section1 Navigation and Routing QML Types + +\annotatedlist qml-QtLocation5-routing + +\section1 Geocoding QML Types + +\annotatedlist qml-QtLocation5-geocoding + +\section1 Places QML Types + +\annotatedlist qml-QtLocation5-places + +\section1 Alphabetical Listing of All QML Types +*/ diff --git a/src/location/doc/src/qtlocation.qdoc b/src/location/doc/src/qtlocation.qdoc new file mode 100644 index 0000000..7979bbe --- /dev/null +++ b/src/location/doc/src/qtlocation.qdoc @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + + + +/*! + \module QtLocation + \title Qt Location C++ Classes + \ingroup modules + \qtvariable location + + \brief Provides C++ interfaces to retrieve location and navigational + information. + + The C++ API provides access to geocoding and navigation information, + and also place search. Use the \l{Maps and Navigation (QML)}{QML} + API to render this information on an interactive map that supports + touch gestures, overlays, and so on. + + Include the appropriate header in your C++ code. For example, + applications using routes can include: + + \code #include \endcode + + Add the \e location keyword in the project file to link against the + Qt Location library: + + \code QT += location \endcode + + See more in the \l{Qt Location}{Qt Location Overview}. + +*/ + + + +/*! +\page qtlocation-index.html +\title Qt Location +\brief Provides QML and C++ interfaces to create location-aware +applications. +\ingroup technology-apis + +The Qt Location API helps you create viable mapping solutions using the data +available from some of the popular location services. + +\section1 Overview + +The Qt Location API enables you to: +\list + \li access and present map data, + \li support touch gesture on a specific area of the map, + \li query for a specific geographical location and route, + \li add additional layers on top, such as polylines and circles, + \li and search for places and related images. +\endlist + +\section1 Getting Started + +To load the Qt Location module, add the following statement to your .qml files + +\code + import QtPositioning 5.5 + import QtLocation 5.6 +\endcode + +The QtLocation QML module depends on the QtPositioning QML module. +Therefore every QML application that imports the QtLocation QML module must always +import the QtPositioning module as well. + +For C++ projects include the header appropriate for the current use case, +for example applications using routes may use + +\code #include \endcode + +The .pro file should have the \e location keyword added + +\code QT += location \endcode + +\section2 Submodules + +The API is split into sub-modules, which provide QML and C++ interfaces for +specific purposes. They focus mainly on Map and Place information. The required +position data can be retrieved using the \l {QtPositioning} module. + +\section3 Places + +The Places submodule is the natural complement to Positioning, providing a +source of geographical data about Places of Interest (POI). Besides the source +information, the API provides information about the location, size, and +other related information about a POI. The Places API can also +retrieve images, reviews, and other content related to a place. + +\table +\row + \li Places introduction: + \li \l{QML Places API}{for QML} + \li \l{Places (C++)}{for C++} +\endtable + +\section3 Maps and Navigation + +The module provides the QML and C++ alternatives for maps and navigation. +The C++ alternative provides utility classes to get geocoding (finding a geographic +coordinate from a street address) and navigation (including driving and walking +directions) information, whereas its QML counterpart provides UI components to render +the information. + +\table +\row +\li Maps and Navigation introduction: + \li \l{Maps and Navigation (QML)}{for QML} + \li \l{Maps and Navigation (C++)}{for C++} +\endtable + +\section1 API References and Examples + +The following are lists of the classes and UI components provided by the module, +with example applications to demonstrate their usage: + +\table + \row + \li \l {Qt Location QML Types}{QML API Reference} + \li Full list of QML components in the Qt Location API + \row + \li \l {Qt Location C++ API}{C++ API Reference by domain} + \li Full list of C++ classes and methods of the Qt Location APIs sorted by domain + \row + \li \l {Qt Location C++ Classes}{C++ API Reference} + \li Full list of C++ classes and methods of the Qt Location APIs + \row + \li \l {Qt Location Examples}{Example Apps} + \li Examples demonstrating use of the Qt Location APIs + \row + \li \l {QML Maps}{Maps and Navigation Tutorial} + \li Tutorial introducing the QML Maps Types +\endtable + +\section1 Plugin References and Parameters + +Information about plugins, important notes on their usage, parameters that can +be provided to influence their behavior. + +\annotatedlist QtLocation-plugins + +\section2 Implementing New Back-Ends and Porting + +For systems integrators and distributors, information related to making +Qt Location available for a new platform. + +\table + \row + \li \l {Qt Location GeoServices}{GeoServices} + \li Information about the Qt Location GeoServices plugins + \row + \li \l {Places Backend} {Places} + \li Information for places backend implementors + \row + \li \l {Qt Location QML API changes since 5.4}{API changes} + \li Information about QML API changes since 5.4 +\endtable + +*/ diff --git a/src/location/doc/src/src.pro b/src/location/doc/src/src.pro new file mode 100644 index 0000000..fe90f13 --- /dev/null +++ b/src/location/doc/src/src.pro @@ -0,0 +1,9 @@ +TEMPLATE = subdirs +SUBDIRS += snippets + +OTHER_FILES = \ + *.qdoc \ + *.qdocinc \ + plugins/*.qdoc \ + examples/*.qdoc \ + imports/*.qdoc diff --git a/src/location/location.pro b/src/location/location.pro new file mode 100644 index 0000000..052a197 --- /dev/null +++ b/src/location/location.pro @@ -0,0 +1,22 @@ +TARGET = QtLocation +QT = core-private positioning-private + +MODULE_PLUGIN_TYPES = \ + geoservices + +QMAKE_DOCS = $$PWD/doc/qtlocation.qdocconf +OTHER_FILES += doc/src/*.qdoc # show .qdoc files in Qt Creator + +PUBLIC_HEADERS += \ + qlocation.h \ + qlocationglobal.h + +SOURCES += \ + qlocation.cpp + +include(maps/maps.pri) +include(places/places.pri) + +HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS + +load(qt_module) diff --git a/src/location/maps/maps.pri b/src/location/maps/maps.pri new file mode 100644 index 0000000..db43962 --- /dev/null +++ b/src/location/maps/maps.pri @@ -0,0 +1,99 @@ + +INCLUDEPATH += maps + +QT += gui quick + +PUBLIC_HEADERS += \ + maps/qgeocodereply.h \ + maps/qgeocodingmanagerengine.h \ + maps/qgeocodingmanager.h \ + maps/qgeomaneuver.h \ + maps/qgeoroute.h \ + maps/qgeoroutereply.h \ + maps/qgeorouterequest.h \ + maps/qgeoroutesegment.h \ + maps/qgeoroutingmanagerengine.h \ + maps/qgeoroutingmanager.h \ + maps/qgeoserviceproviderfactory.h \ + maps/qgeoserviceprovider.h + +PRIVATE_HEADERS += \ + maps/qgeocameracapabilities_p.h \ + maps/qgeocameradata_p.h \ + maps/qgeocameratiles_p.h \ + maps/qgeocodereply_p.h \ + maps/qgeocodingmanagerengine_p.h \ + maps/qgeocodingmanager_p.h \ + maps/qgeomaneuver_p.h \ + maps/qgeotiledmapscene_p.h \ + maps/qgeotilerequestmanager_p.h \ + maps/qgeomap_p.h \ + maps/qgeomap_p_p.h \ + maps/qgeotiledmap_p.h \ + maps/qgeotiledmap_p_p.h \ + maps/qgeotilefetcher_p.h \ + maps/qgeotilefetcher_p_p.h \ + maps/qgeomappingmanager_p.h \ + maps/qgeomappingmanager_p_p.h \ + maps/qgeomappingmanagerengine_p.h \ + maps/qgeomappingmanagerengine_p_p.h \ + maps/qgeotiledmappingmanagerengine_p.h \ + maps/qgeotiledmappingmanagerengine_p_p.h \ + maps/qgeomaptype_p.h \ + maps/qgeomaptype_p_p.h \ + maps/qgeoroute_p.h \ + maps/qgeoroutereply_p.h \ + maps/qgeorouterequest_p.h \ + maps/qgeoroutesegment_p.h \ + maps/qgeoroutingmanagerengine_p.h \ + maps/qgeoroutingmanager_p.h \ + maps/qgeoserviceprovider_p.h \ + maps/qabstractgeotilecache_p.h \ + maps/qgeofiletilecache_p.h \ + maps/qgeotiledmapreply_p.h \ + maps/qgeotiledmapreply_p_p.h \ + maps/qgeotilespec_p.h \ + maps/qgeotilespec_p_p.h \ + maps/qgeorouteparser_p.h \ + maps/qgeorouteparser_p_p.h \ + maps/qgeorouteparserosrmv5_p.h \ + maps/qgeorouteparserosrmv4_p.h \ + maps/qcache3q_p.h + +SOURCES += \ + maps/qgeocameracapabilities.cpp \ + maps/qgeocameradata.cpp \ + maps/qgeocameratiles.cpp \ + maps/qgeocodereply.cpp \ + maps/qgeocodingmanager.cpp \ + maps/qgeocodingmanagerengine.cpp \ + maps/qgeomaneuver.cpp \ + maps/qgeotilerequestmanager.cpp \ + maps/qgeomap.cpp \ + maps/qgeomappingmanager.cpp \ + maps/qgeomappingmanagerengine.cpp \ + maps/qgeotiledmappingmanagerengine.cpp \ + maps/qgeotilefetcher.cpp \ + maps/qgeomaptype.cpp \ + maps/qgeoroute.cpp \ + maps/qgeoroutereply.cpp \ + maps/qgeorouterequest.cpp \ + maps/qgeoroutesegment.cpp \ + maps/qgeoroutingmanager.cpp \ + maps/qgeoroutingmanagerengine.cpp \ + maps/qgeoserviceprovider.cpp \ + maps/qgeoserviceproviderfactory.cpp \ + maps/qabstractgeotilecache.cpp \ + maps/qgeofiletilecache.cpp \ + maps/qgeotiledmapreply.cpp \ + maps/qgeotilespec.cpp \ + maps/qgeotiledmap.cpp \ + maps/qgeotiledmapscene.cpp \ + maps/qgeorouteparser.cpp \ + maps/qgeorouteparserosrmv5.cpp \ + maps/qgeorouteparserosrmv4.cpp + + + + + diff --git a/src/location/maps/qabstractgeotilecache.cpp b/src/location/maps/qabstractgeotilecache.cpp new file mode 100644 index 0000000..739123d --- /dev/null +++ b/src/location/maps/qabstractgeotilecache.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qabstractgeotilecache_p.h" + +#include "qgeotilespec_p.h" + +#include "qgeomappingmanager_p.h" + +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QSet) + +QT_BEGIN_NAMESPACE + +QGeoTileTexture::QGeoTileTexture() + : textureBound(false) {} + +QGeoTileTexture::~QGeoTileTexture() +{ +} + +QAbstractGeoTileCache::QAbstractGeoTileCache(QObject *parent) + : QObject(parent) +{ + qRegisterMetaType(); + qRegisterMetaType >(); + qRegisterMetaType >(); +} + +QAbstractGeoTileCache::~QAbstractGeoTileCache() +{ +} + +void QAbstractGeoTileCache::printStats() +{ +} + +void QAbstractGeoTileCache::handleError(const QGeoTileSpec &, const QString &error) +{ + qWarning() << "tile request error " << error; +} + +void QAbstractGeoTileCache::setMaxDiskUsage(int diskUsage) +{ + Q_UNUSED(diskUsage); +} + +int QAbstractGeoTileCache::maxDiskUsage() const +{ + return 0; +} + +int QAbstractGeoTileCache::diskUsage() const +{ + return 0; +} + +void QAbstractGeoTileCache::setMaxMemoryUsage(int memoryUsage) +{ + Q_UNUSED(memoryUsage); +} + +int QAbstractGeoTileCache::maxMemoryUsage() const +{ + return 0; +} + +int QAbstractGeoTileCache::memoryUsage() const +{ + return 0; +} + +QString QAbstractGeoTileCache::baseCacheDirectory() +{ + QString dir; + + // Try the shared cache first and use a specific directory. (e.g. ~/.cache/QtLocation) + // If this is not supported by the platform, use the application-specific cache + // location. (e.g. ~/.cache//QtLocation) + dir = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); + + if (!dir.isEmpty()) { + // The shared cache may not be writable when application isolation is enforced. + static bool writable = false; + static bool writableChecked = false; + if (!writableChecked) { + writableChecked = true; + QDir::root().mkpath(dir); + QFile writeTestFile(QDir(dir).filePath(QStringLiteral("qt_cache_check"))); + writable = writeTestFile.open(QIODevice::WriteOnly); + if (writable) + writeTestFile.remove(); + } + if (!writable) + dir = QString(); + } + + if (dir.isEmpty()) + dir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + + if (!dir.endsWith(QLatin1Char('/'))) + dir += QLatin1Char('/'); + + dir += QLatin1String("QtLocation/"); + + return dir; +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qabstractgeotilecache_p.h b/src/location/maps/qabstractgeotilecache_p.h new file mode 100644 index 0000000..141aa9b --- /dev/null +++ b/src/location/maps/qabstractgeotilecache_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QABSTRACTGEOTILECACHE_P_H +#define QABSTRACTGEOTILECACHE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include +#include +#include "qcache3q_p.h" +#include +#include +#include + +#include "qgeotilespec_p.h" +#include "qgeotiledmappingmanagerengine_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoMappingManager; + +class QGeoTile; +class QAbstractGeoTileCache; + +class QThread; + +/* This is also used in the mapgeometry */ +class Q_LOCATION_EXPORT QGeoTileTexture +{ +public: + + QGeoTileTexture(); + ~QGeoTileTexture(); + + QGeoTileSpec spec; + QImage image; + bool textureBound; +}; + +class Q_LOCATION_EXPORT QAbstractGeoTileCache : public QObject +{ + Q_OBJECT +public: + virtual ~QAbstractGeoTileCache(); + + virtual void setMaxDiskUsage(int diskUsage); + virtual int maxDiskUsage() const; + virtual int diskUsage() const; + + virtual void setMaxMemoryUsage(int memoryUsage); + virtual int maxMemoryUsage() const; + virtual int memoryUsage() const; + + virtual void setMinTextureUsage(int textureUsage) = 0; + virtual void setExtraTextureUsage(int textureUsage) = 0; + virtual int maxTextureUsage() const = 0; + virtual int minTextureUsage() const = 0; + virtual int textureUsage() const = 0; + virtual void clearAll() = 0; + + virtual QSharedPointer get(const QGeoTileSpec &spec) = 0; + + virtual void insert(const QGeoTileSpec &spec, + const QByteArray &bytes, + const QString &format, + QGeoTiledMappingManagerEngine::CacheAreas areas = QGeoTiledMappingManagerEngine::AllCaches) = 0; + virtual void handleError(const QGeoTileSpec &spec, const QString &errorString); + + static QString baseCacheDirectory(); + +protected: + QAbstractGeoTileCache(QObject *parent = 0); + + virtual void printStats() = 0; +}; + +QT_END_NAMESPACE + +#endif // QABSTRACTGEOTILECACHE_P_H diff --git a/src/location/maps/qcache3q_p.h b/src/location/maps/qcache3q_p.h new file mode 100644 index 0000000..debce5d --- /dev/null +++ b/src/location/maps/qcache3q_p.h @@ -0,0 +1,471 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCACHE3Q_H +#define QCACHE3Q_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +template +class QCache3QDefaultEvictionPolicy +{ +protected: + /* called just before a key/value pair is about to be _evicted_ */ + void aboutToBeEvicted(const Key &key, QSharedPointer obj); + /* called just before a key/value pair is about to be removed, by + * clear(), remove() or by the destructor (which calls clear) */ + void aboutToBeRemoved(const Key &key, QSharedPointer obj); +}; + +template +void QCache3QDefaultEvictionPolicy::aboutToBeEvicted(const Key &key, QSharedPointer obj) +{ + Q_UNUSED(key); + Q_UNUSED(obj); +} + +template +void QCache3QDefaultEvictionPolicy::aboutToBeRemoved(const Key &key, QSharedPointer obj) +{ + Q_UNUSED(key); + Q_UNUSED(obj); +} + +/* + * QCache3Q + * + * A cache template class for managing QSharedPointers to objects with an + * associated key. It's a lot like QCache, but uses an alternative algorithm + * '3Q' -- which is the '2Q' algorithm plus an extra queue for previously popular + * but evicted nodes, and a 'ghost' list of recent evictions to make a better + * placement choice if they are requested again. + * + * New nodes enter the cache on the "newbies" queue, which is evicted LRA + * (least-recently-added). If a newbie is popular enough (it has been requested + * more than promoteAt times), it will be promoted to a "regular". Regulars + * are evicted LRU (least-recently-used). If a regular is under consideration + * for eviction, its popularity is compared to the mean popularity of the whole + * regulars queue. If it is greater, it is instead moved to the "hobos" queue. + * The "hobos" queue is also evicted LRU, but has a maximum size constraint + * so eviction from it is less likely than from the regulars. + * + * Tweakables: + * * maxCost = maximum total cost for the whole cache + * * minRecent = minimum size that q1 ("newbies") has to be before eviction + * from it takes place + * * maxOldPopular = maximum size that q3 ("hobos") can reach before eviction + * from it takes place + * * promoteAt = minimum popularity necessary to promote a node from + * "newbie" to "regular" + */ +template > +class QCache3Q : public EvPolicy +{ +private: + class Queue; + class Node + { + public: + inline explicit Node() : q(0), n(0), p(0), pop(0), cost(0) {} + + Queue *q; + Node *n; + Node *p; + Key k; + QSharedPointer v; + quint64 pop; // popularity, incremented each ping + int cost; + }; + + class Queue + { + public: + inline explicit Queue() : f(0), l(0), cost(0), pop(0), size(0) {} + + Node *f; + Node *l; + int cost; // total cost of nodes on the queue + quint64 pop; // sum of popularity values on the queue + int size; // size of the queue + }; + + Queue *q1_; // "newbies": seen only once, evicted LRA (least-recently-added) + Queue *q2_; // regular nodes, promoted from newbies, evicted LRU + Queue *q3_; // "hobos": evicted from q2 but were very popular (above mean) + Queue *q1_evicted_; // ghosts of recently evicted newbies and regulars + QHash lookup_; + +public: + explicit QCache3Q(int maxCost = 100, int minRecent = -1, int maxOldPopular = -1); + inline ~QCache3Q() { clear(); delete q1_; delete q2_; delete q3_; delete q1_evicted_; } + + inline int maxCost() const { return maxCost_; } + void setMaxCost(int maxCost, int minRecent = -1, int maxOldPopular = -1); + + inline int promoteAt() const { return promote_; } + inline void setPromoteAt(int p) { promote_ = p; } + + inline int totalCost() const { return q1_->cost + q2_->cost + q3_->cost; } + + void clear(); + bool insert(const Key &key, QSharedPointer object, int cost = 1); + QSharedPointer object(const Key &key) const; + QSharedPointer operator[](const Key &key) const; + + void remove(const Key &key); + + void printStats(); + + // Copy data directly into a queue. Designed for single use after construction + void deserializeQueue(int queueNumber, const QList &keys, + const QList > &values, const QList &costs); + // Copy data from specific queue into list + void serializeQueue(int queueNumber, QList > &buffer); + +private: + int maxCost_, minRecent_, maxOldPopular_; + int hitCount_, missCount_, promote_; + + void rebalance(); + void unlink(Node *n); + void link_front(Node *n, Queue *q); + +private: + // make these private so they can't be used + inline QCache3Q(const QCache3Q &) {} + inline QCache3Q &operator=(const QCache3Q &) {} +}; + +template +void QCache3Q::printStats() +{ + qDebug("\n=== cache %p ===", this); + qDebug("hits: %d (%.2f%%)\tmisses: %d\tfill: %.2f%%", hitCount_, + 100.0 * float(hitCount_) / (float(hitCount_ + missCount_)), + missCount_, + 100.0 * float(totalCost()) / float(maxCost())); + qDebug("q1g: size=%d, pop=%llu", q1_evicted_->size, q1_evicted_->pop); + qDebug("q1: cost=%d, size=%d, pop=%llu", q1_->cost, q1_->size, q1_->pop); + qDebug("q2: cost=%d, size=%d, pop=%llu", q2_->cost, q2_->size, q2_->pop); + qDebug("q3: cost=%d, size=%d, pop=%llu", q3_->cost, q3_->size, q3_->pop); +} + +template +QCache3Q::QCache3Q(int maxCost, int minRecent, int maxOldPopular) + : q1_(new Queue), q2_(new Queue), q3_(new Queue), q1_evicted_(new Queue), + maxCost_(maxCost), minRecent_(minRecent), maxOldPopular_(maxOldPopular), + hitCount_(0), missCount_(0), promote_(0) +{ + if (minRecent_ < 0) + minRecent_ = maxCost_ / 3; + if (maxOldPopular_ < 0) + maxOldPopular_ = maxCost_ / 5; +} + +template +void QCache3Q::serializeQueue(int queueNumber, QList > &buffer) +{ + Q_ASSERT(queueNumber >= 1 && queueNumber <= 4); + Queue *queue = queueNumber == 1 ? q1_ : + queueNumber == 2 ? q2_ : + queueNumber == 3 ? q3_ : + q1_evicted_; + for (Node *node = queue->f; node; node = node->n) + buffer.append(node->v); +} + +template +void QCache3Q::deserializeQueue(int queueNumber, const QList &keys, + const QList > &values, const QList &costs) +{ + Q_ASSERT(queueNumber >= 1 && queueNumber <= 4); + int bufferSize = keys.size(); + if (bufferSize == 0) + return; + clear(); + Queue *queue = queueNumber == 1 ? q1_ : + queueNumber == 2 ? q2_ : + queueNumber == 3 ? q3_ : + q1_evicted_; + for (int i = 0; iv = values[i]; + node->k = keys[i]; + node->cost = costs[i]; + link_front(node, queue); + lookup_[keys[i]] = node; + } +} + + +template +inline void QCache3Q::setMaxCost(int maxCost, int minRecent, int maxOldPopular) +{ + maxCost_ = maxCost; + minRecent_ = minRecent; + maxOldPopular_ = maxOldPopular; + if (minRecent_ < 0) + minRecent_ = maxCost_ / 3; + if (maxOldPopular_ < 0) + maxOldPopular_ = maxCost_ / 5; + rebalance(); +} + +template +bool QCache3Q::insert(const Key &key, QSharedPointer object, int cost) +{ + if (cost > maxCost_) { + return false; + } + + if (lookup_.contains(key)) { + Node *n = lookup_[key]; + n->v = object; + n->q->cost -= n->cost; + n->cost = cost; + n->q->cost += cost; + + if (n->q == q1_evicted_) { + if (n->pop > (uint)promote_) { + unlink(n); + link_front(n, q2_); + rebalance(); + } + } else if (n->q != q1_) { + Queue *q = n->q; + unlink(n); + link_front(n, q); + rebalance(); + } + + return true; + } + + Node *n = new Node; + n->v = object; + n->k = key; + n->cost = cost; + link_front(n, q1_); + lookup_[key] = n; + + rebalance(); + + return true; +} + +template +void QCache3Q::clear() +{ + while (q1_evicted_->f) { + Node *n = q1_evicted_->f; + unlink(n); + delete n; + } + + while (q1_->f) { + Node *n = q1_->f; + unlink(n); + EvPolicy::aboutToBeRemoved(n->k, n->v); + delete n; + } + + while (q2_->f) { + Node *n = q2_->f; + unlink(n); + EvPolicy::aboutToBeRemoved(n->k, n->v); + delete n; + } + + while (q3_->f) { + Node *n = q3_->f; + unlink(n); + EvPolicy::aboutToBeRemoved(n->k, n->v); + delete n; + } + + lookup_.clear(); +} + +template +void QCache3Q::unlink(Node *n) +{ + if (n->n) + n->n->p = n->p; + if (n->p) + n->p->n = n->n; + if (n->q->f == n) + n->q->f = n->n; + if (n->q->l == n) + n->q->l = n->p; + n->n = 0; + n->p = 0; + n->q->pop -= n->pop; + n->q->cost -= n->cost; + n->q->size--; + n->q = 0; +} + +template +void QCache3Q::link_front(Node *n, Queue *q) +{ + n->n = q->f; + n->p = 0; + n->q = q; + if (q->f) + q->f->p = n; + q->f = n; + if (!q->l) + q->l = n; + + q->pop += n->pop; + q->cost += n->cost; + q->size++; +} + +template +void QCache3Q::rebalance() +{ + while (q1_evicted_->size > (q1_->size + q2_->size + q3_->size) * 4) { + Node *n = q1_evicted_->l; + unlink(n); + lookup_.remove(n->k); + delete n; + } + + while ((q1_->cost + q2_->cost + q3_->cost) > maxCost_) { + if (q3_->cost > maxOldPopular_) { + Node *n = q3_->l; + unlink(n); + EvPolicy::aboutToBeEvicted(n->k, n->v); + lookup_.remove(n->k); + delete n; + } else if (q1_->cost > minRecent_) { + Node *n = q1_->l; + unlink(n); + EvPolicy::aboutToBeEvicted(n->k, n->v); + n->v.clear(); + n->cost = 0; + link_front(n, q1_evicted_); + } else { + Node *n = q2_->l; + unlink(n); + if (n->pop > (q2_->pop / q2_->size)) { + link_front(n, q3_); + } else { + EvPolicy::aboutToBeEvicted(n->k, n->v); + n->v.clear(); + n->cost = 0; + link_front(n, q1_evicted_); + } + } + } +} + +template +void QCache3Q::remove(const Key &key) +{ + if (!lookup_.contains(key)) { + return; + } + Node *n = lookup_[key]; + unlink(n); + if (n->q != q1_evicted_) + EvPolicy::aboutToBeRemoved(n->k, n->v); + lookup_.remove(key); + delete n; +} + +template +QSharedPointer QCache3Q::object(const Key &key) const +{ + if (!lookup_.contains(key)) { + const_cast *>(this)->missCount_++; + return QSharedPointer(0); + } + + QCache3Q *me = const_cast *>(this); + + Node *n = me->lookup_[key]; + n->pop++; + n->q->pop++; + + if (n->q == q1_) { + me->hitCount_++; + + if (n->pop > (quint64)promote_) { + me->unlink(n); + me->link_front(n, q2_); + me->rebalance(); + } + } else if (n->q != q1_evicted_) { + me->hitCount_++; + + Queue *q = n->q; + me->unlink(n); + me->link_front(n, q); + me->rebalance(); + } else { + me->missCount_++; + } + + return n->v; +} + +template +inline QSharedPointer QCache3Q::operator[](const Key &key) const +{ + return object(key); +} + +QT_END_NAMESPACE + +#endif // QCACHE3Q_H diff --git a/src/location/maps/qgeocameracapabilities.cpp b/src/location/maps/qgeocameracapabilities.cpp new file mode 100644 index 0000000..7b4a014 --- /dev/null +++ b/src/location/maps/qgeocameracapabilities.cpp @@ -0,0 +1,312 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocameracapabilities_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoCameraCapabilitiesPrivate : public QSharedData +{ +public: + QGeoCameraCapabilitiesPrivate(); + QGeoCameraCapabilitiesPrivate(const QGeoCameraCapabilitiesPrivate &other); + ~QGeoCameraCapabilitiesPrivate(); + + QGeoCameraCapabilitiesPrivate &operator = (const QGeoCameraCapabilitiesPrivate &other); + + bool supportsBearing_; + bool supportsRolling_; + bool supportsTilting_; + + // this is mutable so that it can be set from accessor functions that are const + mutable bool valid_; + + double minZoom_; + double maxZoom_; + double minTilt_; + double maxTilt_; +}; + +QGeoCameraCapabilitiesPrivate::QGeoCameraCapabilitiesPrivate() + : supportsBearing_(false), + supportsRolling_(false), + supportsTilting_(false), + valid_(false), + minZoom_(0.0), + maxZoom_(0.0), + minTilt_(0.0), + maxTilt_(0.0) {} + + +QGeoCameraCapabilitiesPrivate::QGeoCameraCapabilitiesPrivate(const QGeoCameraCapabilitiesPrivate &other) + : QSharedData(other), + supportsBearing_(other.supportsBearing_), + supportsRolling_(other.supportsRolling_), + supportsTilting_(other.supportsTilting_), + valid_(other.valid_), + minZoom_(other.minZoom_), + maxZoom_(other.maxZoom_), + minTilt_(other.minTilt_), + maxTilt_(other.maxTilt_) {} + +QGeoCameraCapabilitiesPrivate::~QGeoCameraCapabilitiesPrivate() {} + +QGeoCameraCapabilitiesPrivate &QGeoCameraCapabilitiesPrivate::operator = (const QGeoCameraCapabilitiesPrivate &other) +{ + if (this == &other) + return *this; + + supportsBearing_ = other.supportsBearing_; + supportsRolling_ = other.supportsRolling_; + supportsTilting_ = other.supportsTilting_; + valid_ = other.valid_; + minZoom_ = other.minZoom_; + maxZoom_ = other.maxZoom_; + minTilt_ = other.minTilt_; + maxTilt_ = other.maxTilt_; + + return *this; +} + +/*! + \class QGeoCameraCapabilities + \inmodule QtLocation + \ingroup QtLocation-impl + \since 5.6 + \internal + + \brief The QGeoCameraCapabilities class describes the limitations on camera settings imposed by a mapping plugin. + + Different mapping plugins will support different ranges of zoom levels, and not all mapping plugins will + be able to support, bearing, tilting and rolling of the camera. + + This class describes what the plugin supports, and is used to restrict changes to the camera information + associated with a \l QGeoMap such that the camera information stays within these limits. +*/ + +/*! + Constructs a camera capabilities object. +*/ +QGeoCameraCapabilities::QGeoCameraCapabilities() + : d(new QGeoCameraCapabilitiesPrivate()) {} + +/*! + Constructs a camera capabilities object from the contents of \a other. +*/ +QGeoCameraCapabilities::QGeoCameraCapabilities(const QGeoCameraCapabilities &other) + : d(other.d) {} + +/*! + Destroys this camera capabilities object. +*/ +QGeoCameraCapabilities::~QGeoCameraCapabilities() {} + +/*! + Assigns the contents of \a other to this camera capabilities object and + returns a reference to this camera capabilities object. +*/ +QGeoCameraCapabilities &QGeoCameraCapabilities::operator = (const QGeoCameraCapabilities &other) +{ + if (this == &other) + return *this; + + d = other.d; + return *this; +} + +/*! + Returns whether this instance of the class is considered "valid". To be + valid, the instance must have had at least one capability set (to either + true or false) using a set method, or copied from another instance + (such as by the assignment operator). +*/ +bool QGeoCameraCapabilities::isValid() const +{ + return d->valid_; +} + +/*! + Sets the minimum zoom level supported by the associated plugin to \a maximumZoomLevel. + + Larger values of the zoom level correspond to more detailed views of the + map. +*/ +void QGeoCameraCapabilities::setMinimumZoomLevel(double minimumZoomLevel) +{ + d->minZoom_ = minimumZoomLevel; + d->valid_ = true; +} + +/*! + Returns the minimum zoom level supported by the associated plugin. + + Larger values of the zoom level correspond to more detailed views of the + map. +*/ +double QGeoCameraCapabilities::minimumZoomLevel() const +{ + return d->minZoom_; +} + +/*! + Sets the maximum zoom level supported by the associated plugin to \a maximumZoomLevel. + + Larger values of the zoom level correspond to more detailed views of the + map. +*/ +void QGeoCameraCapabilities::setMaximumZoomLevel(double maximumZoomLevel) +{ + d->maxZoom_ = maximumZoomLevel; + d->valid_ = true; +} + +/*! + Returns the maximum zoom level supported by the associated plugin. + + Larger values of the zoom level correspond to more detailed views of the + map. +*/ +double QGeoCameraCapabilities::maximumZoomLevel() const +{ + return d->maxZoom_; +} + +/*! + Sets whether the associated plugin can render a map when the camera + has an arbitrary bearing to \a supportsBearing. +*/ +void QGeoCameraCapabilities::setSupportsBearing(bool supportsBearing) +{ + d->supportsBearing_ = supportsBearing; + d->valid_ = true; +} + +/*! + Returns whether the associated plugin can render a map when the camera + has an arbitrary bearing. +*/ +bool QGeoCameraCapabilities::supportsBearing() const +{ + return d->supportsBearing_; +} + +/*! + Sets whether the associated plugin can render a map when the + camera is rolled to \a supportsRolling. +*/ +void QGeoCameraCapabilities::setSupportsRolling(bool supportsRolling) +{ + d->supportsRolling_ = supportsRolling; + d->valid_ = true; +} + +/*! + Returns whether the associated plugin can render a map when the + camera is rolled. +*/ +bool QGeoCameraCapabilities::supportsRolling() const +{ + return d->supportsRolling_; +} + +/*! + Sets whether the associated plugin can render a map when the + camera is tilted to \a supportsTilting. +*/ +void QGeoCameraCapabilities::setSupportsTilting(bool supportsTilting) +{ + d->supportsTilting_ = supportsTilting; + d->valid_ = true; +} + +/*! + Returns whether the associated plugin can render a map when the + camera is tilted. +*/ +bool QGeoCameraCapabilities::supportsTilting() const +{ + return d->supportsTilting_; +} + +/*! + Sets the minimum tilt supported by the associated plugin to \a minimumTilt. + + The value is in degrees where 0 is equivalent to 90 degrees between + the line of view and earth's surface, that is, looking straight down to earth. +*/ +void QGeoCameraCapabilities::setMinimumTilt(double minimumTilt) +{ + d->minTilt_ = minimumTilt; + d->valid_ = true; +} + +/*! + Returns the minimum tilt supported by the associated plugin. + + The value is in degrees where 0 is equivalent to 90 degrees between + the line of view and earth's surface, that is, looking straight down to earth. +*/ +double QGeoCameraCapabilities::minimumTilt() const +{ + return d->minTilt_; +} + +/*! + Sets the maximum tilt supported by the associated plugin to \a maximumTilt. + + The value is in degrees where 0 is equivalent to 90 degrees between + the line of view and earth's surface, that is, looking straight down to earth. +*/ +void QGeoCameraCapabilities::setMaximumTilt(double maximumTilt) +{ + d->maxTilt_ = maximumTilt; + d->valid_ = true; +} + +/*! + Returns the maximum tilt supported by the associated plugin. + + The value is in degrees where 0 is equivalent to 90 degrees between + the line of view and earth's surface, that is, looking straight down to earth. +*/ +double QGeoCameraCapabilities::maximumTilt() const +{ + return d->maxTilt_; +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeocameracapabilities_p.h b/src/location/maps/qgeocameracapabilities_p.h new file mode 100644 index 0000000..4e498b1 --- /dev/null +++ b/src/location/maps/qgeocameracapabilities_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCAMERACAPABILITIES_P_H +#define QGEOCAMERACAPABILITIES_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoCameraCapabilitiesPrivate; + +class Q_LOCATION_EXPORT QGeoCameraCapabilities +{ +public: + QGeoCameraCapabilities(); + QGeoCameraCapabilities(const QGeoCameraCapabilities &other); + ~QGeoCameraCapabilities(); + + QGeoCameraCapabilities &operator = (const QGeoCameraCapabilities &other); + + void setMinimumZoomLevel(double minimumZoomLevel); + double minimumZoomLevel() const; + + void setMaximumZoomLevel(double maximumZoomLevel); + double maximumZoomLevel() const; + + void setSupportsBearing(bool supportsBearing); + bool supportsBearing() const; + + void setSupportsRolling(bool supportsRolling); + bool supportsRolling() const; + + void setSupportsTilting(bool supportsTilting); + bool supportsTilting() const; + + void setMinimumTilt(double minimumTilt); + double minimumTilt() const; + + void setMaximumTilt(double maximumTilt); + double maximumTilt() const; + + bool isValid() const; + +private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +#endif // QGEOCAMERACAPABILITIES_P_H diff --git a/src/location/maps/qgeocameradata.cpp b/src/location/maps/qgeocameradata.cpp new file mode 100644 index 0000000..2358608 --- /dev/null +++ b/src/location/maps/qgeocameradata.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeocameradata_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCameraDataPrivate : public QSharedData +{ +public: + QGeoCameraDataPrivate(); + QGeoCameraDataPrivate(const QGeoCameraDataPrivate &rhs); + + QGeoCameraDataPrivate &operator = (const QGeoCameraDataPrivate &rhs); + + bool operator == (const QGeoCameraDataPrivate &rhs) const; + + QGeoCoordinate m_center; + double m_bearing; + double m_tilt; + double m_roll; + double m_zoomLevel; +}; + +QGeoCameraDataPrivate::QGeoCameraDataPrivate() + : QSharedData(), + m_center(0, 0), + m_bearing(0.0), + m_tilt(0.0), + m_roll(0.0), + m_zoomLevel(0.0) {} + +QGeoCameraDataPrivate::QGeoCameraDataPrivate(const QGeoCameraDataPrivate &rhs) + : QSharedData(rhs), + m_center(rhs.m_center), + m_bearing(rhs.m_bearing), + m_tilt(rhs.m_tilt), + m_roll(rhs.m_roll), + m_zoomLevel(rhs.m_zoomLevel) {} + +QGeoCameraDataPrivate &QGeoCameraDataPrivate::operator = (const QGeoCameraDataPrivate &rhs) +{ + if (this == &rhs) + return *this; + + m_center = rhs.m_center; + m_bearing = rhs.m_bearing; + m_tilt = rhs.m_tilt; + m_roll = rhs.m_roll; + m_zoomLevel = rhs.m_zoomLevel; + + return *this; +} + +bool QGeoCameraDataPrivate::operator == (const QGeoCameraDataPrivate &rhs) const +{ + return ((m_center == rhs.m_center) + && (m_bearing == rhs.m_bearing) + && (m_tilt == rhs.m_tilt) + && (m_roll == rhs.m_roll) + && (m_zoomLevel == rhs.m_zoomLevel)); +} + +QVariant cameraInterpolator(const QGeoCameraData &start, + const QGeoCameraData &end, + qreal progress) +{ + QGeoCameraData result = start; + QGeoCoordinate from = start.center(); + QGeoCoordinate to = end.center(); + + if (from == to) { + if (progress < 0.5) { + result.setCenter(from); + } else { + result.setCenter(to); + } + } + else { + QGeoCoordinate coordinateResult = QGeoProjection::coordinateInterpolation(from, to, progress); + result.setCenter(coordinateResult); + } + + double sf = 1.0 - progress; + double ef = progress; + + result.setBearing(sf * start.bearing() + ef * end.bearing()); + result.setTilt(sf * start.tilt() + ef * end.tilt()); + result.setRoll(sf * start.roll() + ef * end.roll()); + result.setZoomLevel(sf * start.zoomLevel() + ef * end.zoomLevel()); + + return QVariant::fromValue(result); +} + +QGeoCameraData::QGeoCameraData() + : d(new QGeoCameraDataPrivate()) +{ + qRegisterMetaType(); + qRegisterAnimationInterpolator(cameraInterpolator); +} + +QGeoCameraData::QGeoCameraData(const QGeoCameraData &other) + : d(other.d) {} + +QGeoCameraData::~QGeoCameraData() +{ +} + +QGeoCameraData &QGeoCameraData::operator = (const QGeoCameraData &other) +{ + if (this == &other) + return *this; + + d = other.d; + return *this; +} + +bool QGeoCameraData::operator == (const QGeoCameraData &rhs) const +{ + return (*(d.constData()) == *(rhs.d.constData())); +} + +bool QGeoCameraData::operator != (const QGeoCameraData &other) const +{ + return !(operator==(other)); +} + +void QGeoCameraData::setCenter(const QGeoCoordinate ¢er) +{ + d->m_center = center; +} + +QGeoCoordinate QGeoCameraData::center() const +{ + return d->m_center; +} + +void QGeoCameraData::setBearing(double bearing) +{ + d->m_bearing = bearing; +} + +double QGeoCameraData::bearing() const +{ + return d->m_bearing; +} + +void QGeoCameraData::setTilt(double tilt) +{ + d->m_tilt = tilt; +} + +double QGeoCameraData::tilt() const +{ + return d->m_tilt; +} + +void QGeoCameraData::setRoll(double roll) +{ + d->m_roll = roll; +} + +double QGeoCameraData::roll() const +{ + return d->m_roll; +} + +void QGeoCameraData::setZoomLevel(double zoomFactor) +{ + d->m_zoomLevel = zoomFactor; +} + +double QGeoCameraData::zoomLevel() const +{ + return d->m_zoomLevel; +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeocameradata_p.h b/src/location/maps/qgeocameradata_p.h new file mode 100644 index 0000000..a1434fd --- /dev/null +++ b/src/location/maps/qgeocameradata_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOCAMERADATA_P_H +#define QGEOCAMERADATA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qlocationglobal.h" +#include "qgeocoordinate.h" + +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoCameraDataPrivate; + +class Q_LOCATION_EXPORT QGeoCameraData +{ +public: + QGeoCameraData(); + QGeoCameraData(const QGeoCameraData &other); + ~QGeoCameraData(); + + QGeoCameraData &operator = (const QGeoCameraData &other); + + bool operator == (const QGeoCameraData &other) const; + bool operator != (const QGeoCameraData &other) const; + + void setCenter(const QGeoCoordinate &coordinate); + QGeoCoordinate center() const; + + void setBearing(double bearing); + double bearing() const; + + void setTilt(double tilt); + double tilt() const; + + void setRoll(double roll); + double roll() const; + + void setZoomLevel(double zoomLevel); + double zoomLevel() const; + +private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoCameraData) + +#endif // QGEOCAMERADATA_P_H diff --git a/src/location/maps/qgeocameratiles.cpp b/src/location/maps/qgeocameratiles.cpp new file mode 100644 index 0000000..5eae7c0 --- /dev/null +++ b/src/location/maps/qgeocameratiles.cpp @@ -0,0 +1,946 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeocameratiles_p.h" +#include "qgeocameradata_p.h" +#include "qgeotilespec_p.h" +#include "qgeomaptype_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +struct Frustum +{ + QDoubleVector3D topLeftNear; + QDoubleVector3D topLeftFar; + QDoubleVector3D topRightNear; + QDoubleVector3D topRightFar; + QDoubleVector3D bottomLeftNear; + QDoubleVector3D bottomLeftFar; + QDoubleVector3D bottomRightNear; + QDoubleVector3D bottomRightFar; +}; + +typedef QVector PolygonVector; + +class QGeoCameraTilesPrivate +{ +public: + QGeoCameraTilesPrivate(); + ~QGeoCameraTilesPrivate(); + + QString m_pluginString; + QGeoMapType m_mapType; + int m_mapVersion; + QGeoCameraData m_camera; + QSize m_screenSize; + int m_tileSize; + QSet m_tiles; + + int m_intZoomLevel; + int m_sideLength; + + bool m_dirtyGeometry; + bool m_dirtyMetadata; + + double m_viewExpansion; + void updateMetadata(); + void updateGeometry(); + + Frustum createFrustum(double fieldOfViewGradient) const; + + class LengthSorter + { + public: + QDoubleVector3D base; + bool operator()(const QDoubleVector3D &lhs, const QDoubleVector3D &rhs) + { + return (lhs - base).lengthSquared() < (rhs - base).lengthSquared(); + } + }; + + void appendZIntersects(const QDoubleVector3D &start, const QDoubleVector3D &end, double z, QVector &results) const; + PolygonVector frustumFootprint(const Frustum &frustum) const; + + QPair splitPolygonAtAxisValue(const PolygonVector &polygon, int axis, double value) const; + QPair clipFootprintToMap(const PolygonVector &footprint) const; + + QList > tileIntersections(double p1, int t1, double p2, int t2) const; + QSet tilesFromPolygon(const PolygonVector &polygon) const; + + struct TileMap + { + TileMap(); + + void add(int tileX, int tileY); + + QMap > data; + }; +}; + +QGeoCameraTiles::QGeoCameraTiles() + : d_ptr(new QGeoCameraTilesPrivate()) {} + +QGeoCameraTiles::~QGeoCameraTiles() +{ +} + +void QGeoCameraTiles::setCameraData(const QGeoCameraData &camera) +{ + if (d_ptr->m_camera == camera) + return; + + d_ptr->m_dirtyGeometry = true; + d_ptr->m_camera = camera; + d_ptr->m_intZoomLevel = static_cast(std::floor(d_ptr->m_camera.zoomLevel())); + d_ptr->m_sideLength = 1 << d_ptr->m_intZoomLevel; +} + +QGeoCameraData QGeoCameraTiles::cameraData() const +{ + return d_ptr->m_camera; +} + +void QGeoCameraTiles::setScreenSize(const QSize &size) +{ + if (d_ptr->m_screenSize == size) + return; + + d_ptr->m_dirtyGeometry = true; + d_ptr->m_screenSize = size; +} + +void QGeoCameraTiles::setPluginString(const QString &pluginString) +{ + if (d_ptr->m_pluginString == pluginString) + return; + + d_ptr->m_dirtyMetadata = true; + d_ptr->m_pluginString = pluginString; +} + +void QGeoCameraTiles::setMapType(const QGeoMapType &mapType) +{ + if (d_ptr->m_mapType == mapType) + return; + + d_ptr->m_dirtyMetadata = true; + d_ptr->m_mapType = mapType; +} + +void QGeoCameraTiles::setMapVersion(int mapVersion) +{ + if (d_ptr->m_mapVersion == mapVersion) + return; + + d_ptr->m_dirtyMetadata = true; + d_ptr->m_mapVersion = mapVersion; +} + +void QGeoCameraTiles::setTileSize(int tileSize) +{ + if (d_ptr->m_tileSize == tileSize) + return; + + d_ptr->m_dirtyGeometry = true; + d_ptr->m_tileSize = tileSize; +} + +void QGeoCameraTiles::setViewExpansion(double viewExpansion) +{ + d_ptr->m_viewExpansion = viewExpansion; + d_ptr->m_dirtyGeometry = true; +} + +int QGeoCameraTiles::tileSize() const +{ + return d_ptr->m_tileSize; +} + +const QSet& QGeoCameraTiles::createTiles() +{ + if (d_ptr->m_dirtyGeometry) { + d_ptr->m_tiles.clear(); + d_ptr->updateGeometry(); + d_ptr->m_dirtyGeometry = false; + } + + if (d_ptr->m_dirtyMetadata) { + d_ptr->updateMetadata(); + d_ptr->m_dirtyMetadata = false; + } + + return d_ptr->m_tiles; +} + +QGeoCameraTilesPrivate::QGeoCameraTilesPrivate() +: m_mapVersion(-1), + m_tileSize(0), + m_intZoomLevel(0), + m_sideLength(0), + m_dirtyGeometry(false), + m_dirtyMetadata(false), + m_viewExpansion(1.0) +{ +} + +QGeoCameraTilesPrivate::~QGeoCameraTilesPrivate() {} + +void QGeoCameraTilesPrivate::updateMetadata() +{ + typedef QSet::const_iterator iter; + + QSet newTiles; + + iter i = m_tiles.constBegin(); + iter end = m_tiles.constEnd(); + + for (; i != end; ++i) { + QGeoTileSpec tile = *i; + newTiles.insert(QGeoTileSpec(m_pluginString, m_mapType.mapId(), tile.zoom(), tile.x(), tile.y(), m_mapVersion)); + } + + m_tiles = newTiles; +} + +void QGeoCameraTilesPrivate::updateGeometry() +{ + // Find the frustum from the camera / screen / viewport information + // The larger frustum when stationary is a form of prefetching + Frustum f = createFrustum(m_viewExpansion); + + // Find the polygon where the frustum intersects the plane of the map + PolygonVector footprint = frustumFootprint(f); + + // Clip the polygon to the map, split it up if it cross the dateline + QPair polygons = clipFootprintToMap(footprint); + + if (!polygons.first.isEmpty()) { + QSet tilesLeft = tilesFromPolygon(polygons.first); + m_tiles.unite(tilesLeft); + } + + if (!polygons.second.isEmpty()) { + QSet tilesRight = tilesFromPolygon(polygons.second); + m_tiles.unite(tilesRight); + } +} + +Frustum QGeoCameraTilesPrivate::createFrustum(double fieldOfViewGradient) const +{ + QDoubleVector3D center = m_sideLength * QGeoProjection::coordToMercator(m_camera.center()); + center.setZ(0.0); + + double f = qMin(m_screenSize.width(), m_screenSize.height()); + + double z = std::pow(2.0, m_camera.zoomLevel() - m_intZoomLevel) * m_tileSize; + + double altitude = f / (2.0 * z); + QDoubleVector3D eye = center; + eye.setZ(altitude); + + QDoubleVector3D view = eye - center; + QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); + QDoubleVector3D up = QDoubleVector3D::normal(side, view); + + double nearPlane = 1 / (4.0 * m_tileSize ); + double farPlane = altitude + 1.0; + + double aspectRatio = 1.0 * m_screenSize.width() / m_screenSize.height(); + + double hn,wn,hf,wf = 0.0; + + // fixes field of view at 45 degrees + // this assumes that viewSize = 2*nearPlane x 2*nearPlane + + if (aspectRatio > 1.0) { + hn = 2 * fieldOfViewGradient * nearPlane; + wn = hn * aspectRatio; + + hf = 2 * fieldOfViewGradient * farPlane; + wf = hf * aspectRatio; + } else { + wn = 2 * fieldOfViewGradient * nearPlane; + hn = wn / aspectRatio; + + wf = 2 * fieldOfViewGradient * farPlane; + hf = wf / aspectRatio; + } + + QDoubleVector3D d = center - eye; + d.normalize(); + up.normalize(); + QDoubleVector3D right = QDoubleVector3D::normal(d, up); + + QDoubleVector3D cf = eye + d * farPlane; + QDoubleVector3D cn = eye + d * nearPlane; + + Frustum frustum; + + frustum.topLeftFar = cf + (up * hf / 2) - (right * wf / 2); + frustum.topRightFar = cf + (up * hf / 2) + (right * wf / 2); + frustum.bottomLeftFar = cf - (up * hf / 2) - (right * wf / 2); + frustum.bottomRightFar = cf - (up * hf / 2) + (right * wf / 2); + + frustum.topLeftNear = cn + (up * hn / 2) - (right * wn / 2); + frustum.topRightNear = cn + (up * hn / 2) + (right * wn / 2); + frustum.bottomLeftNear = cn - (up * hn / 2) - (right * wn / 2); + frustum.bottomRightNear = cn - (up * hn / 2) + (right * wn / 2); + + return frustum; +} + +void QGeoCameraTilesPrivate::appendZIntersects(const QDoubleVector3D &start, + const QDoubleVector3D &end, + double z, + QVector &results) const +{ + if (start.z() == end.z()) { + if (start.z() == z) { + results.append(start); + results.append(end); + } + } else { + double f = (start.z() - z) / (start.z() - end.z()); + if ((0 <= f) && (f <= 1.0)) { + results.append((1 - f) * start + f * end); + } + } +} + +/***************************************************/ +/* Local copy of qSort & qSortHelper to suppress deprecation warnings + * following the deprecation of QtAlgorithms. The comparison has subtle + * differences which eluded detection so far. We just reuse old qSort for now. + **/ + +template +inline void localqSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) +{ + if (start != end) + localqSortHelper(start, end, *start, lessThan); +} + +template +void localqSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan) +{ +top: + int span = int(end - start); + if (span < 2) + return; + + --end; + RandomAccessIterator low = start, high = end - 1; + RandomAccessIterator pivot = start + span / 2; + + if (lessThan(*end, *start)) + qSwap(*end, *start); + if (span == 2) + return; + + if (lessThan(*pivot, *start)) + qSwap(*pivot, *start); + if (lessThan(*end, *pivot)) + qSwap(*end, *pivot); + if (span == 3) + return; + + qSwap(*pivot, *end); + + while (low < high) { + while (low < high && lessThan(*low, *end)) + ++low; + + while (high > low && lessThan(*end, *high)) + --high; + + if (low < high) { + qSwap(*low, *high); + ++low; + --high; + } else { + break; + } + } + + if (lessThan(*low, *end)) + ++low; + + qSwap(*end, *low); + localqSortHelper(start, low, t, lessThan); + + start = low + 1; + ++end; + goto top; +} +/***************************************************/ + + +// Returns the intersection of the plane of the map and the camera frustum as a right handed polygon +PolygonVector QGeoCameraTilesPrivate::frustumFootprint(const Frustum &frustum) const +{ + PolygonVector points; + points.reserve(24); + + appendZIntersects(frustum.topLeftNear, frustum.topLeftFar, 0.0, points); + appendZIntersects(frustum.topRightNear, frustum.topRightFar, 0.0, points); + appendZIntersects(frustum.bottomLeftNear, frustum.bottomLeftFar, 0.0, points); + appendZIntersects(frustum.bottomRightNear, frustum.bottomRightFar, 0.0, points); + + appendZIntersects(frustum.topLeftNear, frustum.bottomLeftNear, 0.0, points); + appendZIntersects(frustum.bottomLeftNear, frustum.bottomRightNear, 0.0, points); + appendZIntersects(frustum.bottomRightNear, frustum.topRightNear, 0.0, points); + appendZIntersects(frustum.topRightNear, frustum.topLeftNear, 0.0, points); + + appendZIntersects(frustum.topLeftFar, frustum.bottomLeftFar, 0.0, points); + appendZIntersects(frustum.bottomLeftFar, frustum.bottomRightFar, 0.0, points); + appendZIntersects(frustum.bottomRightFar, frustum.topRightFar, 0.0, points); + appendZIntersects(frustum.topRightFar, frustum.topLeftFar, 0.0, points); + + if (points.isEmpty()) + return points; + + // sort points into a right handed polygon + + LengthSorter sorter; + + // - initial sort to remove duplicates + sorter.base = points.first(); + localqSort(points.begin(), points.end(), sorter); + //std::sort(points.begin(), points.end(), sorter); + for (int i = points.size() - 1; i > 0; --i) { + if (points.at(i) == points.at(i - 1)) + points.remove(i); + } + + // - proper sort + // - start with the first point, put it in the sorted part of the list + // - add the nearest unsorted point to the last sorted point to the end + // of the sorted points + PolygonVector::iterator i; + for (i = points.begin(); i != points.end(); ++i) { + sorter.base = *i; + if (i + 1 != points.end()) + std::sort(i + 1, points.end(), sorter) ; + } + + // - determine if what we have is right handed + int size = points.size(); + if (size >= 3) { + QDoubleVector3D normal = QDoubleVector3D::normal(points.at(1) - points.at(0), + points.at(2) - points.at(1)); + // - if not, reverse the list + if (normal.z() < 0.0) { + int halfSize = size / 2; + for (int i = 0; i < halfSize; ++i) { + QDoubleVector3D spare = points.at(i); + points[i] = points[size - 1 - i]; + points[size - 1 - i] = spare; + } + } + } + + return points; +} + +QPair QGeoCameraTilesPrivate::splitPolygonAtAxisValue(const PolygonVector &polygon, int axis, double value) const +{ + PolygonVector polygonBelow; + PolygonVector polygonAbove; + + int size = polygon.size(); + + if (size == 0) { + return QPair(polygonBelow, polygonAbove); + } + + QVector comparisons = QVector(polygon.size()); + + for (int i = 0; i < size; ++i) { + double v = polygon.at(i).get(axis); + if (qFuzzyCompare(v - value + 1.0, 1.0)) { + comparisons[i] = 0; + } else { + if (v < value) { + comparisons[i] = -1; + } else if (value < v) { + comparisons[i] = 1; + } + } + } + + for (int index = 0; index < size; ++index) { + int prevIndex = index - 1; + if (prevIndex < 0) + prevIndex += size; + int nextIndex = (index + 1) % size; + + int prevComp = comparisons[prevIndex]; + int comp = comparisons[index]; + int nextComp = comparisons[nextIndex]; + + if (comp == 0) { + if (prevComp == -1) { + polygonBelow.append(polygon.at(index)); + if (nextComp == 1) { + polygonAbove.append(polygon.at(index)); + } + } else if (prevComp == 1) { + polygonAbove.append(polygon.at(index)); + if (nextComp == -1) { + polygonBelow.append(polygon.at(index)); + } + } else if (prevComp == 0) { + if (nextComp == -1) { + polygonBelow.append(polygon.at(index)); + } else if (nextComp == 1) { + polygonAbove.append(polygon.at(index)); + } else if (nextComp == 0) { + // do nothing + } + } + } else { + if (comp == -1) { + polygonBelow.append(polygon.at(index)); + } else if (comp == 1) { + polygonAbove.append(polygon.at(index)); + } + + // there is a point between this and the next point + // on the polygon that lies on the splitting line + // and should be added to both the below and above + // polygons + if ((nextComp != 0) && (nextComp != comp)) { + QDoubleVector3D p1 = polygon.at(index); + QDoubleVector3D p2 = polygon.at(nextIndex); + + double p1v = p1.get(axis); + double p2v = p2.get(axis); + + double f = (p1v - value) / (p1v - p2v); + + if (((0 <= f) && (f <= 1.0)) + || qFuzzyCompare(f + 1.0, 1.0) + || qFuzzyCompare(f + 1.0, 2.0) ) { + QDoubleVector3D midPoint = (1.0 - f) * p1 + f * p2; + polygonBelow.append(midPoint); + polygonAbove.append(midPoint); + } + } + } + } + + return QPair(polygonBelow, polygonAbove); +} + + +QPair QGeoCameraTilesPrivate::clipFootprintToMap(const PolygonVector &footprint) const +{ + bool clipX0 = false; + bool clipX1 = false; + bool clipY0 = false; + bool clipY1 = false; + + double side = 1.0 * m_sideLength; + + typedef PolygonVector::const_iterator const_iter; + + const_iter i = footprint.constBegin(); + const_iter end = footprint.constEnd(); + for (; i != end; ++i) { + QDoubleVector3D p = *i; + if ((p.x() < 0.0) || (qFuzzyIsNull(p.x()))) + clipX0 = true; + if ((side < p.x()) || (qFuzzyCompare(side, p.x()))) + clipX1 = true; + if (p.y() < 0.0) + clipY0 = true; + if (side < p.y()) + clipY1 = true; + } + + PolygonVector results = footprint; + + if (clipY0) { + results = splitPolygonAtAxisValue(results, 1, 0.0).second; + } + + if (clipY1) { + results = splitPolygonAtAxisValue(results, 1, side).first; + } + + if (clipX0) { + if (clipX1) { + results = splitPolygonAtAxisValue(results, 0, 0.0).second; + results = splitPolygonAtAxisValue(results, 0, side).first; + return QPair(results, PolygonVector()); + } else { + QPair pair = splitPolygonAtAxisValue(results, 0, 0.0); + if (pair.first.isEmpty()) { + // if we touched the line but didn't cross it... + for (int i = 0; i < pair.second.size(); ++i) { + if (qFuzzyIsNull(pair.second.at(i).x())) + pair.first.append(pair.second.at(i)); + } + if (pair.first.size() == 2) { + double y0 = pair.first[0].y(); + double y1 = pair.first[1].y(); + pair.first.clear(); + pair.first.append(QDoubleVector3D(side, y0, 0.0)); + pair.first.append(QDoubleVector3D(side - 0.001, y0, 0.0)); + pair.first.append(QDoubleVector3D(side - 0.001, y1, 0.0)); + pair.first.append(QDoubleVector3D(side, y1, 0.0)); + } else if (pair.first.size() == 1) { + // FIXME this is trickier + // - touching at one point on the tile boundary + // - probably need to build a triangular polygon across the edge + // - don't want to add another y tile if we can help it + // - initial version doesn't care + double y = pair.first.at(0).y(); + pair.first.clear(); + pair.first.append(QDoubleVector3D(side - 0.001, y, 0.0)); + pair.first.append(QDoubleVector3D(side, y + 0.001, 0.0)); + pair.first.append(QDoubleVector3D(side, y - 0.001, 0.0)); + } + } else { + for (int i = 0; i < pair.first.size(); ++i) { + pair.first[i].setX(pair.first.at(i).x() + side); + } + } + return pair; + } + } else { + if (clipX1) { + QPair pair = splitPolygonAtAxisValue(results, 0, side); + if (pair.second.isEmpty()) { + // if we touched the line but didn't cross it... + for (int i = 0; i < pair.first.size(); ++i) { + if (qFuzzyCompare(side, pair.first.at(i).x())) + pair.second.append(pair.first.at(i)); + } + if (pair.second.size() == 2) { + double y0 = pair.second[0].y(); + double y1 = pair.second[1].y(); + pair.second.clear(); + pair.second.append(QDoubleVector3D(0, y0, 0.0)); + pair.second.append(QDoubleVector3D(0.001, y0, 0.0)); + pair.second.append(QDoubleVector3D(0.001, y1, 0.0)); + pair.second.append(QDoubleVector3D(0, y1, 0.0)); + } else if (pair.second.size() == 1) { + // FIXME this is trickier + // - touching at one point on the tile boundary + // - probably need to build a triangular polygon across the edge + // - don't want to add another y tile if we can help it + // - initial version doesn't care + double y = pair.second.at(0).y(); + pair.second.clear(); + pair.second.append(QDoubleVector3D(0.001, y, 0.0)); + pair.second.append(QDoubleVector3D(0.0, y - 0.001, 0.0)); + pair.second.append(QDoubleVector3D(0.0, y + 0.001, 0.0)); + } + } else { + for (int i = 0; i < pair.second.size(); ++i) { + pair.second[i].setX(pair.second.at(i).x() - side); + } + } + return pair; + } else { + return QPair(results, PolygonVector()); + } + } + +} + +QList > QGeoCameraTilesPrivate::tileIntersections(double p1, int t1, double p2, int t2) const +{ + if (t1 == t2) { + QList > results = QList >(); + results.append(QPair(0.0, t1)); + return results; + } + + int step = 1; + if (t1 > t2) { + step = -1; + } + + int size = 1 + ((t2 - t1) / step); + + QList > results = QList >(); + + results.append(QPair(0.0, t1)); + + if (step == 1) { + for (int i = 1; i < size; ++i) { + double f = (t1 + i - p1) / (p2 - p1); + results.append(QPair(f, t1 + i)); + } + } else { + for (int i = 1; i < size; ++i) { + double f = (t1 - i + 1 - p1) / (p2 - p1); + results.append(QPair(f, t1 - i)); + } + } + + return results; +} + +QSet QGeoCameraTilesPrivate::tilesFromPolygon(const PolygonVector &polygon) const +{ + int numPoints = polygon.size(); + + if (numPoints == 0) + return QSet(); + + QVector tilesX(polygon.size()); + QVector tilesY(polygon.size()); + + // grab tiles at the corners of the polygon + for (int i = 0; i < numPoints; ++i) { + + QDoubleVector2D p = polygon.at(i).toVector2D(); + + int x = 0; + int y = 0; + + if (qFuzzyCompare(p.x(), m_sideLength * 1.0)) + x = m_sideLength - 1; + else { + x = static_cast(p.x()) % m_sideLength; + if ( !qFuzzyCompare(p.x(), 1.0 * x) && qFuzzyCompare(p.x(), 1.0 * (x + 1)) ) + x++; + } + + if (qFuzzyCompare(p.y(), m_sideLength * 1.0)) + y = m_sideLength - 1; + else { + y = static_cast(p.y()) % m_sideLength; + if ( !qFuzzyCompare(p.y(), 1.0 * y) && qFuzzyCompare(p.y(), 1.0 * (y + 1)) ) + y++; + } + + tilesX[i] = x; + tilesY[i] = y; + } + + QGeoCameraTilesPrivate::TileMap map; + + // walk along the edges of the polygon and add all tiles covered by them + for (int i1 = 0; i1 < numPoints; ++i1) { + int i2 = (i1 + 1) % numPoints; + + double x1 = polygon.at(i1).get(0); + double x2 = polygon.at(i2).get(0); + + bool xFixed = qFuzzyCompare(x1, x2); + bool xIntegral = qFuzzyCompare(x1, std::floor(x1)) || qFuzzyCompare(x1 + 1.0, std::floor(x1 + 1.0)); + + QList > xIntersects + = tileIntersections(x1, + tilesX.at(i1), + x2, + tilesX.at(i2)); + + double y1 = polygon.at(i1).get(1); + double y2 = polygon.at(i2).get(1); + + bool yFixed = qFuzzyCompare(y1, y2); + bool yIntegral = qFuzzyCompare(y1, std::floor(y1)) || qFuzzyCompare(y1 + 1.0, std::floor(y1 + 1.0)); + + QList > yIntersects + = tileIntersections(y1, + tilesY.at(i1), + y2, + tilesY.at(i2)); + + int x = xIntersects.takeFirst().second; + int y = yIntersects.takeFirst().second; + + + /* + If the polygon coincides with the tile edges we must be + inclusive and grab all tiles on both sides. We also need + to handle tiles with corners coindent with the + corners of the polygon. + e.g. all tiles marked with 'x' will be added + + "+" - tile boundaries + "O" - polygon boundary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + x + x + x + + + + + + + + + + + + + + + + + + O O O O O + + + + + + + + + + + O 0 + + + + + x O x 0 x + + + + + O 0 + + + + + + + + + + + O 0 0 0 0 + + + + + + + + + + + + + + + + + + x + x + x + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + */ + + + int xOther = x; + int yOther = y; + + if (xFixed && xIntegral) { + if (y2 < y1) { + xOther = qMax(0, x - 1); + } + } + + if (yFixed && yIntegral) { + if (x1 < x2) { + yOther = qMax(0, y - 1); + + } + } + + if (xIntegral) { + map.add(xOther, y); + if (yIntegral) + map.add(xOther, yOther); + + } + + if (yIntegral) + map.add(x, yOther); + + map.add(x,y); + + // top left corner + int iPrev = (i1 + numPoints - 1) % numPoints; + double xPrevious = polygon.at(iPrev).get(0); + double yPrevious = polygon.at(iPrev).get(1); + bool xPreviousFixed = qFuzzyCompare(xPrevious, x1); + if (xIntegral && xPreviousFixed && yIntegral && yFixed) { + if ((x2 > x1) && (yPrevious > y1)) { + if ((x - 1) > 0 && (y - 1) > 0) + map.add(x - 1, y - 1); + } else if ((x2 < x1) && (yPrevious < y1)) { + // what? + } + } + + // for the simple case where intersections do not coincide with + // the boundaries, we move along the edge and add tiles until + // the x and y intersection lists are exhausted + + while (!xIntersects.isEmpty() && !yIntersects.isEmpty()) { + QPair nextX = xIntersects.first(); + QPair nextY = yIntersects.first(); + if (nextX.first < nextY.first) { + x = nextX.second; + map.add(x, y); + xIntersects.removeFirst(); + + } else if (nextX.first > nextY.first) { + y = nextY.second; + map.add(x, y); + yIntersects.removeFirst(); + + } else { + map.add(x, nextY.second); + map.add(nextX.second, y); + x = nextX.second; + y = nextY.second; + map.add(x, y); + xIntersects.removeFirst(); + yIntersects.removeFirst(); + } + } + + while (!xIntersects.isEmpty()) { + x = xIntersects.takeFirst().second; + map.add(x, y); + if (yIntegral && yFixed) + map.add(x, yOther); + + } + + while (!yIntersects.isEmpty()) { + y = yIntersects.takeFirst().second; + map.add(x, y); + if (xIntegral && xFixed) + map.add(xOther, y); + } + } + + QSet results; + + int z = m_intZoomLevel; + + typedef QMap >::const_iterator iter; + iter i = map.data.constBegin(); + iter end = map.data.constEnd(); + + for (; i != end; ++i) { + int y = i.key(); + int minX = i->first; + int maxX = i->second; + for (int x = minX; x <= maxX; ++x) { + results.insert(QGeoTileSpec(m_pluginString, m_mapType.mapId(), z, x, y, m_mapVersion)); + } + } + + return results; +} + +QGeoCameraTilesPrivate::TileMap::TileMap() {} + +void QGeoCameraTilesPrivate::TileMap::add(int tileX, int tileY) +{ + if (data.contains(tileY)) { + int oldMinX = data.value(tileY).first; + int oldMaxX = data.value(tileY).second; + data.insert(tileY, QPair(qMin(tileX, oldMinX), qMax(tileX, oldMaxX))); + } else { + data.insert(tileY, QPair(tileX, tileX)); + } +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeocameratiles_p.h b/src/location/maps/qgeocameratiles_p.h new file mode 100644 index 0000000..d10895f --- /dev/null +++ b/src/location/maps/qgeocameratiles_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOCAMERATILES_P_H +#define QGEOCAMERATILES_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCameraData; +class QGeoTileSpec; +class QGeoMapType; +class QGeoCameraTilesPrivate; +class QSize; + +class Q_LOCATION_EXPORT QGeoCameraTiles { +public: + QGeoCameraTiles(); + ~QGeoCameraTiles(); + + void setCameraData(const QGeoCameraData &camera); + QGeoCameraData cameraData() const; + void setScreenSize(const QSize &size); + void setTileSize(int tileSize); + int tileSize() const; + void setViewExpansion(double viewExpansion); + void setPluginString(const QString &pluginString); + void setMapType(const QGeoMapType &mapType); + void setMapVersion(int mapVersion); + const QSet& createTiles(); + +protected: + QScopedPointer d_ptr; + Q_DISABLE_COPY(QGeoCameraTiles) +}; + +QT_END_NAMESPACE + +#endif // QGEOCAMERATILES_P_H diff --git a/src/location/maps/qgeocodereply.cpp b/src/location/maps/qgeocodereply.cpp new file mode 100644 index 0000000..4701821 --- /dev/null +++ b/src/location/maps/qgeocodereply.cpp @@ -0,0 +1,329 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocodereply.h" +#include "qgeocodereply_p.h" + +QT_BEGIN_NAMESPACE +/*! + \class QGeoCodeReply + \inmodule QtLocation + \ingroup QtLocation-geocoding + \since 5.6 + + \brief The QGeoCodeReply class manages an operation started by an + instance of QGeoCodingManager. + + Instances of QGeoCodeReply manage the state and results of these + operations. + + The isFinished(), error() and errorString() methods provide information + on whether the operation has completed and if it completed successfully. + + The finished() and error(QGeoCodeReply::Error,QString) + signals can be used to monitor the progress of the operation. + + It is possible that a newly created QGeoCodeReply may be in a finished + state, most commonly because an error has occurred. Since such an instance + will never emit the finished() or + error(QGeoCodeReply::Error,QString) signals, it is + important to check the result of isFinished() before making the connections + to the signals. The documentation for QGeoCodingManager demonstrates how + this might be carried out. + + If the operation completes successfully the results will be able to be + accessed with locations(). +*/ + +/*! + \enum QGeoCodeReply::Error + + Describes an error which prevented the completion of the operation. + + \value NoError + No error has occurred. + \value EngineNotSetError + The geocoding manager that was used did not have a QGeoCodingManagerEngine instance associated with it. + \value CommunicationError + An error occurred while communicating with the service provider. + \value ParseError + The response from the service provider was in an unrecognizable format. + \value UnsupportedOptionError + The requested operation or one of the options for the operation are not + supported by the service provider. + \value CombinationError + An error occurred while results where being combined from multiple sources. + \value UnknownError + An error occurred which does not fit into any of the other categories. +*/ + +/*! + Constructs a geocode reply with the specified \a parent. +*/ +QGeoCodeReply::QGeoCodeReply(QObject *parent) + : QObject(parent), + d_ptr(new QGeoCodeReplyPrivate()) {} + +/*! + Constructs a geocode reply with a given \a error and \a errorString and the specified \a parent. +*/ +QGeoCodeReply::QGeoCodeReply(Error error, const QString &errorString, QObject *parent) + : QObject(parent), + d_ptr(new QGeoCodeReplyPrivate(error, errorString)) {} + +/*! + Destroys this reply object. +*/ +QGeoCodeReply::~QGeoCodeReply() +{ + delete d_ptr; +} + +/*! + Sets whether or not this reply has finished to \a finished. + + If \a finished is true, this will cause the finished() signal to be + emitted. + + If the operation completed successfully, QGeoCodeReply::setLocations() + should be called before this function. If an error occurred, + QGeoCodeReply::setError() should be used instead. +*/ +void QGeoCodeReply::setFinished(bool finished) +{ + d_ptr->isFinished = finished; + if (d_ptr->isFinished) + emit this->finished(); +} + +/*! + Return true if the operation completed successfully or encountered an + error which cause the operation to come to a halt. +*/ +bool QGeoCodeReply::isFinished() const +{ + return d_ptr->isFinished; +} + +/*! + Sets the error state of this reply to \a error and the textual + representation of the error to \a errorString. + + This will also cause error() and finished() signals to be emitted, in that + order. +*/ +void QGeoCodeReply::setError(QGeoCodeReply::Error error, const QString &errorString) +{ + d_ptr->error = error; + d_ptr->errorString = errorString; + emit this->error(error, errorString); + setFinished(true); +} + +/*! + Returns the error state of this reply. + + If the result is QGeoCodeReply::NoError then no error has occurred. +*/ +QGeoCodeReply::Error QGeoCodeReply::error() const +{ + return d_ptr->error; +} + +/*! + Returns the textual representation of the error state of this reply. + + If no error has occurred this will return an empty string. It is possible + that an error occurred which has no associated textual representation, in + which case this will also return an empty string. + + To determine whether an error has occurred, check to see if + QGeoCodeReply::error() is equal to QGeoCodeReply::NoError. +*/ +QString QGeoCodeReply::errorString() const +{ + return d_ptr->errorString; +} + +/*! + Sets the viewport which contains the results to \a viewport. +*/ +void QGeoCodeReply::setViewport(const QGeoShape &viewport) +{ + d_ptr->viewport = viewport; +} + +/*! + Returns the viewport which contains the results. + + This function will return 0 if no viewport bias + was specified in the QGeoCodingManager function which created this reply. +*/ +QGeoShape QGeoCodeReply::viewport() const +{ + return d_ptr->viewport; +} + +/*! + Returns a list of locations. + + The locations are the results of the operation corresponding to the + QGeoCodingManager function which created this reply. +*/ +QList QGeoCodeReply::locations() const +{ + return d_ptr->locations; +} + +/*! + Adds \a location to the list of locations in this reply. +*/ +void QGeoCodeReply::addLocation(const QGeoLocation &location) +{ + d_ptr->locations.append(location); +} + +/*! + Sets the list of \a locations in the reply. +*/ +void QGeoCodeReply::setLocations(const QList &locations) +{ + d_ptr->locations = locations; +} + +/*! + Cancels the operation immediately. + + This will do nothing if the reply is finished. +*/ +void QGeoCodeReply::abort() +{ + if (!isFinished()) + setFinished(true); +} + +/*! + Returns the limit on the number of responses from each data source. + + If no limit was set this function will return -1. + + This may be more than locations().length() if the number of responses + was less than the number requested. +*/ +int QGeoCodeReply::limit() const +{ + return d_ptr->limit; +} + +/*! + Returns the offset into the entire result set at which to start + fetching results. +*/ +int QGeoCodeReply::offset() const +{ + return d_ptr->offset; +} + +/*! + Sets the limit on the number of responses from each data source to \a limit. + + If \a limit is -1 then all available responses will be returned. +*/ +void QGeoCodeReply::setLimit(int limit) +{ + d_ptr->limit = limit; +} + +/*! + Sets the offset in the entire result set at which to start + fetching result to \a offset. +*/ +void QGeoCodeReply::setOffset(int offset) +{ + d_ptr->offset = offset; +} + +/*! + \fn void QGeoCodeReply::finished() + + This signal is emitted when this reply has finished processing. + + If error() equals QGeoCodeReply::NoError then the processing + finished successfully. + + This signal and QGeoCodingManager::finished() will be + emitted at the same time. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ +/*! + \fn void QGeoCodeReply::error(QGeoCodeReply::Error error, const QString &errorString) + + This signal is emitted when an error has been detected in the processing of + this reply. The finished() signal will probably follow. + + The error will be described by the error code \a error. If \a errorString is + not empty it will contain a textual description of the error. + + This signal and QGeoCodingManager::error() will be emitted at the same time. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ + +/******************************************************************************* +*******************************************************************************/ + +QGeoCodeReplyPrivate::QGeoCodeReplyPrivate() + : error(QGeoCodeReply::NoError), + isFinished(false), + limit(-1), + offset(0) {} + +QGeoCodeReplyPrivate::QGeoCodeReplyPrivate(QGeoCodeReply::Error error, const QString &errorString) + : error(error), + errorString(errorString), + isFinished(true), + limit(-1), + offset(0) {} + +QGeoCodeReplyPrivate::~QGeoCodeReplyPrivate() {} + + +#include "moc_qgeocodereply.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeocodereply.h b/src/location/maps/qgeocodereply.h new file mode 100644 index 0000000..048493b --- /dev/null +++ b/src/location/maps/qgeocodereply.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODEREPLY_H +#define QGEOCODEREPLY_H + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoShape; +class QGeoCodeReplyPrivate; + +class Q_LOCATION_EXPORT QGeoCodeReply : public QObject +{ + Q_OBJECT + +public: + enum Error { + NoError, + EngineNotSetError, + CommunicationError, + ParseError, + UnsupportedOptionError, + CombinationError, + UnknownError + }; + + explicit QGeoCodeReply(Error error, const QString &errorString, QObject *parent = Q_NULLPTR); + virtual ~QGeoCodeReply(); + + bool isFinished() const; + Error error() const; + QString errorString() const; + + QGeoShape viewport() const; + QList locations() const; + + int limit() const; + int offset() const; + + virtual void abort(); + +Q_SIGNALS: + void finished(); + void error(QGeoCodeReply::Error error, const QString &errorString = QString()); + +protected: + explicit QGeoCodeReply(QObject *parent = Q_NULLPTR); + + void setError(Error error, const QString &errorString); + void setFinished(bool finished); + + void setViewport(const QGeoShape &viewport); + void addLocation(const QGeoLocation &location); + void setLocations(const QList &locations); + + void setLimit(int limit); + void setOffset(int offset); + +private: + QGeoCodeReplyPrivate *d_ptr; + Q_DISABLE_COPY(QGeoCodeReply) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeocodereply_p.h b/src/location/maps/qgeocodereply_p.h new file mode 100644 index 0000000..fefe788 --- /dev/null +++ b/src/location/maps/qgeocodereply_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODEREPLY_P_H +#define QGEOCODEREPLY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeocodereply.h" + +#include "qgeoshape.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoLocation; + +class QGeoCodeReplyPrivate +{ +public: + QGeoCodeReplyPrivate(); + QGeoCodeReplyPrivate(QGeoCodeReply::Error error, const QString &errorString); + ~QGeoCodeReplyPrivate(); + + QGeoCodeReply::Error error; + QString errorString; + bool isFinished; + + QGeoShape viewport; + QList locations; + + int limit; + int offset; +private: + Q_DISABLE_COPY(QGeoCodeReplyPrivate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeocodingmanager.cpp b/src/location/maps/qgeocodingmanager.cpp new file mode 100644 index 0000000..70c5de8 --- /dev/null +++ b/src/location/maps/qgeocodingmanager.cpp @@ -0,0 +1,327 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocodingmanager.h" +#include "qgeocodingmanager_p.h" +#include "qgeocodingmanagerengine.h" + +#include "qgeorectangle.h" +#include "qgeocircle.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoCodingManager + \inmodule QtLocation + \ingroup QtLocation-geocoding + \since 5.6 + + \brief The QGeoCodingManager class provides support for geocoding + operations. + + The geocode() and reverseGeocode() functions return + QGeoCodeReply objects, which manage these operations and report on the + result of the operations and any errors which may have occurred. + + The geocode() and reverseGeocode() functions can be used to convert + QGeoAddress instances to QGeoCoordinate instances and vice-versa. + + The geocode() function is also overloaded to allow a user to perform a free text + geocoding operation, if the string provided can be interpreted as + an address it can be geocoded to coordinate information. + + Instances of QGeoCodingManager can be accessed with + QGeoServiceProvider::geocodingManager(). +*/ + +/*! + Constructs a new manager with the specified \a parent and with the + implementation provided by \a engine. + + This constructor is used interally by QGeoServiceProviderFactory. Regular + users should acquire instances of QGeoCodingManager with + QGeoServiceProvider::geocodingManager(); +*/ +QGeoCodingManager::QGeoCodingManager(QGeoCodingManagerEngine *engine, QObject *parent) + : QObject(parent), + d_ptr(new QGeoCodingManagerPrivate()) +{ + d_ptr->engine = engine; + if (d_ptr->engine) { + d_ptr->engine->setParent(this); + + connect(d_ptr->engine, + SIGNAL(finished(QGeoCodeReply*)), + this, + SIGNAL(finished(QGeoCodeReply*))); + + connect(d_ptr->engine, + SIGNAL(error(QGeoCodeReply*,QGeoCodeReply::Error,QString)), + this, + SIGNAL(error(QGeoCodeReply*,QGeoCodeReply::Error,QString))); + } else { + qFatal("The geocoding manager engine that was set for this geocoding manager was NULL."); + } +} + +/*! + Destroys this manager. +*/ +QGeoCodingManager::~QGeoCodingManager() +{ + delete d_ptr; +} + +/*! + Returns the name of the engine which implements the behaviour of this + geocoding manager. + + The combination of managerName() and managerVersion() should be unique + amongst the plugin implementations. +*/ +QString QGeoCodingManager::managerName() const +{ +// if (!d_ptr->engine) +// return QString(); + + return d_ptr->engine->managerName(); +} + +/*! + Returns the version of the engine which implements the behaviour of this + geocoding manager. + + The combination of managerName() and managerVersion() should be unique + amongst the plugin implementations. +*/ +int QGeoCodingManager::managerVersion() const +{ +// if (!d_ptr->engine) +// return -1; + + return d_ptr->engine->managerVersion(); +} + +/*! + Begins the geocoding of \a address. Geocoding is the process of finding a + coordinate that corresponds to a given address. + + A QGeoCodeReply object will be returned, which can be used to manage the + geocoding operation and to return the results of the operation. + + This manager and the returned QGeoCodeReply object will emit signals + indicating if the operation completes or if errors occur. + + If supportsGeocoding() returns false an + QGeoCodeReply::UnsupportedOptionError will occur. + + Once the operation has completed, QGeoCodeReply::locations() can be used to + retrieve the results, which will consist of a list of QGeoLocation objects. + These objects represent a combination of coordinate and address data. + + The address data returned in the results may be different from \a address. + This will usually occur if the geocoding service backend uses a different + canonical form of addresses or if \a address was only partially filled out. + + If \a bounds is non-null and is a valid QGeoShape it will be used to + limit the results to those that are contained within \a bounds. This is + particularly useful if \a address is only partially filled out, as the + service will attempt to geocode all matches for the specified data. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoCodingManager::finished(), + QGeoCodingManager::error(), QGeoCodeReply::finished() or + QGeoCodeReply::error() with deleteLater(). +*/ +QGeoCodeReply *QGeoCodingManager::geocode(const QGeoAddress &address, const QGeoShape &bounds) +{ + return d_ptr->engine->geocode(address, bounds); +} + + +/*! + Begins the reverse geocoding of \a coordinate. Reverse geocoding is the + process of finding an address that corresponds to a given coordinate. + + A QGeoCodeReply object will be returned, which can be used to manage the + reverse geocoding operation and to return the results of the operation. + + This manager and the returned QGeoCodeReply object will emit signals + indicating if the operation completes or if errors occur. + + If supportsReverseGeocoding() returns false an + QGeoCodeReply::UnsupportedOptionError will occur. + + At that point QGeoCodeReply::locations() can be used to retrieve the + results, which will consist of a list of QGeoLocation objects. These objects + represent a combination of coordinate and address data. + + The coordinate data returned in the results may be different from \a + coordinate. This will usually occur if the reverse geocoding service + backend shifts the coordinates to be closer to the matching addresses, or + if the backend returns results at multiple levels of detail. + + If multiple results are returned by the reverse geocoding service backend + they will be provided in order of specificity. This normally occurs if the + backend is configured to reverse geocode across multiple levels of detail. + As an example, some services will return address and coordinate pairs for + the street address, the city, the state and the country. + + If \a bounds is non-null and a valid QGeoRectangle it will be used to + limit the results to those that are contained within \a bounds. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoCodingManager::finished(), + QGeoCodingManager::error(), QGeoCodeReply::finished() or + QGeoCodeReply::error() with deleteLater(). +*/ +QGeoCodeReply *QGeoCodingManager::reverseGeocode(const QGeoCoordinate &coordinate, const QGeoShape &bounds) +{ + return d_ptr->engine->reverseGeocode(coordinate, bounds); +} + +/*! + Begins geocoding for a location matching \a address. + + A QGeoCodeReply object will be returned, which can be used to manage the + geocoding operation and to return the results of the operation. + + This manager and the returned QGeoCodeReply object will emit signals + indicating if the operation completes or if errors occur. + + Once the operation has completed, QGeoCodeReply::locations() can be used to + retrieve the results, which will consist of a list of QGeoLocation objects. + These objects represent a combination of coordinate and address data. + + If \a limit is -1 the entire result set will be returned, otherwise at most + \a limit results will be returned. + + The \a offset parameter is used to ask the geocoding service to not return the + first \a offset results. + + The \a limit and \a offset results are used together to implement paging. + + If \a bounds is non-null and a valid QGeoShape it will be used to + limit the results to those that are contained within \a bounds. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoCodingManager::finished(), + QGeoCodingManager::error(), QGeoCodeReply::finished() or + QGeoCodeReply::error() with deleteLater(). +*/ +QGeoCodeReply *QGeoCodingManager::geocode(const QString &address, + int limit, + int offset, + const QGeoShape &bounds) +{ + QGeoCodeReply *reply = d_ptr->engine->geocode(address, + limit, + offset, + bounds); + return reply; +} + +/*! + Sets the locale to be used by this manager to \a locale. + + If this geocoding manager supports returning the results + in different languages, they will be returned in the language of \a locale. + + The locale used defaults to the system locale if this is not set. +*/ +void QGeoCodingManager::setLocale(const QLocale &locale) +{ + d_ptr->engine->setLocale(locale); +} + +/*! + Returns the locale used to hint to this geocoding manager about what + language to use for the results. +*/ +QLocale QGeoCodingManager::locale() const +{ + return d_ptr->engine->locale(); +} + +/*! +\fn void QGeoCodingManager::finished(QGeoCodeReply *reply) + + This signal is emitted when \a reply has finished processing. + + If reply::error() equals QGeoCodeReply::NoError then the processing + finished successfully. + + This signal and QGeoCodeReply::finished() will be emitted at the same + time. + + \note Do not delete the \a reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ + +/*! +\fn void QGeoCodingManager::error(QGeoCodeReply *reply, QGeoCodeReply::Error error, QString errorString) + + This signal is emitted when an error has been detected in the processing of + \a reply. The QGeoCodingManager::finished() signal will probably follow. + + The error will be described by the error code \a error. If \a errorString is + not empty it will contain a textual description of the error. + + This signal and QGeoCodeReply::error() will be emitted at the same time. + + \note Do not delete the \a reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ + +/******************************************************************************* +*******************************************************************************/ + +QGeoCodingManagerPrivate::QGeoCodingManagerPrivate() + : engine(0) {} + +QGeoCodingManagerPrivate::~QGeoCodingManagerPrivate() +{ + delete engine; +} + +/******************************************************************************* +*******************************************************************************/ + +#include "moc_qgeocodingmanager.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeocodingmanager.h b/src/location/maps/qgeocodingmanager.h new file mode 100644 index 0000000..eb366f6 --- /dev/null +++ b/src/location/maps/qgeocodingmanager.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODINGMANAGER_H +#define QGEOCODINGMANAGER_H + +#include +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QLocale; + +class QGeoCodingManagerEngine; +class QGeoCodingManagerPrivate; + +class Q_LOCATION_EXPORT QGeoCodingManager : public QObject +{ + Q_OBJECT +public: + ~QGeoCodingManager(); + + QString managerName() const; + int managerVersion() const; + + QGeoCodeReply *geocode(const QGeoAddress &address, + const QGeoShape &bounds = QGeoShape()); + QGeoCodeReply *geocode(const QString &searchString, + int limit = -1, + int offset = 0, + const QGeoShape &bounds = QGeoShape()); + + QGeoCodeReply *reverseGeocode(const QGeoCoordinate &coordinate, + const QGeoShape &bounds = QGeoShape()); + + void setLocale(const QLocale &locale); + QLocale locale() const; + +Q_SIGNALS: + void finished(QGeoCodeReply *reply); + void error(QGeoCodeReply *reply, QGeoCodeReply::Error error, QString errorString = QString()); + +private: + explicit QGeoCodingManager(QGeoCodingManagerEngine *engine, QObject *parent = Q_NULLPTR); + + QGeoCodingManagerPrivate *d_ptr; + Q_DISABLE_COPY(QGeoCodingManager) + + friend class QGeoServiceProvider; + friend class QGeoServiceProviderPrivate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeocodingmanager_p.h b/src/location/maps/qgeocodingmanager_p.h new file mode 100644 index 0000000..de723ee --- /dev/null +++ b/src/location/maps/qgeocodingmanager_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODINGMANAGER_P_H +#define QGEOCODINGMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeocodingmanager.h" + +#include "qgeocodereply.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoCodingManagerEngine; + +class QGeoCodingManagerPrivate +{ +public: + QGeoCodingManagerPrivate(); + ~QGeoCodingManagerPrivate(); + + QGeoCodingManagerEngine *engine; + +private: + Q_DISABLE_COPY(QGeoCodingManagerPrivate) +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/location/maps/qgeocodingmanagerengine.cpp b/src/location/maps/qgeocodingmanagerengine.cpp new file mode 100644 index 0000000..b163d17 --- /dev/null +++ b/src/location/maps/qgeocodingmanagerengine.cpp @@ -0,0 +1,336 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocodingmanagerengine.h" +#include "qgeocodingmanagerengine_p.h" + +#include "qgeoaddress.h" +#include "qgeocoordinate.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoCodingManagerEngine + \inmodule QtLocation + \ingroup QtLocation-impl + \since 5.6 + + \brief The QGeoCodingManagerEngine class provides an interface and + convenience methods to implementers of QGeoServiceProvider plugins who want + to provide support for geocoding operations. + + In the default implementation, supportsGeocoding() and supportsReverseGeocoding() returns false while + geocode() and reverseGeocode() + cause QGeoCodeReply::UnsupportedOptionError to occur. + + If the service provider supports geocoding the subclass should provide an + implementation of geocode() and call setSupportsGeocoding(true) at + some point in time before geocode() is called. + + Similarly, if the service provider supports reverse geocoding the subclass + should provide an implementation reverseGeocode() and call + setSupportsReverseGeocoding(true) at some point in time before + reverseGeocode() is called. + + A subclass of QGeoCodingManagerEngine will often make use of a subclass + fo QGeoCodeReply internally, in order to add any engine-specific + data (such as a QNetworkReply object for network-based services) to the + QGeoCodeReply instances used by the engine. + + \sa QGeoCodingManager +*/ + +/*! + Constructs a new engine with the specified \a parent, using \a parameters + to pass any implementation specific data to the engine. +*/ +QGeoCodingManagerEngine::QGeoCodingManagerEngine(const QVariantMap ¶meters, QObject *parent) + : QObject(parent), + d_ptr(new QGeoCodingManagerEnginePrivate()) +{ + Q_UNUSED(parameters) +} + +/*! + Destroys this engine. +*/ +QGeoCodingManagerEngine::~QGeoCodingManagerEngine() +{ + delete d_ptr; +} + +/*! + Sets the name which this engine implementation uses to distinguish itself + from the implementations provided by other plugins to \a managerName. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +void QGeoCodingManagerEngine::setManagerName(const QString &managerName) +{ + d_ptr->managerName = managerName; +} + +/*! + Returns the name which this engine implementation uses to distinguish + itself from the implementations provided by other plugins. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +QString QGeoCodingManagerEngine::managerName() const +{ + return d_ptr->managerName; +} + +/*! + Sets the version of this engine implementation to \a managerVersion. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +void QGeoCodingManagerEngine::setManagerVersion(int managerVersion) +{ + d_ptr->managerVersion = managerVersion; +} + +/*! + Returns the version of this engine implementation. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +int QGeoCodingManagerEngine::managerVersion() const +{ + return d_ptr->managerVersion; +} + +/*! + Begins the geocoding of \a address. Geocoding is the process of finding a + coordinate that corresponds to a given address. + + A QGeoCodeReply object will be returned, which can be used to manage the + geocoding operation and to return the results of the operation. + + This engine and the returned QGeoCodeReply object will emit signals + indicating if the operation completes or if errors occur. + + If supportsGeocoding() returns false an + QGeoCodeReply::UnsupportedOptionError will occur. + + Once the operation has completed, QGeoCodeReply::locations() can be used to + retrieve the results, which will consist of a list of QGeoLocation objects. + These objects represent a combination of coordinate and address data. + + The address data returned in the results may be different from \a address. + This will usually occur if the geocoding service backend uses a different + canonical form of addresses or if \a address was only partially filled out. + + If \a bounds is non-null and a valid QGeoShape it will be used to + limit the results to those that are contained by \a bounds. This is + particularly useful if \a address is only partially filled out, as the + service will attempt to geocode all matches for the specified data. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoCodingManagerEngine::finished(), + QGeoCodingManagerEngine::error(), QGeoCodeReply::finished() or + QGeoCodeReply::error() with deleteLater(). +*/ +QGeoCodeReply *QGeoCodingManagerEngine::geocode(const QGeoAddress &address, + const QGeoShape &bounds) +{ + Q_UNUSED(address) + Q_UNUSED(bounds) + return new QGeoCodeReply(QGeoCodeReply::UnsupportedOptionError, + QLatin1String("Geocoding is not supported by this service provider."), this); +} + +/*! + Begins the reverse geocoding of \a coordinate. Reverse geocoding is the + process of finding an address that corresponds to a given coordinate. + + A QGeoCodeReply object will be returned, which can be used to manage the + reverse geocoding operation and to return the results of the operation. + + This engine and the returned QGeoCodeReply object will emit signals + indicating if the operation completes or if errors occur. + + If supportsReverseGeocoding() returns false an + QGeoCodeReply::UnsupportedOptionError will occur. + + At that point QGeoCodeReply::locations() can be used to retrieve the + results, which will consist of a list of QGeoLocation objects. These objects + represent a combination of coordinate and address data. + + The coordinate data returned in the results may be different from \a + coordinate. This will usually occur if the reverse geocoding service + backend shifts the coordinates to be closer to the matching addresses, or + if the backend returns results at multiple levels of detail. + + If multiple results are returned by the reverse geocoding service backend + they will be provided in order of specificity. This normally occurs if the + backend is configured to reverse geocode across multiple levels of detail. + As an example, some services will return address and coordinate pairs for + the street address, the city, the state and the country. + + If \a bounds is non-null and a valid QGeoShape it will be used to + limit the results to those that are contained by \a bounds. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoCodingManagerEngine::finished(), + QGeoCodingManagerEngine::error(), QGeoCodeReply::finished() or + QGeoCodeReply::error() with deleteLater(). +*/ +QGeoCodeReply *QGeoCodingManagerEngine::reverseGeocode(const QGeoCoordinate &coordinate, + const QGeoShape &bounds) +{ + Q_UNUSED(coordinate) + Q_UNUSED(bounds) + return new QGeoCodeReply(QGeoCodeReply::UnsupportedOptionError, + QLatin1String("Reverse geocoding is not supported by this service provider."), this); +} + +/*! + Begins geocoding for a location matching \a address. + + A QGeoCodeReply object will be returned, which can be used to manage the + geocoding operation and to return the results of the operation. + + This engine and the returned QGeoCodeReply object will emit signals + indicating if the operation completes or if errors occur. + + Once the operation has completed, QGeoCodeReply::locations() can be used to + retrieve the results, which will consist of a list of QGeoLocation objects. + These objects represent a combination of coordinate and address data. + + If \a limit is -1 the entire result set will be returned, otherwise at most + \a limit results will be returned. + + The \a offset parameter is used to ask the geocoding service to not return the + first \a offset results. + + The \a limit and \a offset results are used together to implement paging. + + If \a bounds is non-null and a valid QGeoShape it will be used to + limit the results to those that are contained by \a bounds. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoCodingManagerEngine::finished(), + QGeoCodingManagerEngine::error(), QGeoCodeReply::finished() or + QGeoCodeReply::error() with deleteLater(). +*/ +QGeoCodeReply *QGeoCodingManagerEngine::geocode(const QString &address, + int limit, + int offset, + const QGeoShape &bounds) +{ + Q_UNUSED(address) + Q_UNUSED(limit) + Q_UNUSED(offset) + Q_UNUSED(bounds) + + return new QGeoCodeReply(QGeoCodeReply::UnsupportedOptionError, + QLatin1String("Searching is not supported by this service provider."), this); +} + +/*! + Sets the locale to be used by this manager to \a locale. + + If this geocoding manager supports returning the results + in different languages, they will be returned in the language of \a locale. + + The locale used defaults to the system locale if this is not set. +*/ +void QGeoCodingManagerEngine::setLocale(const QLocale &locale) +{ + d_ptr->locale = locale; +} + +/*! + Returns the locale used to hint to this geocoding manager about what + language to use for the results. +*/ +QLocale QGeoCodingManagerEngine::locale() const +{ + return d_ptr->locale; +} + +/*! +\fn void QGeoCodingManagerEngine::finished(QGeoCodeReply *reply) + + This signal is emitted when \a reply has finished processing. + + If reply::error() equals QGeoCodeReply::NoError then the processing + finished successfully. + + This signal and QGeoCodeReply::finished() will be emitted at the same + time. + + \note Do not delete the \a reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ + +/*! +\fn void QGeoCodingManagerEngine::error(QGeoCodeReply *reply, QGeoCodeReply::Error error, QString errorString) + + This signal is emitted when an error has been detected in the processing of + \a reply. The QGeoCodingManagerEngine::finished() signal will probably follow. + + The error will be described by the error code \a error. If \a errorString is + not empty it will contain a textual description of the error. + + This signal and QGeoCodeReply::error() will be emitted at the same time. + + \note Do not delete the \a reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ + +/******************************************************************************* +*******************************************************************************/ + +QGeoCodingManagerEnginePrivate::QGeoCodingManagerEnginePrivate() + : managerVersion(-1) +{} + +QGeoCodingManagerEnginePrivate::~QGeoCodingManagerEnginePrivate() +{ +} + +#include "moc_qgeocodingmanagerengine.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeocodingmanagerengine.h b/src/location/maps/qgeocodingmanagerengine.h new file mode 100644 index 0000000..ce7021a --- /dev/null +++ b/src/location/maps/qgeocodingmanagerengine.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODINGMANAGERENGINE_H +#define QGEOCODINGMANAGERENGINE_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoAddress; +class QGeoShape; +class QGeoCodingManagerEnginePrivate; + +class Q_LOCATION_EXPORT QGeoCodingManagerEngine : public QObject +{ + Q_OBJECT +public: + explicit QGeoCodingManagerEngine(const QVariantMap ¶meters, QObject *parent = Q_NULLPTR); + virtual ~QGeoCodingManagerEngine(); + + QString managerName() const; + int managerVersion() const; + + virtual QGeoCodeReply *geocode(const QGeoAddress &address, const QGeoShape &bounds); + virtual QGeoCodeReply *geocode(const QString &address, + int limit, + int offset, + const QGeoShape &bounds); + virtual QGeoCodeReply *reverseGeocode(const QGeoCoordinate &coordinate, + const QGeoShape &bounds); + + + void setLocale(const QLocale &locale); + QLocale locale() const; + +Q_SIGNALS: + void finished(QGeoCodeReply *reply); + void error(QGeoCodeReply *reply, QGeoCodeReply::Error error, QString errorString = QString()); + +private: + void setManagerName(const QString &managerName); + void setManagerVersion(int managerVersion); + + QGeoCodingManagerEnginePrivate *d_ptr; + Q_DISABLE_COPY(QGeoCodingManagerEngine) + + friend class QGeoServiceProvider; + friend class QGeoServiceProviderPrivate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeocodingmanagerengine_p.h b/src/location/maps/qgeocodingmanagerengine_p.h new file mode 100644 index 0000000..b6fcb68 --- /dev/null +++ b/src/location/maps/qgeocodingmanagerengine_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODINGMANAGERENGINE_P_H +#define QGEOCODINGMANAGERENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeocodingmanagerengine.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCodingManagerEnginePrivate +{ +public: + QGeoCodingManagerEnginePrivate(); + ~QGeoCodingManagerEnginePrivate(); + + QString managerName; + int managerVersion; + + QLocale locale; + +private: + Q_DISABLE_COPY(QGeoCodingManagerEnginePrivate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeofiletilecache.cpp b/src/location/maps/qgeofiletilecache.cpp new file mode 100644 index 0000000..3d381dc --- /dev/null +++ b/src/location/maps/qgeofiletilecache.cpp @@ -0,0 +1,463 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeofiletilecache_p.h" + +#include "qgeotilespec_p.h" + +#include "qgeomappingmanager_p.h" + +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QSet) + +QT_BEGIN_NAMESPACE + +class QGeoCachedTileMemory +{ +public: + ~QGeoCachedTileMemory() + { + if (cache) + cache->evictFromMemoryCache(this); + } + + QGeoTileSpec spec; + QGeoFileTileCache *cache; + QByteArray bytes; + QString format; +}; + +void QCache3QTileEvictionPolicy::aboutToBeRemoved(const QGeoTileSpec &key, QSharedPointer obj) +{ + Q_UNUSED(key); + // set the cache pointer to zero so we can't call evictFromDiskCache + obj->cache = 0; +} + +void QCache3QTileEvictionPolicy::aboutToBeEvicted(const QGeoTileSpec &key, QSharedPointer obj) +{ + Q_UNUSED(key); + Q_UNUSED(obj); + // leave the pointer set if it's a real eviction +} + +QGeoCachedTileDisk::~QGeoCachedTileDisk() +{ + if (cache) + cache->evictFromDiskCache(this); +} + +QGeoFileTileCache::QGeoFileTileCache(const QString &directory, QObject *parent) + : QAbstractGeoTileCache(parent), directory_(directory), + minTextureUsage_(0), extraTextureUsage_(0) +{ + const QString basePath = baseCacheDirectory(); + + // delete old tiles from QtLocation 5.4 or prior + // Newer version use plugin-specific subdirectories so those are not affected. + // TODO Remove cache cleanup in Qt 6 + QDir baseDir(basePath); + if (baseDir.exists()) { + const QStringList oldCacheFiles = baseDir.entryList(QDir::Files); + foreach (const QString& file, oldCacheFiles) + baseDir.remove(file); + } + + if (directory_.isEmpty()) { + directory_ = basePath; + qWarning() << "Plugin uses uninitialized QGeoFileTileCache directory which was deleted during startup"; + } + + QDir::root().mkpath(directory_); + + // default values + setMaxDiskUsage(20 * 1024 * 1024); + setMaxMemoryUsage(3 * 1024 * 1024); + setExtraTextureUsage(6 * 1024 * 1024); + + loadTiles(); +} + +void QGeoFileTileCache::loadTiles() +{ + QStringList formats; + formats << QLatin1String("*.*"); + + QDir dir(directory_); + QStringList files = dir.entryList(formats, QDir::Files); + + // Method: + // 1. read each queue file then, if each file exists, deserialize the data into the appropriate + // cache queue. + for (int i = 1; i<=4; i++) { + QString filename = dir.filePath(QString::fromLatin1("queue") + QString::number(i)); + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)) + continue; + QList > queue; + QList specs; + QList costs; + while (!file.atEnd()) { + QByteArray line = file.readLine().trimmed(); + QString filename = QString::fromLatin1(line.constData(), line.length()); + if (dir.exists(filename)){ + files.removeOne(filename); + QGeoTileSpec spec = filenameToTileSpec(filename); + if (spec.zoom() == -1) + continue; + QSharedPointer tileDisk(new QGeoCachedTileDisk); + tileDisk->filename = dir.filePath(filename); + tileDisk->cache = this; + tileDisk->spec = spec; + QFileInfo fi(tileDisk->filename); + specs.append(spec); + queue.append(tileDisk); + costs.append(fi.size()); + } + } + + diskCache_.deserializeQueue(i, specs, queue, costs); + file.close(); + } + + // 2. remaining tiles that aren't registered in a queue get pushed into cache here + // this is a backup, in case the queue manifest files get deleted or out of sync due to + // the application not closing down properly + for (int i = 0; i < files.size(); ++i) { + QGeoTileSpec spec = filenameToTileSpec(files.at(i)); + if (spec.zoom() == -1) + continue; + QString filename = dir.filePath(files.at(i)); + addToDiskCache(spec, filename); + } +} + +QGeoFileTileCache::~QGeoFileTileCache() +{ + // write disk cache queues to disk + QDir dir(directory_); + for (int i = 1; i<=4; i++) { + QString filename = dir.filePath(QString::fromLatin1("queue") + QString::number(i)); + QFile file(filename); + if (!file.open(QIODevice::WriteOnly)){ + qWarning() << "Unable to write tile cache file " << filename; + continue; + } + QList > queue; + diskCache_.serializeQueue(i, queue); + foreach (const QSharedPointer &tile, queue) { + if (tile.isNull()) + continue; + + // we just want the filename here, not the full path + int index = tile->filename.lastIndexOf(QLatin1Char('/')); + QByteArray filename = tile->filename.mid(index + 1).toLatin1() + '\n'; + file.write(filename); + } + file.close(); + } +} + +void QGeoFileTileCache::printStats() +{ + textureCache_.printStats(); + memoryCache_.printStats(); + diskCache_.printStats(); +} + +void QGeoFileTileCache::setMaxDiskUsage(int diskUsage) +{ + diskCache_.setMaxCost(diskUsage); +} + +int QGeoFileTileCache::maxDiskUsage() const +{ + return diskCache_.maxCost(); +} + +int QGeoFileTileCache::diskUsage() const +{ + return diskCache_.totalCost(); +} + +void QGeoFileTileCache::setMaxMemoryUsage(int memoryUsage) +{ + memoryCache_.setMaxCost(memoryUsage); +} + +int QGeoFileTileCache::maxMemoryUsage() const +{ + return memoryCache_.maxCost(); +} + +int QGeoFileTileCache::memoryUsage() const +{ + return memoryCache_.totalCost(); +} + +void QGeoFileTileCache::setExtraTextureUsage(int textureUsage) +{ + extraTextureUsage_ = textureUsage; + textureCache_.setMaxCost(minTextureUsage_ + extraTextureUsage_); +} + +void QGeoFileTileCache::setMinTextureUsage(int textureUsage) +{ + minTextureUsage_ = textureUsage; + textureCache_.setMaxCost(minTextureUsage_ + extraTextureUsage_); +} + +int QGeoFileTileCache::maxTextureUsage() const +{ + return textureCache_.maxCost(); +} + +int QGeoFileTileCache::minTextureUsage() const +{ + return minTextureUsage_; +} + + +int QGeoFileTileCache::textureUsage() const +{ + return textureCache_.totalCost(); +} + +void QGeoFileTileCache::clearAll() +{ + textureCache_.clear(); + memoryCache_.clear(); + diskCache_.clear(); + QDir dir(directory_); + dir.setNameFilters(QStringList() << QLatin1String("*-*-*-*.*")); + dir.setFilter(QDir::Files); + foreach (QString dirFile, dir.entryList()) { + dir.remove(dirFile); + } +} + +QSharedPointer QGeoFileTileCache::get(const QGeoTileSpec &spec) +{ + QSharedPointer tt = textureCache_.object(spec); + if (tt) + return tt; + + QSharedPointer tm = memoryCache_.object(spec); + if (tm) { + QImage image; + if (!image.loadFromData(tm->bytes)) { + handleError(spec, QLatin1String("Problem with tile image")); + return QSharedPointer(0); + } + QSharedPointer tt = addToTextureCache(spec, image); + if (tt) + return tt; + } + + QSharedPointer td = diskCache_.object(spec); + if (td) { + const QString format = QFileInfo(td->filename).suffix(); + QFile file(td->filename); + file.open(QIODevice::ReadOnly); + QByteArray bytes = file.readAll(); + file.close(); + + QImage image; + if (!image.loadFromData(bytes)) { + handleError(spec, QLatin1String("Problem with tile image")); + return QSharedPointer(0); + } + + addToMemoryCache(spec, bytes, format); + QSharedPointer tt = addToTextureCache(td->spec, image); + if (tt) + return tt; + } + + return QSharedPointer(); +} + +void QGeoFileTileCache::insert(const QGeoTileSpec &spec, + const QByteArray &bytes, + const QString &format, + QGeoTiledMappingManagerEngine::CacheAreas areas) +{ + if (bytes.isEmpty()) + return; + + if (areas & QGeoTiledMappingManagerEngine::DiskCache) { + QString filename = tileSpecToFilename(spec, format, directory_); + QFile file(filename); + file.open(QIODevice::WriteOnly); + file.write(bytes); + file.close(); + + addToDiskCache(spec, filename); + } + + if (areas & QGeoTiledMappingManagerEngine::MemoryCache) { + addToMemoryCache(spec, bytes, format); + } + + /* inserts do not hit the texture cache -- this actually reduces overall + * cache hit rates because many tiles come too late to be useful + * and act as a poison */ +} + +void QGeoFileTileCache::evictFromDiskCache(QGeoCachedTileDisk *td) +{ + QFile::remove(td->filename); +} + +void QGeoFileTileCache::evictFromMemoryCache(QGeoCachedTileMemory * /* tm */) +{ +} + +QSharedPointer QGeoFileTileCache::addToDiskCache(const QGeoTileSpec &spec, const QString &filename) +{ + QSharedPointer td(new QGeoCachedTileDisk); + td->spec = spec; + td->filename = filename; + td->cache = this; + + QFileInfo fi(filename); + int diskCost = fi.size(); + diskCache_.insert(spec, td, diskCost); + return td; +} + +QSharedPointer QGeoFileTileCache::addToMemoryCache(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format) +{ + QSharedPointer tm(new QGeoCachedTileMemory); + tm->spec = spec; + tm->cache = this; + tm->bytes = bytes; + tm->format = format; + + int cost = bytes.size(); + memoryCache_.insert(spec, tm, cost); + + return tm; +} + +QSharedPointer QGeoFileTileCache::addToTextureCache(const QGeoTileSpec &spec, const QImage &image) +{ + QSharedPointer tt(new QGeoTileTexture); + tt->spec = spec; + tt->image = image; + + int textureCost = image.width() * image.height() * image.depth() / 8; + textureCache_.insert(spec, tt, textureCost); + + return tt; +} + +QString QGeoFileTileCache::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) +{ + QString filename = spec.plugin(); + filename += QLatin1String("-"); + filename += QString::number(spec.mapId()); + filename += QLatin1String("-"); + filename += QString::number(spec.zoom()); + filename += QLatin1String("-"); + filename += QString::number(spec.x()); + filename += QLatin1String("-"); + filename += QString::number(spec.y()); + + //Append version if real version number to ensure backwards compatibility and eviction of old tiles + if (spec.version() != -1) { + filename += QLatin1String("-"); + filename += QString::number(spec.version()); + } + + filename += QLatin1String("."); + filename += format; + + QDir dir = QDir(directory); + + return dir.filePath(filename); +} + +QGeoTileSpec QGeoFileTileCache::filenameToTileSpec(const QString &filename) +{ + QGeoTileSpec emptySpec; + + QStringList parts = filename.split('.'); + + if (parts.length() != 2) + return emptySpec; + + QString name = parts.at(0); + QStringList fields = name.split('-'); + + int length = fields.length(); + if (length != 5 && length != 6) + return emptySpec; + + QList numbers; + + bool ok = false; + for (int i = 1; i < length; ++i) { + ok = false; + int value = fields.at(i).toInt(&ok); + if (!ok) + return emptySpec; + numbers.append(value); + } + + //File name without version, append default + if (numbers.length() < 5) + numbers.append(-1); + + return QGeoTileSpec(fields.at(0), + numbers.at(0), + numbers.at(1), + numbers.at(2), + numbers.at(3), + numbers.at(4)); +} + +QString QGeoFileTileCache::directory() const +{ + return directory_; +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeofiletilecache_p.h b/src/location/maps/qgeofiletilecache_p.h new file mode 100644 index 0000000..bd3e684 --- /dev/null +++ b/src/location/maps/qgeofiletilecache_p.h @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOFILETILECACHE_P_H +#define QGEOFILETILECACHE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include +#include +#include "qcache3q_p.h" +#include +#include +#include + +#include "qgeotilespec_p.h" +#include "qgeotiledmappingmanagerengine_p.h" +#include "qabstractgeotilecache_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoMappingManager; + +class QGeoTile; +class QGeoCachedTileMemory; +class QGeoFileTileCache; + +class QPixmap; +class QThread; + +/* This would be internal to qgeofiletilecache.cpp except that the eviction + * policy can't be defined without it being concrete here */ +class QGeoCachedTileDisk +{ +public: + ~QGeoCachedTileDisk(); + + QGeoTileSpec spec; + QString filename; + QString format; + QGeoFileTileCache *cache; +}; + +/* Custom eviction policy for the disk cache, to avoid deleting all the files + * when the application closes */ +class QCache3QTileEvictionPolicy : public QCache3QDefaultEvictionPolicy +{ +protected: + void aboutToBeRemoved(const QGeoTileSpec &key, QSharedPointer obj); + void aboutToBeEvicted(const QGeoTileSpec &key, QSharedPointer obj); +}; + +class Q_LOCATION_EXPORT QGeoFileTileCache : public QAbstractGeoTileCache +{ + Q_OBJECT +public: + QGeoFileTileCache(const QString &directory = QString(), QObject *parent = 0); + ~QGeoFileTileCache(); + + void setMaxDiskUsage(int diskUsage) Q_DECL_OVERRIDE; + int maxDiskUsage() const Q_DECL_OVERRIDE; + int diskUsage() const Q_DECL_OVERRIDE; + + void setMaxMemoryUsage(int memoryUsage) Q_DECL_OVERRIDE; + int maxMemoryUsage() const Q_DECL_OVERRIDE; + int memoryUsage() const Q_DECL_OVERRIDE; + + void setMinTextureUsage(int textureUsage) Q_DECL_OVERRIDE; + void setExtraTextureUsage(int textureUsage) Q_DECL_OVERRIDE; + int maxTextureUsage() const Q_DECL_OVERRIDE; + int minTextureUsage() const Q_DECL_OVERRIDE; + int textureUsage() const Q_DECL_OVERRIDE; + void clearAll() Q_DECL_OVERRIDE; + + QSharedPointer get(const QGeoTileSpec &spec) Q_DECL_OVERRIDE; + + // can be called without a specific tileCache pointer + static void evictFromDiskCache(QGeoCachedTileDisk *td); + static void evictFromMemoryCache(QGeoCachedTileMemory *tm); + + void insert(const QGeoTileSpec &spec, + const QByteArray &bytes, + const QString &format, + QGeoTiledMappingManagerEngine::CacheAreas areas = QGeoTiledMappingManagerEngine::AllCaches) Q_DECL_OVERRIDE; + +private: + void printStats() Q_DECL_OVERRIDE; + void loadTiles(); + + QString directory() const; + + QSharedPointer addToDiskCache(const QGeoTileSpec &spec, const QString &filename); + QSharedPointer addToMemoryCache(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format); + QSharedPointer addToTextureCache(const QGeoTileSpec &spec, const QImage &image); + + static QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory); + static QGeoTileSpec filenameToTileSpec(const QString &filename); + + QCache3Q diskCache_; + QCache3Q memoryCache_; + QCache3Q textureCache_; + + QString directory_; + + int minTextureUsage_; + int extraTextureUsage_; +}; + +QT_END_NAMESPACE + +#endif // QGEOFILETILECACHE_P_H diff --git a/src/location/maps/qgeomaneuver.cpp b/src/location/maps/qgeomaneuver.cpp new file mode 100644 index 0000000..f38cb29 --- /dev/null +++ b/src/location/maps/qgeomaneuver.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomaneuver.h" +#include "qgeomaneuver_p.h" + +#include "qgeocoordinate.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoManeuver + \inmodule QtLocation + \ingroup QtLocation-routing + \since 5.6 + + \brief The QGeoManeuver class represents the information relevant to the + point at which two QGeoRouteSegments meet. + + QGeoRouteSegment instances can be thought of as edges on a routing + graph, with QGeoManeuver instances as optional labels attached to the + vertices of the graph. + + The most interesting information help in a QGeoManeuver instance is + normally the textual navigation to provide and the position at which to + provide it, accessible by instructionText() and position() respectively. + + It is also possible to determine if a routing waypoint has been passed by + checking if waypoint() returns a valid QGeoCoordinate. +*/ + +/*! +\enum QGeoManeuver::InstructionDirection + +Describes the change in direction associated with the instruction text +that is associated with a QGeoManaeuver. + +\value NoDirection +There is no direction associated with the instruction text. + +\value DirectionForward +The instruction indicates that the direction of travel does not need to change. + +\value DirectionBearRight +The instruction indicates that the direction of travel should bear to the right. + +\value DirectionLightRight +The instruction indicates that a light turn to the right is required. + +\value DirectionRight +The instruction indicates that a turn to the right is required. + +\value DirectionHardRight +The instruction indicates that a hard turn to the right is required. + +\value DirectionUTurnRight +The instruction indicates that a u-turn to the right is required. + +\value DirectionUTurnLeft +The instruction indicates that a u-turn to the left is required. + +\value DirectionHardLeft +The instruction indicates that a hard turn to the left is required. + +\value DirectionLeft +The instruction indicates that a turn to the left is required. + +\value DirectionLightLeft +The instruction indicates that a light turn to the left is required. + +\value DirectionBearLeft +The instruction indicates that the direction of travel should bear to the left. + +*/ + +/*! + Constructs a invalid maneuver object. + + The maneuver will remain invalid until one of + setPosition(), setInstructionText(), setDirection(), + setTimeToNextInstruction(), setDistanceToNextInstruction() or + setWaypoint() is called. +*/ +QGeoManeuver::QGeoManeuver() + : d_ptr(new QGeoManeuverPrivate()) {} + +/*! + Constructs a maneuver object from the contents of \a other. +*/ +QGeoManeuver::QGeoManeuver(const QGeoManeuver &other) + : d_ptr(other.d_ptr) {} + +/*! + Destroys this maneuver object. +*/ +QGeoManeuver::~QGeoManeuver() {} + +/*! + Assigns \a other to this maneuver object and then returns + a reference to this maneuver object. +*/ +QGeoManeuver &QGeoManeuver::operator= (const QGeoManeuver & other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns whether this maneuver is equal to \a other. +*/ +bool QGeoManeuver::operator== (const QGeoManeuver &other) const +{ + return (*(d_ptr.constData()) == *(other.d_ptr.constData())); +} + +/*! + Returns whether this maneuver is not equal to \a other. +*/ +bool QGeoManeuver::operator!= (const QGeoManeuver &other) const +{ + return !(operator==(other)); +} + +/*! + Returns whether this maneuver is valid or not. + + Invalid maneuvers are used when there is no information + that needs to be attached to the endpoint of a QGeoRouteSegment instance. +*/ +bool QGeoManeuver::isValid() const +{ + return d_ptr->valid; +} + +/*! + Sets the position where instructionText() should be displayed to \a + position. +*/ +void QGeoManeuver::setPosition(const QGeoCoordinate &position) +{ + d_ptr->valid = true; + d_ptr->position = position; +} + +/*! + Returns the position where instructionText() should be displayed. +*/ +QGeoCoordinate QGeoManeuver::position() const +{ + return d_ptr->position; +} + +/*! + Sets the textual navigation instructions to \a instructionText. +*/ +void QGeoManeuver::setInstructionText(const QString &instructionText) +{ + d_ptr->valid = true; + d_ptr->text = instructionText; +} + +/*! + Returns the textual navigation instructions. +*/ +QString QGeoManeuver::instructionText() const +{ + return d_ptr->text; +} + +/*! + Sets the direction associated with the associated instruction to \a + direction. +*/ +void QGeoManeuver::setDirection(QGeoManeuver::InstructionDirection direction) +{ + d_ptr->valid = true; + d_ptr->direction = direction; +} + +/*! + Returns the direction associated with the associated instruction. +*/ +QGeoManeuver::InstructionDirection QGeoManeuver::direction() const +{ + return d_ptr->direction; +} + +/*! + Sets the estimated time it will take to travel from the point at which the + associated instruction was issued and the point that the next instruction + should be issued, in seconds, to \a secs. +*/ +void QGeoManeuver::setTimeToNextInstruction(int secs) +{ + d_ptr->valid = true; + d_ptr->timeToNextInstruction = secs; +} + +/*! + Returns the estimated time it will take to travel from the point at which + the associated instruction was issued and the point that the next + instruction should be issued, in seconds. +*/ +int QGeoManeuver::timeToNextInstruction() const +{ + return d_ptr->timeToNextInstruction; +} + +/*! + Sets the distance, in meters, between the point at which the associated + instruction was issued and the point that the next instruction should be + issued to \a distance. +*/ +void QGeoManeuver::setDistanceToNextInstruction(qreal distance) +{ + d_ptr->valid = true; + d_ptr->distanceToNextInstruction = distance; +} + +/*! + Returns the distance, in meters, between the point at which the associated + instruction was issued and the point that the next instruction should be + issued. +*/ +qreal QGeoManeuver::distanceToNextInstruction() const +{ + return d_ptr->distanceToNextInstruction; +} + +/*! + Sets the waypoint associated with this maneuver to \a coordinate. +*/ +void QGeoManeuver::setWaypoint(const QGeoCoordinate &coordinate) +{ + d_ptr->valid = true; + d_ptr->waypoint = coordinate; +} + +/*! + Returns the waypoint associated with this maneuver. + + If there is not waypoint associated with this maneuver an invalid + QGeoCoordinate will be returned. +*/ +QGeoCoordinate QGeoManeuver::waypoint() const +{ + return d_ptr->waypoint; +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoManeuverPrivate::QGeoManeuverPrivate() + : valid(false), + direction(QGeoManeuver::NoDirection), + timeToNextInstruction(0), + distanceToNextInstruction(0.0) {} + +QGeoManeuverPrivate::QGeoManeuverPrivate(const QGeoManeuverPrivate &other) + : QSharedData(other), + valid(other.valid), + position(other.position), + text(other.text), + direction(other.direction), + timeToNextInstruction(other.timeToNextInstruction), + distanceToNextInstruction(other.distanceToNextInstruction), + waypoint(other.waypoint) {} + +QGeoManeuverPrivate::~QGeoManeuverPrivate() {} + +bool QGeoManeuverPrivate::operator ==(const QGeoManeuverPrivate &other) const +{ + return ((valid == other.valid) + && (position == other.position) + && (text == other.text) + && (direction == other.direction) + && (timeToNextInstruction == other.timeToNextInstruction) + && (distanceToNextInstruction == other.distanceToNextInstruction) + && (waypoint == other.waypoint)); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeomaneuver.h b/src/location/maps/qgeomaneuver.h new file mode 100644 index 0000000..9710f8f --- /dev/null +++ b/src/location/maps/qgeomaneuver.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMANEUVER_H +#define QGEOMANEUVER_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QString; + +class QGeoCoordinate; +class QGeoManeuverPrivate; + +class Q_LOCATION_EXPORT QGeoManeuver +{ + +public: + enum InstructionDirection { + NoDirection, + DirectionForward, + DirectionBearRight, + DirectionLightRight, + DirectionRight, + DirectionHardRight, + DirectionUTurnRight, + DirectionUTurnLeft, + DirectionHardLeft, + DirectionLeft, + DirectionLightLeft, + DirectionBearLeft + }; + + QGeoManeuver(); + QGeoManeuver(const QGeoManeuver &other); + ~QGeoManeuver(); + + QGeoManeuver &operator= (const QGeoManeuver &other); + + bool operator== (const QGeoManeuver &other) const; + bool operator!= (const QGeoManeuver &other) const; + + bool isValid() const; + + void setPosition(const QGeoCoordinate &position); + QGeoCoordinate position() const; + + void setInstructionText(const QString &instructionText); + QString instructionText() const; + + void setDirection(InstructionDirection direction); + InstructionDirection direction() const; + + void setTimeToNextInstruction(int secs); + int timeToNextInstruction() const; + + void setDistanceToNextInstruction(qreal distance); + qreal distanceToNextInstruction() const; + + void setWaypoint(const QGeoCoordinate &coordinate); + QGeoCoordinate waypoint() const; + +private: + QSharedDataPointer d_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeomaneuver_p.h b/src/location/maps/qgeomaneuver_p.h new file mode 100644 index 0000000..c048f13 --- /dev/null +++ b/src/location/maps/qgeomaneuver_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMANEUVER_P_H +#define QGEOMANEUVER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeomaneuver.h" +#include "qgeocoordinate.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoManeuverPrivate : public QSharedData +{ +public: + QGeoManeuverPrivate(); + QGeoManeuverPrivate(const QGeoManeuverPrivate &other); + ~QGeoManeuverPrivate(); + + bool operator== (const QGeoManeuverPrivate &other) const; + + bool valid; + QString id; + QGeoCoordinate position; + QString text; + QGeoManeuver::InstructionDirection direction; + int timeToNextInstruction; + qreal distanceToNextInstruction; + QGeoCoordinate waypoint; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp new file mode 100644 index 0000000..c3b01a3 --- /dev/null +++ b/src/location/maps/qgeomap.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomap_p.h" +#include "qgeomap_p_p.h" +#include "qgeocameracapabilities_p.h" +#include "qgeomappingmanagerengine_p.h" +#include + +QT_BEGIN_NAMESPACE + +QGeoMap::QGeoMap(QGeoMapPrivate &dd, QObject *parent) + : QObject(dd,parent) +{ +} + +QGeoMap::~QGeoMap() +{ +} + +void QGeoMap::setSize(const QSize& size) +{ + Q_D(QGeoMap); + if (size == d->m_size) + return; + d->m_size = size; + d->changeMapSize(size); +} + +QSize QGeoMap::size() const +{ + Q_D(const QGeoMap); + return d->m_size; +} + +int QGeoMap::width() const +{ + Q_D(const QGeoMap); + return d->m_size.width(); +} + +int QGeoMap::height() const +{ + Q_D(const QGeoMap); + return d->m_size.height(); +} + +void QGeoMap::setCameraData(const QGeoCameraData &cameraData) +{ + Q_D(QGeoMap); + if (cameraData == d->m_cameraData) + return; + d->m_cameraData = cameraData; + d->changeCameraData(cameraData); + emit cameraDataChanged(d->m_cameraData); +} + +QGeoCameraData QGeoMap::cameraData() const +{ + Q_D(const QGeoMap); + return d->m_cameraData; +} + +void QGeoMap::setActiveMapType(const QGeoMapType type) +{ + Q_D(QGeoMap); + if (type == d->m_activeMapType) + return; + d->m_activeMapType = type; + d->changeActiveMapType(type); + emit activeMapTypeChanged(); +} + +const QGeoMapType QGeoMap::activeMapType() const +{ + Q_D(const QGeoMap); + return d->m_activeMapType; +} + + +QGeoCameraCapabilities QGeoMap::cameraCapabilities() const +{ + Q_D(const QGeoMap); + if (!d->m_engine.isNull()) + return d->m_engine->cameraCapabilities(); + else + return QGeoCameraCapabilities(); +} + +void QGeoMap::prefetchData() +{ + +} + +void QGeoMap::clearData() +{ + +} + +QGeoMapPrivate::QGeoMapPrivate(QGeoMappingManagerEngine *engine) + : QObjectPrivate(), + m_engine(engine), + m_activeMapType(QGeoMapType()) +{ +} + +QGeoMapPrivate::~QGeoMapPrivate() +{ +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h new file mode 100644 index 0000000..021c440 --- /dev/null +++ b/src/location/maps/qgeomap_p.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOMAP_P_H +#define QGEOMAP_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeocameradata_p.h" +#include "qgeomaptype_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMappingManagerEngine; +class QGeoMapPrivate; +class QGeoMapController; +class QGeoCameraCapabilities; +class QGeoCoordinate; +class QSGNode; +class QQuickWindow; + +class Q_LOCATION_EXPORT QGeoMap : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGeoMap) + +public: + virtual ~QGeoMap(); + + void setSize(const QSize& size); + QSize size() const; + int width() const; + int height() const; + + + QGeoCameraData cameraData() const; + QGeoCameraCapabilities cameraCapabilities() const; + + void setActiveMapType(const QGeoMapType mapType); + const QGeoMapType activeMapType() const; + + virtual QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const = 0; + virtual QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const = 0; + + virtual double minimumZoomForMapSize(int width, int height) const = 0; + virtual double maximumLatitudeForZoom(double zoomLevel) const = 0; + + virtual QDoubleVector2D referenceCoordinateToItemPosition(const QGeoCoordinate &coordinate) const = 0; + virtual QGeoCoordinate referenceItemPositionToCoordinate(const QDoubleVector2D &pos) const = 0; + + virtual void prefetchData(); + virtual void clearData(); + +protected: + QGeoMap(QGeoMapPrivate &dd, QObject *parent = 0); + void setCameraData(const QGeoCameraData &cameraData); + virtual QSGNode *updateSceneGraph(QSGNode *node, QQuickWindow *window) = 0; + +Q_SIGNALS: + void cameraDataChanged(const QGeoCameraData &cameraData); + void sgNodeChanged(); + void activeMapTypeChanged(); + void copyrightsChanged(const QImage ©rightsImage); + void copyrightsChanged(const QString ©rightsHtml); + +private: + Q_DISABLE_COPY(QGeoMap) + friend class QGeoMapController; //setCameraData + friend class QDeclarativeGeoMap; //updateSceneGraph +}; + +QT_END_NAMESPACE + +#endif // QGEOMAP_P_H diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h new file mode 100644 index 0000000..f09d55c --- /dev/null +++ b/src/location/maps/qgeomap_p_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOMAP_P_P_H +#define QGEOMAP_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeocameradata_p.h" +#include "qgeomaptype_p.h" +#include +#include + + +QT_BEGIN_NAMESPACE + +class QGeoMappingManagerEngine; +class QGeoMap; +class QGeoMapController; + +class QGeoMapPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGeoMap) +public: + QGeoMapPrivate(QGeoMappingManagerEngine *engine); + virtual ~QGeoMapPrivate(); + +protected: + virtual void changeMapSize(const QSize &size) = 0; + virtual void changeCameraData(const QGeoCameraData &oldCameraData) = 0; + virtual void changeActiveMapType(const QGeoMapType mapType) = 0; + +protected: + QSize m_size; + QPointer m_engine; + QGeoMapController *m_controller; + QGeoCameraData m_cameraData; + QGeoMapType m_activeMapType; +}; + +QT_END_NAMESPACE + +#endif // QGEOMAP_P_P_H diff --git a/src/location/maps/qgeomappingmanager.cpp b/src/location/maps/qgeomappingmanager.cpp new file mode 100644 index 0000000..12e61c7 --- /dev/null +++ b/src/location/maps/qgeomappingmanager.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomappingmanager_p.h" +#include "qgeomappingmanager_p_p.h" +#include "qgeomappingmanagerengine_p.h" +#include "qgeotiledmapreply_p.h" +#include "qgeocameracapabilities_p.h" + + +#include "qgeomap_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoMappingManager + \inmodule QtLocation + \ingroup QtLocation-maps + \since 5.6 + \internal + + \brief The QGeoMappingManager class provides support for displaying + and interacting with maps. +*/ + +/*! + Constructs a new manager with the specified \a parent and with the + implementation provided by \a engine. + + This constructor is used internally by QGeoServiceProviderFactory. Regular + users should acquire instances of QGeoMappingManager with + QGeoServiceProvider::mappingManager() +*/ +QGeoMappingManager::QGeoMappingManager(QGeoMappingManagerEngine *engine, QObject *parent) + : QObject(parent), + d_ptr(new QGeoMappingManagerPrivate) +{ + d_ptr->engine = engine; + if (!d_ptr->engine) { + qFatal("The mapping manager engine that was set for this mapping manager was NULL."); + } + + connect(d_ptr->engine, + SIGNAL(initialized()), + this, + SIGNAL(initialized()), + Qt::QueuedConnection); + + connect(d_ptr->engine, + SIGNAL(supportedMapTypesChanged()), + this, + SIGNAL(supportedMapTypesChanged()), + Qt::QueuedConnection); +} + +/*! + Destroys this mapping manager. +*/ +QGeoMappingManager::~QGeoMappingManager() +{ + delete d_ptr; +} + +/*! + \fn void QGeoMappingManager::initialized() + + This signal is emitted when the mapping manager has been initialized + and is ready to be used. +*/ + +/*! + Returns the name of the engine which implements the behaviour of this + mapping manager. + + The combination of managerName() and managerVersion() should be unique + amongst the plugin implementations. +*/ +QString QGeoMappingManager::managerName() const +{ + return d_ptr->engine->managerName(); +} + +/*! + Returns the version of the engine which implements the behaviour of this + mapping manager. + + The combination of managerName() and managerVersion() should be unique + amongst the plugin implementations. +*/ +int QGeoMappingManager::managerVersion() const +{ + return d_ptr->engine->managerVersion(); +} + +QGeoCameraCapabilities QGeoMappingManager::cameraCapabilities() const +{ + return d_ptr->engine->cameraCapabilities(); +} + +/*! + Returns a new QGeoMap instance which will be managed by this manager. +*/ +QGeoMap *QGeoMappingManager::createMap(QObject *parent) +{ + QGeoMap * map = d_ptr->engine->createMap(); + if (map) + connect(parent, &QObject::destroyed,map, &QGeoMap::deleteLater); + return map; +} + +QList QGeoMappingManager::supportedMapTypes() const +{ + return d_ptr->engine->supportedMapTypes(); +} + +/*! + Return whether the manager has been initialized + (will be done automatically but may take some time). + +*/ +bool QGeoMappingManager::isInitialized() const +{ + return d_ptr->engine->isInitialized(); +} + +/*! + Sets the locale to be used by the this manager to \a locale. + + If this mapping manager supports returning map labels + in different languages, they will be returned in the language of \a locale. + + The locale used defaults to the system locale if this is not set. +*/ +void QGeoMappingManager::setLocale(const QLocale &locale) +{ + d_ptr->engine->setLocale(locale); +} + +/*! + Returns the locale used to hint to this mapping manager about what + language to use for map labels. +*/ +QLocale QGeoMappingManager::locale() const +{ + return d_ptr->engine->locale(); +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoMappingManagerPrivate::QGeoMappingManagerPrivate() + : engine(0) {} + +QGeoMappingManagerPrivate::~QGeoMappingManagerPrivate() +{ + delete engine; + engine = 0; +} + +#include "moc_qgeomappingmanager_p.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeomappingmanager_p.h b/src/location/maps/qgeomappingmanager_p.h new file mode 100644 index 0000000..2ec1e8b --- /dev/null +++ b/src/location/maps/qgeomappingmanager_p.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPPINGMANAGER_H +#define QGEOMAPPINGMANAGER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include "qgeomaptype_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoMap; +class QLocale; +class QGeoRectangle; +class QGeoCoordinate; +class QGeoMappingManagerPrivate; +class QGeoMapRequestOptions; +class QGeoMappingManagerEngine; +class QGeoCameraCapabilities; + + +class Q_LOCATION_EXPORT QGeoMappingManager : public QObject +{ + Q_OBJECT + +public: + ~QGeoMappingManager(); + + QString managerName() const; + int managerVersion() const; + + QGeoMap *createMap(QObject *parent); + + QList supportedMapTypes() const; + + bool isInitialized() const; + + QGeoCameraCapabilities cameraCapabilities() const; + + void setLocale(const QLocale &locale); + QLocale locale() const; + +Q_SIGNALS: + void initialized(); + void supportedMapTypesChanged(); + +protected: + QGeoMappingManager(QGeoMappingManagerEngine *engine, QObject *parent = 0); + +private: + QGeoMappingManagerPrivate *d_ptr; + Q_DISABLE_COPY(QGeoMappingManager) + + friend class QGeoServiceProvider; + friend class QGeoServiceProviderPrivate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeomappingmanager_p_p.h b/src/location/maps/qgeomappingmanager_p_p.h new file mode 100644 index 0000000..65d1b5e --- /dev/null +++ b/src/location/maps/qgeomappingmanager_p_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPPINGMANAGER_P_H +#define QGEOMAPPINGMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMappingManagerPrivate +{ +public: + QGeoMappingManagerPrivate(); + ~QGeoMappingManagerPrivate(); + + QGeoMappingManagerEngine *engine; + +private: + Q_DISABLE_COPY(QGeoMappingManagerPrivate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeomappingmanagerengine.cpp b/src/location/maps/qgeomappingmanagerengine.cpp new file mode 100644 index 0000000..0eeadf7 --- /dev/null +++ b/src/location/maps/qgeomappingmanagerengine.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomappingmanagerengine_p.h" +#include "qgeomappingmanagerengine_p_p.h" +#include "qgeotiledmapreply_p.h" +#include "qgeotilespec_p.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoMappingManagerEngine + \inmodule QtLocation + \ingroup QtLocation-impl + \since 5.6 + \internal + + \brief Provides support functionality for map display with QGeoServiceProvider. + + The QGeoMappingManagerEngine class provides an interface and convenience + methods to implementors of QGeoServiceProvider plugins who want to + provide support for displaying and interacting with maps. +*/ + +/*! + Constructs a new engine with the specified \a parent. +*/ +QGeoMappingManagerEngine::QGeoMappingManagerEngine(QObject *parent) + : QObject(parent), + d_ptr(new QGeoMappingManagerEnginePrivate()) {} + +/*! + Destroys this engine. +*/ +QGeoMappingManagerEngine::~QGeoMappingManagerEngine() +{ + Q_D(QGeoMappingManagerEngine); + delete d; +} + +/*! + Marks the engine as initialized. Subclasses of QGeoMappingManagerEngine are to + call this method after performing implementation-specific initializatioin within + the constructor. +*/ +void QGeoMappingManagerEngine::engineInitialized() +{ + Q_D(QGeoMappingManagerEngine); + d->initialized = true; + emit initialized(); +} + +/*! + Sets the name which this engine implementation uses to distinguish itself + from the implementations provided by other plugins to \a managerName. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +void QGeoMappingManagerEngine::setManagerName(const QString &managerName) +{ + d_ptr->managerName = managerName; +} + +/*! + Returns the name which this engine implementation uses to distinguish + itself from the implementations provided by other plugins. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +QString QGeoMappingManagerEngine::managerName() const +{ + return d_ptr->managerName; +} + +/*! + Sets the version of this engine implementation to \a managerVersion. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +void QGeoMappingManagerEngine::setManagerVersion(int managerVersion) +{ + d_ptr->managerVersion = managerVersion; +} + +/*! + Returns the version of this engine implementation. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +int QGeoMappingManagerEngine::managerVersion() const +{ + return d_ptr->managerVersion; +} + +QList QGeoMappingManagerEngine::supportedMapTypes() const +{ + Q_D(const QGeoMappingManagerEngine); + return d->supportedMapTypes; +} + +/*! + Sets the list of map types supported by this engine to \a mapTypes. + + Subclasses of QGeoMappingManagerEngine should use this function to ensure + that supportedMapTypes() provides accurate information. +*/ +void QGeoMappingManagerEngine::setSupportedMapTypes(const QList &supportedMapTypes) +{ + Q_D(QGeoMappingManagerEngine); + d->supportedMapTypes = supportedMapTypes; + emit supportedMapTypesChanged(); +} + +QGeoCameraCapabilities QGeoMappingManagerEngine::cameraCapabilities() const +{ + Q_D(const QGeoMappingManagerEngine); + return d->capabilities_; +} + +void QGeoMappingManagerEngine::setCameraCapabilities(const QGeoCameraCapabilities &capabilities) +{ + Q_D(QGeoMappingManagerEngine); + d->capabilities_ = capabilities; +} + +/*! + Return whether the engine has been initialized and is ready to be used. +*/ + +bool QGeoMappingManagerEngine::isInitialized() const +{ + Q_D(const QGeoMappingManagerEngine); + return d->initialized; +} + +/*! + Sets the locale to be used by the this manager to \a locale. + + If this mapping manager supports returning map labels + in different languages, they will be returned in the language of \a locale. + + The locale used defaults to the system locale if this is not set. +*/ +void QGeoMappingManagerEngine::setLocale(const QLocale &locale) +{ + d_ptr->locale = locale; +} + +/*! + Returns the locale used to hint to this mapping manager about what + language to use for map labels. +*/ +QLocale QGeoMappingManagerEngine::locale() const +{ + return d_ptr->locale; +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoMappingManagerEnginePrivate::QGeoMappingManagerEnginePrivate() + : managerVersion(-1), + initialized(false) {} + +QGeoMappingManagerEnginePrivate::~QGeoMappingManagerEnginePrivate() {} + +#include "moc_qgeomappingmanagerengine_p.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeomappingmanagerengine_p.h b/src/location/maps/qgeomappingmanagerengine_p.h new file mode 100644 index 0000000..fd48d44 --- /dev/null +++ b/src/location/maps/qgeomappingmanagerengine_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPPINGMANAGERENGINE_H +#define QGEOMAPPINGMANAGERENGINE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qgeomaptype_p.h" +#include "qgeomappingmanager_p.h" + +QT_BEGIN_NAMESPACE + +class QLocale; + +class QGeoRectangle; +class QGeoCoordinate; +class QGeoMappingManagerPrivate; +class QGeoMapRequestOptions; + +class QGeoMappingManagerEnginePrivate; +class QGeoMap; + +class Q_LOCATION_EXPORT QGeoMappingManagerEngine : public QObject +{ + Q_OBJECT + +public: + explicit QGeoMappingManagerEngine(QObject *parent = 0); + virtual ~QGeoMappingManagerEngine(); + + virtual QGeoMap *createMap() = 0; + + QVariantMap parameters() const; + + QString managerName() const; + int managerVersion() const; + + QList supportedMapTypes() const; + + QGeoCameraCapabilities cameraCapabilities() const; + + void setLocale(const QLocale &locale); + QLocale locale() const; + + bool isInitialized() const; + +Q_SIGNALS: + void initialized(); + void supportedMapTypesChanged(); + +protected: + void setSupportedMapTypes(const QList &supportedMapTypes); + void setCameraCapabilities(const QGeoCameraCapabilities &capabilities); + + void engineInitialized(); + +private: + QGeoMappingManagerEnginePrivate *d_ptr; + + void setManagerName(const QString &managerName); + void setManagerVersion(int managerVersion); + + Q_DECLARE_PRIVATE(QGeoMappingManagerEngine) + Q_DISABLE_COPY(QGeoMappingManagerEngine) + + friend class QGeoServiceProvider; + friend class QGeoServiceProviderPrivate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeomappingmanagerengine_p_p.h b/src/location/maps/qgeomappingmanagerengine_p_p.h new file mode 100644 index 0000000..5442686 --- /dev/null +++ b/src/location/maps/qgeomappingmanagerengine_p_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPPINGMANAGERENGINE_P_H +#define QGEOMAPPINGMANAGERENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include "qgeomaptype_p.h" +#include "qgeomappingmanager_p.h" +#include "qgeocameracapabilities_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoTileSpec; +class QGeoTiledMapReply; + +class QGeoMappingManagerEnginePrivate +{ +public: + QGeoMappingManagerEnginePrivate(); + ~QGeoMappingManagerEnginePrivate(); + + QString managerName; + int managerVersion; + + QList supportedMapTypes; + QGeoCameraCapabilities capabilities_; + + QLocale locale; + bool initialized; + +private: + Q_DISABLE_COPY(QGeoMappingManagerEnginePrivate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeomaptype.cpp b/src/location/maps/qgeomaptype.cpp new file mode 100644 index 0000000..b4efa1d --- /dev/null +++ b/src/location/maps/qgeomaptype.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomaptype_p.h" +#include "qgeomaptype_p_p.h" + +QT_BEGIN_NAMESPACE + +QGeoMapType::QGeoMapType() + : d_ptr(new QGeoMapTypePrivate()) {} + +QGeoMapType::QGeoMapType(const QGeoMapType &other) + : d_ptr(other.d_ptr) {} + +QGeoMapType::QGeoMapType(QGeoMapType::MapStyle style, const QString &name, + const QString &description, bool mobile, bool night, int mapId) +: d_ptr(new QGeoMapTypePrivate(style, name, description, mobile, night, mapId)) +{ +} + +QGeoMapType::~QGeoMapType() {} + +QGeoMapType &QGeoMapType::operator = (const QGeoMapType &other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +bool QGeoMapType::operator == (const QGeoMapType &other) const +{ + return (*d_ptr.constData() == *other.d_ptr.constData()); +} + +bool QGeoMapType::operator != (const QGeoMapType &other) const +{ + return !(operator ==(other)); +} + +QGeoMapType::MapStyle QGeoMapType::style() const +{ + return d_ptr->style_; +} + +QString QGeoMapType::name() const +{ + return d_ptr->name_; +} + +QString QGeoMapType::description() const +{ + return d_ptr->description_; +} + +bool QGeoMapType::mobile() const +{ + return d_ptr->mobile_; +} + +bool QGeoMapType::night() const +{ + return d_ptr->night_; +} + +int QGeoMapType::mapId() const +{ + return d_ptr->mapId_; +} + +QGeoMapTypePrivate::QGeoMapTypePrivate() +: style_(QGeoMapType::NoMap), mobile_(false), night_(false), mapId_(0) +{ +} + +QGeoMapTypePrivate::QGeoMapTypePrivate(const QGeoMapTypePrivate &other) +: QSharedData(other), style_(other.style_), name_(other.name_), description_(other.description_), + mobile_(other.mobile_), night_(other.night_), mapId_(other.mapId_) +{ +} + +QGeoMapTypePrivate::QGeoMapTypePrivate(QGeoMapType::MapStyle style, const QString &name, + const QString &description, bool mobile, bool night, + int mapId) +: style_(style), name_(name), description_(description), mobile_(mobile), night_(night), + mapId_(mapId) +{ +} + +QGeoMapTypePrivate::~QGeoMapTypePrivate() +{ +} + +bool QGeoMapTypePrivate::operator==(const QGeoMapTypePrivate &other) const +{ + return style_ == other.style_ && name_ == other.name_ && description_ == other.description_ && + mobile_ == other.mobile_ && night_ == other.night_ && mapId_ == other.mapId_; +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeomaptype_p.h b/src/location/maps/qgeomaptype_p.h new file mode 100644 index 0000000..78c7416 --- /dev/null +++ b/src/location/maps/qgeomaptype_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPTYPE_H +#define QGEOMAPTYPE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMapTypePrivate; + +class Q_LOCATION_EXPORT QGeoMapType +{ +public: + enum MapStyle { + NoMap = 0, + StreetMap, + SatelliteMapDay, + SatelliteMapNight, + TerrainMap, + HybridMap, + TransitMap, + GrayStreetMap, + PedestrianMap, + CarNavigationMap, + CycleMap, + CustomMap = 100 + }; + + QGeoMapType(); + QGeoMapType(const QGeoMapType &other); + QGeoMapType(MapStyle style, const QString &name, const QString &description, bool mobile, + bool night, int mapId); + ~QGeoMapType(); + + QGeoMapType &operator = (const QGeoMapType &other); + + bool operator == (const QGeoMapType &other) const; + bool operator != (const QGeoMapType &other) const; + + MapStyle style() const; + QString name() const; + QString description() const; + bool mobile() const; + bool night() const; + int mapId() const; + +private: + QSharedDataPointer d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QGEOMAPTYPE_H diff --git a/src/location/maps/qgeomaptype_p_p.h b/src/location/maps/qgeomaptype_p_p.h new file mode 100644 index 0000000..2aafd37 --- /dev/null +++ b/src/location/maps/qgeomaptype_p_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPTYPE_P_H +#define QGEOMAPTYPE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include "qgeomaptype_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoMapTypePrivate : public QSharedData +{ +public: + QGeoMapTypePrivate(); + QGeoMapTypePrivate(QGeoMapType::MapStyle style, const QString &name, const QString &description, bool mobile, bool night, int mapId); + QGeoMapTypePrivate(const QGeoMapTypePrivate &other); + ~QGeoMapTypePrivate(); + + QGeoMapTypePrivate &operator = (const QGeoMapTypePrivate &other); + + bool operator == (const QGeoMapTypePrivate &other) const; + + QGeoMapType::MapStyle style_; + QString name_; + QString description_; + bool mobile_; + bool night_; + int mapId_; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoMapTypePrivate) + +#endif // QGEOMAPTYPE_P_H diff --git a/src/location/maps/qgeoroute.cpp b/src/location/maps/qgeoroute.cpp new file mode 100644 index 0000000..52fa4a5 --- /dev/null +++ b/src/location/maps/qgeoroute.cpp @@ -0,0 +1,320 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroute.h" +#include "qgeoroute_p.h" + +#include "qgeorectangle.h" +#include "qgeoroutesegment.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoRoute + \inmodule QtLocation + \ingroup QtLocation-routing + \since 5.6 + + \brief The QGeoRoute class represents a route between two points. + + A QGeoRoute object contains high level information about a route, such + as the length the route, the estimated travel time for the route, + and enough information to render a basic image of the route on a map. + + The QGeoRoute object also contains a list of QGeoRouteSegment objecs which + describe subsections of the route in greater detail. + + Routing information is normally requested using + QGeoRoutingManager::calculateRoute(), which returns a QGeoRouteReply + instance. If the operation is completed successfully the routing + information can be accessed with QGeoRouteReply::routes() + + \sa QGeoRoutingManager +*/ + +/*! + Constructs a route object. +*/ +QGeoRoute::QGeoRoute() + : d_ptr(new QGeoRoutePrivate()) {} + +/*! + Constructs a route object from the contents of \a other. +*/ +QGeoRoute::QGeoRoute(const QGeoRoute &other) + : d_ptr(other.d_ptr) {} + +/*! + Destroys this route object. +*/ +QGeoRoute::~QGeoRoute() +{ +} + +/*! + Assigns the contents of \a other to this route and returns a reference to + this route. +*/ +QGeoRoute &QGeoRoute::operator= (const QGeoRoute & other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns whether this route and \a other are equal. +*/ +bool QGeoRoute::operator ==(const QGeoRoute &other) const +{ + return (d_ptr.constData() == other.d_ptr.constData()); +} + +/*! + Returns whether this route and \a other are not equal. +*/ +bool QGeoRoute::operator !=(const QGeoRoute &other) const +{ + return (d_ptr.constData() != other.d_ptr.constData()); +} + +/*! + Sets the identifier of this route to \a id. + + Service providers which support the updating of routes commonly assign + identifiers to routes. If this route came from such a service provider changing + the identifier will probably cause route updates to stop working. +*/ +void QGeoRoute::setRouteId(const QString &id) +{ + d_ptr->id = id; +} + +/*! + Returns the identifier of this route. + + Service providers which support the updating of routes commonly assign + identifiers to routes. If this route did not come from such a service provider + the function will return an empty string. +*/ +QString QGeoRoute::routeId() const +{ + return d_ptr->id; +} + +/*! + Sets the route request which describes the criteria used in the + calculcation of this route to \a request. +*/ +void QGeoRoute::setRequest(const QGeoRouteRequest &request) +{ + d_ptr->request = request; +} + +/*! + Returns the route request which describes the criteria used in + the calculation of this route. +*/ +QGeoRouteRequest QGeoRoute::request() const +{ + return d_ptr->request; +} + +/*! + Sets the bounding box which encompasses the entire route to \a bounds. +*/ +void QGeoRoute::setBounds(const QGeoRectangle &bounds) +{ + d_ptr->bounds = bounds; +} + +/*! + Returns a bounding box which encompasses the entire route. +*/ +QGeoRectangle QGeoRoute::bounds() const +{ + return d_ptr->bounds; +} + +/*! + Sets the first route segment in the route to \a routeSegment. +*/ +void QGeoRoute::setFirstRouteSegment(const QGeoRouteSegment &routeSegment) +{ + d_ptr->firstSegment = routeSegment; +} + +/*! + Returns the first route segment in the route. + + Will return an invalid route segment if there are no route segments + associated with the route. + + The remaining route segments can be accessed sequentially with + QGeoRouteSegment::nextRouteSegment. +*/ +QGeoRouteSegment QGeoRoute::firstRouteSegment() const +{ + return d_ptr->firstSegment; +} + +/*! + Sets the estimated amount of time it will take to traverse this route, + in seconds, to \a secs. +*/ +void QGeoRoute::setTravelTime(int secs) +{ + d_ptr->travelTime = secs; +} + +/*! + Returns the estimated amount of time it will take to traverse this route, + in seconds. +*/ +int QGeoRoute::travelTime() const +{ + return d_ptr->travelTime; +} + +/*! + Sets the distance covered by this route, in meters, to \a distance. +*/ +void QGeoRoute::setDistance(qreal distance) +{ + d_ptr->distance = distance; +} + +/*! + Returns the distance covered by this route, in meters. +*/ +qreal QGeoRoute::distance() const +{ + return d_ptr->distance; +} + +/*! + Sets the travel mode for this route to \a mode. + + This should be one of the travel modes returned by request().travelModes(). +*/ +void QGeoRoute::setTravelMode(QGeoRouteRequest::TravelMode mode) +{ + d_ptr->travelMode = mode; +} + +/*! + Returns the travel mode for the this route. + + This should be one of the travel modes returned by request().travelModes(). +*/ +QGeoRouteRequest::TravelMode QGeoRoute::travelMode() const +{ + return d_ptr->travelMode; +} + +/*! + Sets the geometric shape of the route to \a path. + + The coordinates in \a path should be listed in the order in which they + would be traversed by someone traveling along this segment of the route. +*/ +void QGeoRoute::setPath(const QList &path) +{ + d_ptr->path = path; +} + +/*! + Returns the geometric shape of the route. + + The coordinates should be listed in the order in which they + would be traversed by someone traveling along this segment of the route. +*/ +QList QGeoRoute::path() const +{ + return d_ptr->path; +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoRoutePrivate::QGeoRoutePrivate() + : travelTime(0), + distance(0.0), + travelMode(QGeoRouteRequest::CarTravel) {} + +QGeoRoutePrivate::QGeoRoutePrivate(const QGeoRoutePrivate &other) + : QSharedData(other), + id(other.id), + request(other.request), + bounds(other.bounds), + travelTime(other.travelTime), + distance(other.distance), + travelMode(other.travelMode), + path(other.path), + firstSegment(other.firstSegment) {} + +QGeoRoutePrivate::~QGeoRoutePrivate() {} + +bool QGeoRoutePrivate::operator ==(const QGeoRoutePrivate &other) const +{ + QGeoRouteSegment s1 = firstSegment; + QGeoRouteSegment s2 = other.firstSegment; + + while (true) { + if (s1.isValid() != s2.isValid()) + return false; + if (!s1.isValid()) + break; + if (s1 != s2) + return false; + s1 = s1.nextRouteSegment(); + s2 = s2.nextRouteSegment(); + } + + return ((id == other.id) + && (request == other.request) + && (bounds == other.bounds) + && (travelTime == other.travelTime) + && (distance == other.distance) + && (travelMode == other.travelMode) + && (path == other.path)); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroute.h b/src/location/maps/qgeoroute.h new file mode 100644 index 0000000..68e73c0 --- /dev/null +++ b/src/location/maps/qgeoroute.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTE_H +#define QGEOROUTE_H + +#include +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRectangle; +class QGeoRouteSegment; + +class QGeoRoutePrivate; + +class Q_LOCATION_EXPORT QGeoRoute +{ +public: + QGeoRoute(); + QGeoRoute(const QGeoRoute &other); + ~QGeoRoute(); + + QGeoRoute &operator = (const QGeoRoute &other); + + bool operator == (const QGeoRoute &other) const; + bool operator != (const QGeoRoute &other) const; + + void setRouteId(const QString &id); + QString routeId() const; + + void setRequest(const QGeoRouteRequest &request); + QGeoRouteRequest request() const; + + void setBounds(const QGeoRectangle &bounds); + QGeoRectangle bounds() const; + + void setFirstRouteSegment(const QGeoRouteSegment &routeSegment); + QGeoRouteSegment firstRouteSegment() const; + + void setTravelTime(int secs); + int travelTime() const; + + void setDistance(qreal distance); + qreal distance() const; + + void setTravelMode(QGeoRouteRequest::TravelMode mode); + QGeoRouteRequest::TravelMode travelMode() const; + + void setPath(const QList &path); + QList path() const; + +private: + QExplicitlySharedDataPointer d_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoroute_p.h b/src/location/maps/qgeoroute_p.h new file mode 100644 index 0000000..66ef3c6 --- /dev/null +++ b/src/location/maps/qgeoroute_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTE_P_H +#define QGEOROUTE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeoroute.h" +#include "qgeorouterequest.h" +#include "qgeorectangle.h" +#include "qgeoroutesegment.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; + +class QGeoRoutePrivate : public QSharedData +{ +public: + QGeoRoutePrivate(); + QGeoRoutePrivate(const QGeoRoutePrivate &other); + ~QGeoRoutePrivate(); + + bool operator == (const QGeoRoutePrivate &other) const; + + QString id; + QGeoRouteRequest request; + + QGeoRectangle bounds; +// QList routeSegments; + + int travelTime; + qreal distance; + + QGeoRouteRequest::TravelMode travelMode; + + QList path; + + QGeoRouteSegment firstSegment; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeorouteparser.cpp b/src/location/maps/qgeorouteparser.cpp new file mode 100644 index 0000000..646902e --- /dev/null +++ b/src/location/maps/qgeorouteparser.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeorouteparser_p.h" +#include "qgeorouteparser_p_p.h" +#include "qgeoroutesegment.h" +#include "qgeomaneuver.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/* + Private class implementations +*/ + +QGeoRouteParserPrivate::QGeoRouteParserPrivate() : QObjectPrivate() +{ +} + +QGeoRouteParserPrivate::~QGeoRouteParserPrivate() +{ +} + +/* + Public class implementations +*/ + +QGeoRouteParser::~QGeoRouteParser() +{ + +} + +QGeoRouteParser::QGeoRouteParser(QGeoRouteParserPrivate &dd, QObject *parent) : QObject(dd, parent) +{ + +} + +QGeoRouteReply::Error QGeoRouteParser::parseReply(QList &routes, QString &errorString, const QByteArray &reply) const +{ + Q_D(const QGeoRouteParser); + return d->parseReply(routes, errorString, reply); +} + +QUrl QGeoRouteParser::requestUrl(const QGeoRouteRequest &request, const QString &prefix) const +{ + Q_D(const QGeoRouteParser); + return d->requestUrl(request, prefix); +} + +QT_END_NAMESPACE + + diff --git a/src/location/maps/qgeorouteparser_p.h b/src/location/maps/qgeorouteparser_p.h new file mode 100644 index 0000000..da1c09f --- /dev/null +++ b/src/location/maps/qgeorouteparser_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QOSRMROUTEPARSER_P_H +#define QOSRMROUTEPARSER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRouteParserPrivate; +class Q_LOCATION_EXPORT QGeoRouteParser : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGeoRouteParser) + +public: + virtual ~QGeoRouteParser(); + QGeoRouteReply::Error parseReply(QList &routes, QString &errorString, const QByteArray &reply) const; + QUrl requestUrl(const QGeoRouteRequest &request, const QString &prefix) const; + +protected: + QGeoRouteParser(QGeoRouteParserPrivate &dd, QObject *parent = Q_NULLPTR); + +private: + Q_DISABLE_COPY(QGeoRouteParser) +}; + +QT_END_NAMESPACE + +#endif // QOSRMROUTEPARSER_P_H diff --git a/src/location/maps/qgeorouteparser_p_p.h b/src/location/maps/qgeorouteparser_p_p.h new file mode 100644 index 0000000..7bf41f8 --- /dev/null +++ b/src/location/maps/qgeorouteparser_p_p.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTEPARSER_P_P_H +#define QGEOROUTEPARSER_P_P_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRouteParserPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGeoRouteParser) +public: + QGeoRouteParserPrivate(); + virtual ~QGeoRouteParserPrivate(); + + virtual QGeoRouteReply::Error parseReply(QList &routes, QString &errorString, const QByteArray &reply) const = 0; + virtual QUrl requestUrl(const QGeoRouteRequest &request, const QString &prefix) const = 0; +}; + +QT_END_NAMESPACE + +#endif // QGEOROUTEPARSER_P_P_H diff --git a/src/location/maps/qgeorouteparserosrmv4.cpp b/src/location/maps/qgeorouteparserosrmv4.cpp new file mode 100644 index 0000000..7321fb6 --- /dev/null +++ b/src/location/maps/qgeorouteparserosrmv4.cpp @@ -0,0 +1,404 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeorouteparserosrmv4_p.h" +#include "qgeorouteparser_p_p.h" +#include "qgeoroutesegment.h" +#include "qgeomaneuver.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static QList parsePolyline(const QByteArray &data) +{ + QList path; + + bool parsingLatitude = true; + + int shift = 0; + int value = 0; + + QGeoCoordinate coord(0, 0); + + for (int i = 0; i < data.length(); ++i) { + unsigned char c = data.at(i) - 63; + + value |= (c & 0x1f) << shift; + shift += 5; + + // another chunk + if (c & 0x20) + continue; + + int diff = (value & 1) ? ~(value >> 1) : (value >> 1); + + if (parsingLatitude) { + coord.setLatitude(coord.latitude() + (double)diff/1e6); + } else { + coord.setLongitude(coord.longitude() + (double)diff/1e6); + path.append(coord); + } + + parsingLatitude = !parsingLatitude; + + value = 0; + shift = 0; + } + + return path; +} + +static QGeoManeuver::InstructionDirection osrmInstructionDirection(const QString &instructionCode) +{ + if (instructionCode == QLatin1String("0")) + return QGeoManeuver::NoDirection; + else if (instructionCode == QLatin1String("1")) + return QGeoManeuver::DirectionForward; + else if (instructionCode == QLatin1String("2")) + return QGeoManeuver::DirectionBearRight; + else if (instructionCode == QLatin1String("3")) + return QGeoManeuver::DirectionRight; + else if (instructionCode == QLatin1String("4")) + return QGeoManeuver::DirectionHardRight; + else if (instructionCode == QLatin1String("5")) + return QGeoManeuver::DirectionUTurnLeft; + else if (instructionCode == QLatin1String("6")) + return QGeoManeuver::DirectionHardLeft; + else if (instructionCode == QLatin1String("7")) + return QGeoManeuver::DirectionLeft; + else if (instructionCode == QLatin1String("8")) + return QGeoManeuver::DirectionBearLeft; + else if (instructionCode == QLatin1String("9")) + return QGeoManeuver::NoDirection; + else if (instructionCode == QLatin1String("10")) + return QGeoManeuver::DirectionForward; + else if (instructionCode == QLatin1String("11")) + return QGeoManeuver::NoDirection; + else if (instructionCode == QLatin1String("12")) + return QGeoManeuver::NoDirection; + else if (instructionCode == QLatin1String("13")) + return QGeoManeuver::NoDirection; + else if (instructionCode == QLatin1String("14")) + return QGeoManeuver::NoDirection; + else if (instructionCode == QLatin1String("15")) + return QGeoManeuver::NoDirection; + else + return QGeoManeuver::NoDirection; +} + +static QString osrmInstructionText(const QString &instructionCode, const QString &wayname) +{ + if (instructionCode == QLatin1String("0")) { + return QString(); + } else if (instructionCode == QLatin1String("1")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Go straight."); + else + return QGeoRouteParserOsrmV4::tr("Go straight onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("2")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Turn slightly right."); + else + return QGeoRouteParserOsrmV4::tr("Turn slightly right onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("3")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Turn right."); + else + return QGeoRouteParserOsrmV4::tr("Turn right onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("4")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Make a sharp right."); + else + return QGeoRouteParserOsrmV4::tr("Make a sharp right onto %1.").arg(wayname); + } + else if (instructionCode == QLatin1String("5")) { + return QGeoRouteParserOsrmV4::tr("When it is safe to do so, perform a U-turn."); + } else if (instructionCode == QLatin1String("6")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Make a sharp left."); + else + return QGeoRouteParserOsrmV4::tr("Make a sharp left onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("7")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Turn left."); + else + return QGeoRouteParserOsrmV4::tr("Turn left onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("8")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Turn slightly left."); + else + return QGeoRouteParserOsrmV4::tr("Turn slightly left onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("9")) { + return QGeoRouteParserOsrmV4::tr("Reached waypoint."); + } else if (instructionCode == QLatin1String("10")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Head on."); + else + return QGeoRouteParserOsrmV4::tr("Head onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11")) { + return QGeoRouteParserOsrmV4::tr("Enter the roundabout."); + } else if (instructionCode == QLatin1String("11-1")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("At the roundabout take the first exit."); + else + return QGeoRouteParserOsrmV4::tr("At the roundabout take the first exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-2")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("At the roundabout take the second exit."); + else + return QGeoRouteParserOsrmV4::tr("At the roundabout take the second exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-3")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("At the roundabout take the third exit."); + else + return QGeoRouteParserOsrmV4::tr("At the roundabout take the third exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-4")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("At the roundabout take the fourth exit."); + else + return QGeoRouteParserOsrmV4::tr("At the roundabout take the fourth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-5")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("At the roundabout take the fifth exit."); + else + return QGeoRouteParserOsrmV4::tr("At the roundabout take the fifth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-6")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("At the roundabout take the sixth exit."); + else + return QGeoRouteParserOsrmV4::tr("At the roundabout take the sixth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-7")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("At the roundabout take the seventh exit."); + else + return QGeoRouteParserOsrmV4::tr("At the roundabout take the seventh exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-8")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("At the roundabout take the eighth exit."); + else + return QGeoRouteParserOsrmV4::tr("At the roundabout take the eighth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-9")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("At the roundabout take the ninth exit."); + else + return QGeoRouteParserOsrmV4::tr("At the roundabout take the ninth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("12")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Leave the roundabout."); + else + return QGeoRouteParserOsrmV4::tr("Leave the roundabout onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("13")) { + return QGeoRouteParserOsrmV4::tr("Stay on the roundabout."); + } else if (instructionCode == QLatin1String("14")) { + if (wayname.isEmpty()) + return QGeoRouteParserOsrmV4::tr("Start at the end of the street."); + else + return QGeoRouteParserOsrmV4::tr("Start at the end of %1.").arg(wayname); + } else if (instructionCode == QLatin1String("15")) { + return QGeoRouteParserOsrmV4::tr("You have reached your destination."); + } else { + return QGeoRouteParserOsrmV4::tr("Don't know what to say for '%1'").arg(instructionCode); + } +} + +static QGeoRoute constructRoute(const QByteArray &geometry, const QJsonArray &instructions, + const QJsonObject &summary) +{ + QGeoRoute route; + + QList path = parsePolyline(geometry); + + QGeoRouteSegment firstSegment; + int firstPosition = -1; + + int segmentPathLengthCount = 0; + + for (int i = instructions.count() - 1; i >= 0; --i) { + QJsonArray instruction = instructions.at(i).toArray(); + + if (instruction.count() < 8) { + qWarning("Instruction does not contain enough fields."); + continue; + } + + const QString instructionCode = instruction.at(0).toString(); + const QString wayname = instruction.at(1).toString(); + double segmentLength = instruction.at(2).toDouble(); + int position = instruction.at(3).toDouble(); + int time = instruction.at(4).toDouble(); + //const QString segmentLengthString = instruction.at(5).toString(); + //const QString direction = instruction.at(6).toString(); + //double azimuth = instruction.at(7).toDouble(); + + QGeoRouteSegment segment; + segment.setDistance(segmentLength); + + QGeoManeuver maneuver; + maneuver.setDirection(osrmInstructionDirection(instructionCode)); + maneuver.setDistanceToNextInstruction(segmentLength); + maneuver.setInstructionText(osrmInstructionText(instructionCode, wayname)); + maneuver.setPosition(path.at(position)); + maneuver.setTimeToNextInstruction(time); + + segment.setManeuver(maneuver); + + if (firstPosition == -1) + segment.setPath(path.mid(position)); + else + segment.setPath(path.mid(position, firstPosition - position)); + + segmentPathLengthCount += segment.path().length(); + + segment.setTravelTime(time); + + segment.setNextRouteSegment(firstSegment); + + firstSegment = segment; + firstPosition = position; + } + + route.setDistance(summary.value(QStringLiteral("total_distance")).toDouble()); + route.setTravelTime(summary.value(QStringLiteral("total_time")).toDouble()); + route.setFirstRouteSegment(firstSegment); + route.setPath(path); + + return route; +} + +class QGeoRouteParserOsrmV4Private : public QGeoRouteParserPrivate +{ + Q_DECLARE_PUBLIC(QGeoRouteParserOsrmV4) +public: + QGeoRouteParserOsrmV4Private(); + virtual ~QGeoRouteParserOsrmV4Private(); + + QGeoRouteReply::Error parseReply(QList &routes, QString &errorString, const QByteArray &reply) const Q_DECL_OVERRIDE; + QUrl requestUrl(const QGeoRouteRequest &request, const QString &prefix) const Q_DECL_OVERRIDE; +}; + +QGeoRouteParserOsrmV4Private::QGeoRouteParserOsrmV4Private() : QGeoRouteParserPrivate() +{ +} + +QGeoRouteParserOsrmV4Private::~QGeoRouteParserOsrmV4Private() +{ +} + +QGeoRouteReply::Error QGeoRouteParserOsrmV4Private::parseReply(QList &routes, QString &errorString, const QByteArray &reply) const +{ + // OSRM v4 specs: https://github.com/Project-OSRM/osrm-backend/wiki/Server-API---v4,-old + QJsonDocument document = QJsonDocument::fromJson(reply); + + if (document.isObject()) { + QJsonObject object = document.object(); + + //double version = object.value(QStringLiteral("version")).toDouble(); + int status = object.value(QStringLiteral("status")).toDouble(); + QString statusMessage = object.value(QStringLiteral("status_message")).toString(); + + // status code 0 or 200 are case of success + // status code is 207 if no route was found + // an error occurred when trying to find a route + if (0 != status && 200 != status) { + errorString = statusMessage; + return QGeoRouteReply::UnknownError; + } + + QJsonObject routeSummary = object.value(QStringLiteral("route_summary")).toObject(); + + QByteArray routeGeometry = + object.value(QStringLiteral("route_geometry")).toString().toLatin1(); + + QJsonArray routeInstructions = object.value(QStringLiteral("route_instructions")).toArray(); + + QGeoRoute route = constructRoute(routeGeometry, routeInstructions, routeSummary); + + routes.append(route); + + QJsonArray alternativeSummaries = + object.value(QStringLiteral("alternative_summaries")).toArray(); + QJsonArray alternativeGeometries = + object.value(QStringLiteral("alternative_geometries")).toArray(); + QJsonArray alternativeInstructions = + object.value(QStringLiteral("alternative_instructions")).toArray(); + + if (alternativeSummaries.count() == alternativeGeometries.count() && + alternativeSummaries.count() == alternativeInstructions.count()) { + for (int i = 0; i < alternativeSummaries.count(); ++i) { + route = constructRoute(alternativeGeometries.at(i).toString().toLatin1(), + alternativeInstructions.at(i).toArray(), + alternativeSummaries.at(i).toObject()); + //routes.append(route); + } + } + + return QGeoRouteReply::NoError; + } else { + errorString = QStringLiteral("Couldn't parse json."); + return QGeoRouteReply::ParseError; + } +} + +QUrl QGeoRouteParserOsrmV4Private::requestUrl(const QGeoRouteRequest &request, const QString &prefix) const +{ + QUrl url(prefix); + QUrlQuery query; + + query.addQueryItem(QStringLiteral("instructions"), QStringLiteral("true")); + + foreach (const QGeoCoordinate &c, request.waypoints()) { + query.addQueryItem(QStringLiteral("loc"), QString::number(c.latitude()) + QLatin1Char(',') + + QString::number(c.longitude())); + } + + url.setQuery(query); + return url; +} + +QGeoRouteParserOsrmV4::QGeoRouteParserOsrmV4(QObject *parent) : QGeoRouteParser(*new QGeoRouteParserOsrmV4Private(), parent) +{ +} + +QGeoRouteParserOsrmV4::~QGeoRouteParserOsrmV4() +{ +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeorouteparserosrmv4_p.h b/src/location/maps/qgeorouteparserosrmv4_p.h new file mode 100644 index 0000000..3d38cbf --- /dev/null +++ b/src/location/maps/qgeorouteparserosrmv4_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTEPARSEROSRMV4_H +#define QGEOROUTEPARSEROSRMV4_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include + +QT_BEGIN_NAMESPACE + +class QGeoRouteParserOsrmV4Private; +class Q_LOCATION_EXPORT QGeoRouteParserOsrmV4 : public QGeoRouteParser +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGeoRouteParserOsrmV4) + +public: + QGeoRouteParserOsrmV4(QObject *parent = Q_NULLPTR); + virtual ~QGeoRouteParserOsrmV4(); + +private: + Q_DISABLE_COPY(QGeoRouteParserOsrmV4) +}; + +QT_END_NAMESPACE + +#endif // QGEOROUTEPARSEROSRMV4_H diff --git a/src/location/maps/qgeorouteparserosrmv5.cpp b/src/location/maps/qgeorouteparserosrmv5.cpp new file mode 100644 index 0000000..cbbf7fc --- /dev/null +++ b/src/location/maps/qgeorouteparserosrmv5.cpp @@ -0,0 +1,979 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeorouteparserosrmv5_p.h" +#include "qgeorouteparser_p_p.h" +#include "qgeoroutesegment.h" +#include "qgeomaneuver.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static QList decodePolyline(const QString &polylineString) +{ + QList path; + if (polylineString.isEmpty()) + return path; + + QByteArray data = polylineString.toLatin1(); + + bool parsingLatitude = true; + + int shift = 0; + int value = 0; + + QGeoCoordinate coord(0, 0); + + for (int i = 0; i < data.length(); ++i) { + unsigned char c = data.at(i) - 63; + + value |= (c & 0x1f) << shift; + shift += 5; + + // another chunk + if (c & 0x20) + continue; + + int diff = (value & 1) ? ~(value >> 1) : (value >> 1); + + if (parsingLatitude) { + coord.setLatitude(coord.latitude() + (double)diff/1e5); + } else { + coord.setLongitude(coord.longitude() + (double)diff/1e5); + path.append(coord); + } + + parsingLatitude = !parsingLatitude; + + value = 0; + shift = 0; + } + + return path; +} + +static QString cardinalDirection4(QLocationUtils::CardinalDirection direction) +{ + switch (direction) { + case QLocationUtils::CardinalN: + //: Always used in "Head %1 [onto ]" + return QGeoRouteParserOsrmV5::tr("North"); + case QLocationUtils::CardinalE: + return QGeoRouteParserOsrmV5::tr("East"); + case QLocationUtils::CardinalS: + return QGeoRouteParserOsrmV5::tr("South"); + case QLocationUtils::CardinalW: + return QGeoRouteParserOsrmV5::tr("West"); + default: + return QString(); + } +} + +static QString exitOrdinal(int exit) +{ + static QList ordinals; + + if (!ordinals.size()) { + ordinals.append(QStringLiteral("")); + //: always used in " and take the %1 exit [onto ]" + ordinals.append(QGeoRouteParserOsrmV5::tr("first", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("second", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("third", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("fourth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("fifth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("sixth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("seventh", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("eighth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("ninth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("tenth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("eleventh", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("twelfth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("thirteenth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("fourteenth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("fifteenth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("sixteenth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("seventeenth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("eighteenth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("nineteenth", "roundabout exit")); + ordinals.append(QGeoRouteParserOsrmV5::tr("twentieth", "roundabout exit")); + }; + + if (exit < 1 || exit > ordinals.size()) + return QString(); + return ordinals[exit]; +} + +static QString exitDirection(int exit, const QString &wayName) +{ + /*: Always appended to one of the following strings: + - "Enter the roundabout" + - "Enter the rotary" + - "Enter the rotary " + */ + static QString directionExit = QGeoRouteParserOsrmV5::tr(" and take the %1 exit"); + static QString directionExitOnto = QGeoRouteParserOsrmV5::tr(" and take the %1 exit onto %2"); + + if (exit < 1 || exit > 20) + return QString(); + if (wayName.isEmpty()) + return directionExit.arg(exitOrdinal(exit)); + else + return directionExitOnto.arg(exitOrdinal(exit), wayName); +} + +static QString instructionArrive(QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionForward: + return QGeoRouteParserOsrmV5::tr("You have arrived at your destination, straight ahead"); + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionHardLeft: + case QGeoManeuver::DirectionLeft: + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + return QGeoRouteParserOsrmV5::tr("You have arrived at your destination, on the left"); + case QGeoManeuver::DirectionUTurnRight: + case QGeoManeuver::DirectionHardRight: + case QGeoManeuver::DirectionRight: + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + return QGeoRouteParserOsrmV5::tr("You have arrived at your destination, on the right"); + default: + return QGeoRouteParserOsrmV5::tr("You have arrived at your destination"); + } +} + +static QString instructionContinue(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionForward: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue straight"); + else + return QGeoRouteParserOsrmV5::tr("Continue straight on %1").arg(wayName); + case QGeoManeuver::DirectionHardLeft: + case QGeoManeuver::DirectionLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue left"); + else + return QGeoRouteParserOsrmV5::tr("Continue left onto %1").arg(wayName); + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue slightly left"); + else + return QGeoRouteParserOsrmV5::tr("Continue slightly left on %1").arg(wayName); + case QGeoManeuver::DirectionHardRight: + case QGeoManeuver::DirectionRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue right"); + else + return QGeoRouteParserOsrmV5::tr("Continue right onto %1").arg(wayName); + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue slightly right"); + else + return QGeoRouteParserOsrmV5::tr("Continue slightly right on %1").arg(wayName); + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionUTurnRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Make a U-turn"); + else + return QGeoRouteParserOsrmV5::tr("Make a U-turn onto %1").arg(wayName); + default: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue"); + else + return QGeoRouteParserOsrmV5::tr("Continue on %1").arg(wayName); + } +} + +static QString instructionDepart(const QJsonObject &maneuver, const QString &wayName) +{ + double bearing = maneuver.value(QLatin1String("bearing_after")).toDouble(-1.0); + if (bearing >= 0.0) { + if (wayName.isEmpty()) + //: %1 is "North", "South", "East" or "West" + return QGeoRouteParserOsrmV5::tr("Head %1").arg(cardinalDirection4(QLocationUtils::azimuthToCardinalDirection4(bearing))); + else + return QGeoRouteParserOsrmV5::tr("Head %1 onto %2").arg(cardinalDirection4(QLocationUtils::azimuthToCardinalDirection4(bearing)), wayName); + } else { + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Depart"); + else + return QGeoRouteParserOsrmV5::tr("Depart onto %1").arg(wayName); + } +} + +static QString instructionEndOfRoad(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionHardLeft: + case QGeoManeuver::DirectionLeft: + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the end of the road, turn left"); + else + return QGeoRouteParserOsrmV5::tr("At the end of the road, turn left onto %1").arg(wayName); + case QGeoManeuver::DirectionHardRight: + case QGeoManeuver::DirectionRight: + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the end of the road, turn right"); + else + return QGeoRouteParserOsrmV5::tr("At the end of the road, turn right onto %1").arg(wayName); + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionUTurnRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the end of the road, make a U-turn"); + else + return QGeoRouteParserOsrmV5::tr("At the end of the road, make a U-turn onto %1").arg(wayName); + case QGeoManeuver::DirectionForward: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the end of the road, continue straight"); + else + return QGeoRouteParserOsrmV5::tr("At the end of the road, continue straight onto %1").arg(wayName); + default: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the end of the road, continue"); + else + return QGeoRouteParserOsrmV5::tr("At the end of the road, continue onto %1").arg(wayName); + } +} + +static QString instructionFerry(const QString &wayName) +{ + QString instruction = QGeoRouteParserOsrmV5::tr("Take the ferry"); + if (!wayName.isEmpty()) + instruction += QLatin1String(" [") + wayName + QLatin1Char(']'); + + return instruction; +} + +static QString instructionFork(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionHardLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the fork, take a sharp left"); + else + return QGeoRouteParserOsrmV5::tr("At the fork, take a sharp left onto %1").arg(wayName); + case QGeoManeuver::DirectionLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the fork, turn left"); + else + return QGeoRouteParserOsrmV5::tr("At the fork, turn left onto %1").arg(wayName); + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the fork, keep left"); + else + return QGeoRouteParserOsrmV5::tr("At the fork, keep left onto %1").arg(wayName); + case QGeoManeuver::DirectionHardRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the fork, take a sharp right"); + else + return QGeoRouteParserOsrmV5::tr("At the fork, take a sharp right onto %1").arg(wayName); + case QGeoManeuver::DirectionRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the fork, turn right"); + else + return QGeoRouteParserOsrmV5::tr("At the fork, turn right onto %1").arg(wayName); + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the fork, keep right"); + else + return QGeoRouteParserOsrmV5::tr("At the fork, keep right onto %1").arg(wayName); + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionUTurnRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Make a U-turn"); + else + return QGeoRouteParserOsrmV5::tr("Make a U-turn onto %1").arg(wayName); + case QGeoManeuver::DirectionForward: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the fork, continue straight ahead"); + else + return QGeoRouteParserOsrmV5::tr("At the fork, continue straight ahead onto %1").arg(wayName); + default: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the fork, continue"); + else + return QGeoRouteParserOsrmV5::tr("At the fork, continue onto %1").arg(wayName); + } +} + +static QString instructionMerge(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionHardLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Merge sharply left"); + else + return QGeoRouteParserOsrmV5::tr("Merge sharply left onto %1").arg(wayName); + case QGeoManeuver::DirectionLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Merge left"); + else + return QGeoRouteParserOsrmV5::tr("Merge left onto %1").arg(wayName); + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Merge slightly left"); + else + return QGeoRouteParserOsrmV5::tr("Merge slightly left on %1").arg(wayName); + case QGeoManeuver::DirectionUTurnRight: + case QGeoManeuver::DirectionHardRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Merge sharply right"); + else + return QGeoRouteParserOsrmV5::tr("Merge sharply right onto %1").arg(wayName); + case QGeoManeuver::DirectionRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Merge right"); + else + return QGeoRouteParserOsrmV5::tr("Merge right onto %1").arg(wayName); + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Merge slightly right"); + else + return QGeoRouteParserOsrmV5::tr("Merge slightly right on %1").arg(wayName); + case QGeoManeuver::DirectionForward: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Merge straight"); + else + return QGeoRouteParserOsrmV5::tr("Merge straight on %1").arg(wayName); + default: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Merge"); + else + return QGeoRouteParserOsrmV5::tr("Merge onto %1").arg(wayName); + } +} + +static QString instructionNewName(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionHardLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Take a sharp left"); + else + return QGeoRouteParserOsrmV5::tr("Take a sharp left onto %1").arg(wayName); + case QGeoManeuver::DirectionLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Turn left"); + else + return QGeoRouteParserOsrmV5::tr("Turn left onto %1").arg(wayName); + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue slightly left"); + else + return QGeoRouteParserOsrmV5::tr("Continue slightly left onto %1").arg(wayName); + case QGeoManeuver::DirectionHardRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Take a sharp right"); + else + return QGeoRouteParserOsrmV5::tr("Take a sharp right onto %1").arg(wayName); + case QGeoManeuver::DirectionRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Turn right"); + else + return QGeoRouteParserOsrmV5::tr("Turn right onto %1").arg(wayName); + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Contine slightly right"); + else + return QGeoRouteParserOsrmV5::tr("Contine slightly right onto %1").arg(wayName); + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionUTurnRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Make a U-turn"); + else + return QGeoRouteParserOsrmV5::tr("Make a U-turn onto %1").arg(wayName); + case QGeoManeuver::DirectionForward: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue straight"); + else + return QGeoRouteParserOsrmV5::tr("Continue straight onto %1").arg(wayName); + default: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue"); + else + return QGeoRouteParserOsrmV5::tr("Continue onto %1").arg(wayName); + } +} + +static QString instructionNotification(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionHardLeft: + case QGeoManeuver::DirectionLeft: + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue on the left"); + else + return QGeoRouteParserOsrmV5::tr("Continue on the left on %1").arg(wayName); + case QGeoManeuver::DirectionUTurnRight: + case QGeoManeuver::DirectionHardRight: + case QGeoManeuver::DirectionRight: + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Contine on the right"); + else + return QGeoRouteParserOsrmV5::tr("Contine on the right on %1").arg(wayName); + case QGeoManeuver::DirectionForward: + default: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue"); + else + return QGeoRouteParserOsrmV5::tr("Continue on %1").arg(wayName); + } +} + +static QString instructionOffRamp(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionHardLeft: + case QGeoManeuver::DirectionLeft: + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Take the ramp on the left"); + else + return QGeoRouteParserOsrmV5::tr("Take the ramp on the left onto %1").arg(wayName); + case QGeoManeuver::DirectionUTurnRight: + case QGeoManeuver::DirectionHardRight: + case QGeoManeuver::DirectionRight: + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Take the ramp on the right"); + else + return QGeoRouteParserOsrmV5::tr("Take the ramp on the right onto %1").arg(wayName); + case QGeoManeuver::DirectionForward: + default: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Take the ramp"); + else + return QGeoRouteParserOsrmV5::tr("Take the ramp onto %1").arg(wayName); + } +} + +static QString instructionOnRamp(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + return instructionOffRamp(wayName, direction); +} + +static QString instructionPushingBike(const QString &wayName) +{ + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Get off the bike and push"); + else + return QGeoRouteParserOsrmV5::tr("Get off the bike and push onto %1").arg(wayName); +} + +static QString instructionRotary(const QJsonObject &step, const QJsonObject &maneuver, const QString &wayName) +{ + QString instruction; + QString rotaryName = step.value(QLatin1String("rotary_name")).toString(); + //QString modifier = maneuver.value(QLatin1String("modifier")).toString(); // Apparently not used for rotaries + int exit = maneuver.value(QLatin1String("exit")).toInt(0); + + //: This string will be prepended to " and take the exit [onto ] + instruction += QGeoRouteParserOsrmV5::tr("Enter the rotary"); + if (!rotaryName.isEmpty()) + instruction += QLatin1Char(' ') + rotaryName; + instruction += exitDirection(exit, wayName); + return instruction; +} + +static QString instructionRoundabout(const QJsonObject &maneuver, const QString &wayName) +{ + QString instruction; + //QString modifier = maneuver.value(QLatin1String("modifier")).toString(); // Apparently not used for rotaries + int exit = maneuver.value(QLatin1String("exit")).toInt(0); + + //: This string will be prepended to " and take the exit [onto ] + instruction += QGeoRouteParserOsrmV5::tr("Enter the roundabout"); + instruction += exitDirection(exit, wayName); + return instruction; +} + +static QString instructionRoundaboutTurn(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionForward: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the roundabout, continue straight"); + else + return QGeoRouteParserOsrmV5::tr("At the roundabout, continue straight on %1").arg(wayName); + case QGeoManeuver::DirectionHardLeft: + case QGeoManeuver::DirectionLeft: + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the roundabout, turn left"); + else + return QGeoRouteParserOsrmV5::tr("At the roundabout, turn left onto %1").arg(wayName); + case QGeoManeuver::DirectionHardRight: + case QGeoManeuver::DirectionRight: + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the roundabout, turn right"); + else + return QGeoRouteParserOsrmV5::tr("At the roundabout, turn right onto %1").arg(wayName); + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionUTurnRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the roundabout, turn around"); + else + return QGeoRouteParserOsrmV5::tr("At the roundabout, turn around onto %1").arg(wayName); + default: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("At the roundabout, continue"); + else + return QGeoRouteParserOsrmV5::tr("At the roundabout, continue onto %1").arg(wayName); + } +} + +static QString instructionTrain(const QString &wayName) +{ + QString instruction = QGeoRouteParserOsrmV5::tr("Take the train"); + if (!wayName.isEmpty()) + instruction += QLatin1String(" [") + wayName + QLatin1Char(']'); + + return instruction; +} + +static QString instructionTurn(const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + switch (direction) { + case QGeoManeuver::DirectionForward: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Go straight"); + else + return QGeoRouteParserOsrmV5::tr("Go straight onto %1").arg(wayName); + case QGeoManeuver::DirectionHardLeft: + case QGeoManeuver::DirectionLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Turn left"); + else + return QGeoRouteParserOsrmV5::tr("Turn left onto %1").arg(wayName); + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Turn slightly left"); + else + return QGeoRouteParserOsrmV5::tr("Turn slightly left onto %1").arg(wayName); + case QGeoManeuver::DirectionHardRight: + case QGeoManeuver::DirectionRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Turn right"); + else + return QGeoRouteParserOsrmV5::tr("Turn right onto %1").arg(wayName); + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Turn slightly right"); + else + return QGeoRouteParserOsrmV5::tr("Turn slightly right onto %1").arg(wayName); + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionUTurnRight: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Make a U-turn"); + else + return QGeoRouteParserOsrmV5::tr("Make a U-turn onto %1").arg(wayName); + default: + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Turn"); + else + return QGeoRouteParserOsrmV5::tr("Turn onto %1").arg(wayName); + } +} + +static QString instructionUseLane(const QJsonObject &maneuver, const QString &wayName, QGeoManeuver::InstructionDirection direction) +{ + QString laneTypes = maneuver.value(QLatin1String("laneTypes")).toString(); + QString laneInstruction; + if (laneTypes == QLatin1String("xo") || laneTypes == QLatin1String("xoo") || laneTypes == QLatin1String("xxo")) + //: "and [onto ] will be appended to this string. E.g., "Keep right and make a sharp left" + laneInstruction = QLatin1String("Keep right"); + else if (laneTypes == QLatin1String("ox") || laneTypes == QLatin1String("oox") || laneTypes == QLatin1String("oxx")) + laneInstruction = QLatin1String("Keep left"); + else if (laneTypes == QLatin1String("xox")) + laneInstruction = QLatin1String("Use the middle lane"); + else if (laneTypes == QLatin1String("oxo")) + laneInstruction = QLatin1String("Use the left or the right lane"); + + if (laneInstruction.isEmpty()) { + if (wayName.isEmpty()) + return QGeoRouteParserOsrmV5::tr("Continue straight"); + else + return QGeoRouteParserOsrmV5::tr("Continue straight onto %1").arg(wayName); + } + + switch (direction) { + case QGeoManeuver::DirectionForward: + if (wayName.isEmpty()) + //: This string will be prepended with lane instructions. E.g., "Use the left or the right lane and continue straight" + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and continue straight"); + else + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and continue straight onto %1").arg(wayName); + case QGeoManeuver::DirectionHardLeft: + if (wayName.isEmpty()) + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a sharp left"); + else + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a sharp left onto %1").arg(wayName); + case QGeoManeuver::DirectionLeft: + if (wayName.isEmpty()) + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and turn left"); + else + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and turn left onto %1").arg(wayName); + case QGeoManeuver::DirectionLightLeft: + case QGeoManeuver::DirectionBearLeft: + if (wayName.isEmpty()) + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a slight left"); + else + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a slight left onto %1").arg(wayName); + case QGeoManeuver::DirectionHardRight: + if (wayName.isEmpty()) + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a sharp right"); + else + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a sharp right onto %1").arg(wayName); + case QGeoManeuver::DirectionRight: + if (wayName.isEmpty()) + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and turn right"); + else + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and turn right onto %1").arg(wayName); + case QGeoManeuver::DirectionLightRight: + case QGeoManeuver::DirectionBearRight: + if (wayName.isEmpty()) + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a slight right"); + else + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a slight right onto %1").arg(wayName); + case QGeoManeuver::DirectionUTurnLeft: + case QGeoManeuver::DirectionUTurnRight: + if (wayName.isEmpty()) + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a U-turn"); + else + return laneInstruction + QGeoRouteParserOsrmV5::tr(" and make a U-turn onto %1").arg(wayName); + default: + return laneInstruction; + } +} + +static QString instructionText(const QJsonObject &step, const QJsonObject &maneuver, QGeoManeuver::InstructionDirection direction) { + QString modifier; + if (maneuver.value(QLatin1String("modifier")).isString()) + modifier = maneuver.value(QLatin1String("modifier")).toString(); + QString maneuverType; + if (maneuver.value(QLatin1String("type")).isString()) + maneuverType = maneuver.value(QLatin1String("type")).toString(); + QString wayName = QStringLiteral("unknown street"); + if (step.value(QLatin1String("name")).isString()) + wayName = step.value(QLatin1String("name")).toString(); + + + if (maneuverType == QLatin1String("arrive")) + return instructionArrive(direction); + else if (maneuverType == QLatin1String("continue")) + return instructionContinue(wayName, direction); + else if (maneuverType == QLatin1String("depart")) + return instructionDepart(maneuver, wayName); + else if (maneuverType == QLatin1String("end of road")) + return instructionEndOfRoad(wayName, direction); + else if (maneuverType == QLatin1String("ferry")) + return instructionFerry(wayName); + else if (maneuverType == QLatin1String("fork")) + return instructionFork(wayName, direction); + else if (maneuverType == QLatin1String("merge")) + return instructionMerge(wayName, direction); + else if (maneuverType == QLatin1String("new name")) + return instructionNewName(wayName, direction); + else if (maneuverType == QLatin1String("notification")) + return instructionNotification(wayName, direction); + else if (maneuverType == QLatin1String("off ramp")) + return instructionOffRamp(wayName, direction); + else if (maneuverType == QLatin1String("on ramp")) + return instructionOnRamp(wayName, direction); + else if (maneuverType == QLatin1String("pushing bike")) + return instructionPushingBike(wayName); + else if (maneuverType == QLatin1String("rotary")) + return instructionRotary(step, maneuver, wayName); + else if (maneuverType == QLatin1String("roundabout")) + return instructionRoundabout(maneuver, wayName); + else if (maneuverType == QLatin1String("roundabout turn")) + return instructionRoundaboutTurn(wayName, direction); + else if (maneuverType == QLatin1String("train")) + return instructionTrain(wayName); + else if (maneuverType == QLatin1String("turn")) + return instructionTurn(wayName, direction); + else if (maneuverType == QLatin1String("use lane")) + return instructionUseLane(maneuver, wayName, direction); + else + return maneuverType + QLatin1String(" to/onto ") + wayName; +} + +static QGeoManeuver::InstructionDirection instructionDirection(const QJsonObject &maneuver) +{ + QString modifier; + if (maneuver.value(QLatin1String("modifier")).isString()) + modifier = maneuver.value(QLatin1String("modifier")).toString(); + + if (modifier.isEmpty()) + return QGeoManeuver::NoDirection; + else if (modifier == QLatin1String("straight")) + return QGeoManeuver::DirectionForward; + else if (modifier == QLatin1String("right")) + return QGeoManeuver::DirectionRight; + else if (modifier == QLatin1String("sharp right")) + return QGeoManeuver::DirectionHardRight; + else if (modifier == QLatin1String("slight right")) + return QGeoManeuver::DirectionLightRight; + else if (modifier == QLatin1String("uturn")) + return QGeoManeuver::DirectionUTurnRight; + else if (modifier == QLatin1String("left")) + return QGeoManeuver::DirectionLeft; + else if (modifier == QLatin1String("sharp left")) + return QGeoManeuver::DirectionHardLeft; + else if (modifier == QLatin1String("slight left")) + return QGeoManeuver::DirectionLightLeft; + else + return QGeoManeuver::NoDirection; +} + +static QGeoRouteSegment parseStep(const QJsonObject &step) { + // OSRM Instructions documentation: https://github.com/Project-OSRM/osrm-text-instructions/blob/master/instructions.json + QGeoRouteSegment segment; + if (!step.value(QLatin1String("maneuver")).isObject()) + return segment; + QJsonObject maneuver = step.value(QLatin1String("maneuver")).toObject(); + if (!step.value(QLatin1String("duration")).isDouble()) + return segment; + if (!step.value(QLatin1String("distance")).isDouble()) + return segment; + if (!step.value(QLatin1String("intersections")).isArray()) + return segment; + if (!maneuver.value(QLatin1String("location")).isArray()) + return segment; + + double time = step.value(QLatin1String("duration")).toDouble(); + double distance = step.value(QLatin1String("distance")).toDouble(); + + QJsonArray position = maneuver.value(QLatin1String("location")).toArray(); + if (position.isEmpty()) + return segment; + double latitude = position[1].toDouble(); + double longitude = position[0].toDouble(); + QGeoCoordinate coord(latitude, longitude); + + QString geometry = step.value(QLatin1String("geometry")).toString(); + QList path = decodePolyline(geometry); + + QGeoManeuver geoManeuver; + geoManeuver.setDirection(instructionDirection(maneuver)); + geoManeuver.setDistanceToNextInstruction(distance); + geoManeuver.setTimeToNextInstruction(time); + geoManeuver.setInstructionText(instructionText(step, maneuver, geoManeuver.direction())); + geoManeuver.setPosition(coord); + geoManeuver.setWaypoint(coord); + + segment.setDistance(distance); + segment.setPath(path); + segment.setTravelTime(time); + segment.setManeuver(geoManeuver); + return segment; +} + +class QGeoRouteParserOsrmV5Private : public QGeoRouteParserPrivate +{ + Q_DECLARE_PUBLIC(QGeoRouteParserOsrmV5) +public: + QGeoRouteParserOsrmV5Private(); + virtual ~QGeoRouteParserOsrmV5Private(); + + QGeoRouteReply::Error parseReply(QList &routes, QString &errorString, const QByteArray &reply) const Q_DECL_OVERRIDE; + QUrl requestUrl(const QGeoRouteRequest &request, const QString &prefix) const Q_DECL_OVERRIDE; +}; + +QGeoRouteParserOsrmV5Private::QGeoRouteParserOsrmV5Private() : QGeoRouteParserPrivate() +{ +} + +QGeoRouteParserOsrmV5Private::~QGeoRouteParserOsrmV5Private() +{ +} + +QGeoRouteReply::Error QGeoRouteParserOsrmV5Private::parseReply(QList &routes, QString &errorString, const QByteArray &reply) const +{ + // OSRM v5 specs: https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md + QJsonDocument document = QJsonDocument::fromJson(reply); + if (document.isObject()) { + QJsonObject object = document.object(); + + QString status = object.value(QStringLiteral("code")).toString(); + if (status != QLatin1String("Ok")) { + errorString = status; + return QGeoRouteReply::UnknownError; + } + if (!object.value(QLatin1String("routes")).isArray()) { + errorString = QLatin1String("No routes found"); + return QGeoRouteReply::ParseError; + } + + QJsonArray osrmRoutes = object.value(QLatin1String("routes")).toArray(); + foreach (const QJsonValue &r, osrmRoutes) { + if (!r.isObject()) + continue; + QJsonObject route = r.toObject(); + if (!route.value(QLatin1String("legs")).isArray()) + continue; + if (!route.value(QLatin1String("duration")).isDouble()) + continue; + if (!route.value(QLatin1String("distance")).isDouble()) + continue; + + double distance = route.value(QLatin1String("distance")).toDouble(); + double travelTime = route.value(QLatin1String("duration")).toDouble(); + bool error = false; + QList segments; + + QJsonArray legs = route.value(QLatin1String("legs")).toArray(); + foreach (const QJsonValue &l, legs) { + if (!l.isObject()) { // invalid leg record + error = true; + break; + } + QJsonObject leg = l.toObject(); + if (!leg.value(QLatin1String("steps")).isArray()) { // Invalid steps field + error = true; + break; + } + QJsonArray steps = leg.value(QLatin1String("steps")).toArray(); + foreach (const QJsonValue &s, steps) { + if (!s.isObject()) { + error = true; + break; + } + QGeoRouteSegment segment = parseStep(s.toObject()); + if (segment.isValid()) { + segments.append(segment); + } else { + error = true; + break; + } + } + if (error) + break; + } + + if (!error) { + QList path; + foreach (const QGeoRouteSegment &s, segments) + path.append(s.path()); + + for (int i = segments.size() - 1; i > 0; --i) + segments[i-1].setNextRouteSegment(segments[i]); + + QGeoRoute r; + r.setDistance(distance); + r.setTravelTime(travelTime); + if (!path.isEmpty()) { + r.setPath(path); + r.setFirstRouteSegment(segments.first()); + } + //r.setTravelMode(QGeoRouteRequest::CarTravel); // The only one supported by OSRM demo service, but other OSRM servers might do cycle or pedestrian too + routes.append(r); + } + } + + // setError(QGeoRouteReply::NoError, status); // can't do this, or NoError is emitted and does damages + return QGeoRouteReply::NoError; + } else { + errorString = QStringLiteral("Couldn't parse json."); + return QGeoRouteReply::ParseError; + } +} + +QUrl QGeoRouteParserOsrmV5Private::requestUrl(const QGeoRouteRequest &request, const QString &prefix) const +{ + QString routingUrl = prefix; + int notFirst = 0; + foreach (const QGeoCoordinate &c, request.waypoints()) { + if (notFirst) + routingUrl.append(QLatin1Char(';')); + routingUrl.append(QString::number(c.longitude())).append(QLatin1Char(',')).append(QString::number(c.latitude())); + ++notFirst; + } + + QUrl url(routingUrl); + QUrlQuery query; + query.addQueryItem(QStringLiteral("overview"), QStringLiteral("full")); + query.addQueryItem(QStringLiteral("steps"), QStringLiteral("true")); + query.addQueryItem(QStringLiteral("geometries"), QStringLiteral("polyline")); + query.addQueryItem(QStringLiteral("alternatives"), QStringLiteral("true")); + url.setQuery(query); + return url; +} + +QGeoRouteParserOsrmV5::QGeoRouteParserOsrmV5(QObject *parent) : QGeoRouteParser(*new QGeoRouteParserOsrmV5Private(), parent) +{ +} + +QGeoRouteParserOsrmV5::~QGeoRouteParserOsrmV5() +{ +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeorouteparserosrmv5_p.h b/src/location/maps/qgeorouteparserosrmv5_p.h new file mode 100644 index 0000000..47c6891 --- /dev/null +++ b/src/location/maps/qgeorouteparserosrmv5_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTEPARSEROSRMV5_H +#define QGEOROUTEPARSEROSRMV5_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include + +QT_BEGIN_NAMESPACE + +class QGeoRouteParserOsrmV5Private; +class Q_LOCATION_EXPORT QGeoRouteParserOsrmV5 : public QGeoRouteParser +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGeoRouteParserOsrmV5) + +public: + QGeoRouteParserOsrmV5(QObject *parent = Q_NULLPTR); + virtual ~QGeoRouteParserOsrmV5(); + +private: + Q_DISABLE_COPY(QGeoRouteParserOsrmV5) +}; + +QT_END_NAMESPACE + +#endif // QGEOROUTEPARSEROSRMV5_H diff --git a/src/location/maps/qgeoroutereply.cpp b/src/location/maps/qgeoroutereply.cpp new file mode 100644 index 0000000..ab869d3 --- /dev/null +++ b/src/location/maps/qgeoroutereply.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroutereply.h" +#include "qgeoroutereply_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoRouteReply + \inmodule QtLocation + \ingroup QtLocation-routing + \since 5.6 + + \brief The QGeoRouteReply class manages an operation started by an instance + of QGeoRoutingManager. + + Instances of QGeoRouteReply manage the state and results of these + operations. + + The isFinished(), error() and errorString() methods provide information + on whether the operation has completed and if it completed successfully. + + The finished() and error(QGeoRouteReply::Error,QString) + signals can be used to monitor the progress of the operation. + + It is possible that a newly created QGeoRouteReply may be in a finished + state, most commonly because an error has occurred. Since such an instance + will never emit the finished() or + error(QGeoRouteReply::Error,QString) signals, it is + important to check the result of isFinished() before making the connections + to the signals. The documentation for QGeoRoutingManager demonstrates how + this might be carried out. + + If the operation completes successfully the results will be able to be + accessed with routes(). +*/ + +/*! + \enum QGeoRouteReply::Error + + Describes an error which prevented the completion of the operation. + + \value NoError + No error has occurred. + \value EngineNotSetError + The routing manager that was used did not have a QGeoRoutingManagerEngine instance associated with it. + \value CommunicationError + An error occurred while communicating with the service provider. + \value ParseError + The response from the service provider was in an unrecognizable format. + \value UnsupportedOptionError + The requested operation or one of the options for the operation are not + supported by the service provider. + \value UnknownError + An error occurred which does not fit into any of the other categories. +*/ + +/*! + Constructs a route reply object based on \a request, with the specified \a parent. +*/ +QGeoRouteReply::QGeoRouteReply(const QGeoRouteRequest &request, QObject *parent) + : QObject(parent), + d_ptr(new QGeoRouteReplyPrivate(request)) +{ +} + +/*! + Constructs a route reply with a given \a error and \a errorString and the specified \a parent. +*/ +QGeoRouteReply::QGeoRouteReply(Error error, const QString &errorString, QObject *parent) + : QObject(parent), + d_ptr(new QGeoRouteReplyPrivate(error, errorString)) {} + +/*! + Destroys this route reply object. +*/ +QGeoRouteReply::~QGeoRouteReply() +{ + delete d_ptr; +} + +/*! + Sets whether or not this reply has finished to \a finished. + + If \a finished is true, this will cause the finished() signal to be + emitted. + + If the operation completed successfully, QGeoRouteReply::setRoutes() should + be called before this function. If an error occurred, + QGeoRouteReply::setError() should be used instead. +*/ +void QGeoRouteReply::setFinished(bool finished) +{ + d_ptr->isFinished = finished; + if (d_ptr->isFinished) + emit this->finished(); +} + +/*! + Return true if the operation completed successfully or encountered an + error which cause the operation to come to a halt. +*/ +bool QGeoRouteReply::isFinished() const +{ + return d_ptr->isFinished; +} + +/*! + Sets the error state of this reply to \a error and the textual + representation of the error to \a errorString. + + This will also cause error() and finished() signals to be emitted, in that + order. +*/ +void QGeoRouteReply::setError(QGeoRouteReply::Error error, const QString &errorString) +{ + d_ptr->error = error; + d_ptr->errorString = errorString; + emit this->error(error, errorString); + setFinished(true); +} + +/*! + Returns the error state of this reply. + + If the result is QGeoRouteReply::NoError then no error has occurred. +*/ +QGeoRouteReply::Error QGeoRouteReply::error() const +{ + return d_ptr->error; +} + +/*! + Returns the textual representation of the error state of this reply. + + If no error has occurred this will return an empty string. It is possible + that an error occurred which has no associated textual representation, in + which case this will also return an empty string. + + To determine whether an error has occurred, check to see if + QGeoRouteReply::error() is equal to QGeoRouteReply::NoError. +*/ +QString QGeoRouteReply::errorString() const +{ + return d_ptr->errorString; +} + +/*! + Returns the route request which specified the route. +*/ +QGeoRouteRequest QGeoRouteReply::request() const +{ + return d_ptr->request; +} + +/*! + Returns the list of routes which were requested. +*/ +QList QGeoRouteReply::routes() const +{ + return d_ptr->routes; +} + +/*! + Sets the list of routes in the reply to \a routes. +*/ +void QGeoRouteReply::setRoutes(const QList &routes) +{ + d_ptr->routes = routes; +} + +/*! + Appends the list of \a routes to the existing list. +*/ +void QGeoRouteReply::addRoutes(const QList &routes) +{ + d_ptr->routes.append(routes); +} + +/*! + Cancels the operation immediately. + + This will do nothing if the reply is finished. +*/ +void QGeoRouteReply::abort() +{ + if (!isFinished()) + setFinished(true); +} + +/*! + \fn void QGeoRouteReply::finished() + + This signal is emitted when this reply has finished processing. + + If error() equals QGeoRouteReply::NoError then the processing + finished successfully. + + This signal and QGeoRoutingManager::finished() will be + emitted at the same time. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ +/*! + \fn void QGeoRouteReply::error(QGeoRouteReply::Error error, const QString &errorString) + + This signal is emitted when an error has been detected in the processing of + this reply. The finished() signal will probably follow. + + The error will be described by the error code \a error. If \a errorString is + not empty it will contain a textual description of the error. + + This signal and QGeoRoutingManager::error() will be emitted at the same time. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ + +/******************************************************************************* +*******************************************************************************/ + +QGeoRouteReplyPrivate::QGeoRouteReplyPrivate(const QGeoRouteRequest &request) + : error(QGeoRouteReply::NoError), + isFinished(false), + request(request) {} + +QGeoRouteReplyPrivate::QGeoRouteReplyPrivate(QGeoRouteReply::Error error, QString errorString) + : error(error), + errorString(errorString), + isFinished(true) {} + +QGeoRouteReplyPrivate::~QGeoRouteReplyPrivate() {} + +#include "moc_qgeoroutereply.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroutereply.h b/src/location/maps/qgeoroutereply.h new file mode 100644 index 0000000..318d85f --- /dev/null +++ b/src/location/maps/qgeoroutereply.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTEREPLY_H +#define QGEOROUTEREPLY_H + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRouteRequest; +class QGeoRouteReplyPrivate; + +class Q_LOCATION_EXPORT QGeoRouteReply : public QObject +{ + Q_OBJECT +public: + enum Error { + NoError, + EngineNotSetError, + CommunicationError, + ParseError, + UnsupportedOptionError, + UnknownError + }; + + explicit QGeoRouteReply(Error error, const QString &errorString, QObject *parent = Q_NULLPTR); + virtual ~QGeoRouteReply(); + + bool isFinished() const; + Error error() const; + QString errorString() const; + + QGeoRouteRequest request() const; + QList routes() const; + + virtual void abort(); + +Q_SIGNALS: + void finished(); + void error(QGeoRouteReply::Error error, const QString &errorString = QString()); + +protected: + explicit QGeoRouteReply(const QGeoRouteRequest &request, QObject *parent = Q_NULLPTR); + + void setError(Error error, const QString &errorString); + void setFinished(bool finished); + + void setRoutes(const QList &routes); + void addRoutes(const QList &routes); + +private: + QGeoRouteReplyPrivate *d_ptr; + Q_DISABLE_COPY(QGeoRouteReply) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoroutereply_p.h b/src/location/maps/qgeoroutereply_p.h new file mode 100644 index 0000000..496a616 --- /dev/null +++ b/src/location/maps/qgeoroutereply_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTEREPLY_P_H +#define QGEOROUTEREPLY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeorouterequest.h" +#include "qgeoroutereply.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoRoute; + +class QGeoRouteReplyPrivate +{ +public: + explicit QGeoRouteReplyPrivate(const QGeoRouteRequest &request); + QGeoRouteReplyPrivate(QGeoRouteReply::Error error, QString errorString); + ~QGeoRouteReplyPrivate(); + + QGeoRouteReply::Error error; + QString errorString; + bool isFinished; + + QGeoRouteRequest request; + QList routes; + +private: + Q_DISABLE_COPY(QGeoRouteReplyPrivate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeorouterequest.cpp b/src/location/maps/qgeorouterequest.cpp new file mode 100644 index 0000000..369606e --- /dev/null +++ b/src/location/maps/qgeorouterequest.cpp @@ -0,0 +1,486 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeorouterequest.h" +#include "qgeorouterequest_p.h" + +#include "qgeocoordinate.h" +#include "qgeorectangle.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoRouteRequest + \inmodule QtLocation + \ingroup QtLocation-routing + \since 5.6 + + \brief The QGeoRouteRequest class represents the parameters and restrictions + which define a request for routing information. + + The default state of a QGeoRouteRequest instance will result in a request + for basic route segment and navigation maneuvers describing the fastest + route by car which covers the given waypoints. + + There may be significant variation in the features supported by different + providers of routing information, or even in the features supported by + the same provider if different levels of authorization are used. + + There are several functions in QGeoRoutingManager which can be used to + check which features are supported with the current provider and + authorization level. + \sa QGeoRoutingManager +*/ + +/* + DESIGN NOTE + + There are plans to make this extensible by allowing the user to set a + list of QGeoTransportOptions (or QGeoTransitOptions). We don't have any + subclasses for that just yet, otherwise they'd be present. + + A QGeoPublicTransportOption subclass would allow users to specify things + like cost limits, the maximum number of changes of vehicle, the maximum + walking time / distance between changes of vehicle. + + There's Nokia / Navteq support for specifying things like Truck attributes + so you can route around various road restrictions and conditions which + effect trucks. + + A QGeoTrafficAwareTransportOption is probably also a good place to put the + inputs for the various traffic / time aware bits of information. A + departure / arrrival time could be set, and the presence of this transport + options subclass (and the fact that user auth said that the user had + support) would mean we could provide better values for the estimated + travel times and so on. + + This all relies on at least one service making this data available to us, + which would probably be tied to token based authorization. It could be + some time before this becomes available. +*/ + +/*! + \enum QGeoRouteRequest::TravelMode + + Defines modes of travel to be used for a route. + + \value CarTravel + The route will be optimized for someone who is driving a car. + \value PedestrianTravel + The route will be optimized for someone who is walking. + \value BicycleTravel + The route will be optimized for someone who is riding a bicycle. + \value PublicTransitTravel + The route will be optimized for someone who is making use of public transit. + \value TruckTravel + The route will be optimized for someone who is driving a truck. +*/ + +/*! + \enum QGeoRouteRequest::FeatureType + + Defines a feature which is important to the planning of a route. + + These values will be used in combination with + QGeoRouteRequest::FeatureWeight to determine if they should or should + not be part of the route. + + \value NoFeature + Used by QGeoRoutingManager::supportedFeatureTypes() to indicate that + no features will be taken into account when planning the route. + \value TollFeature + Consdier tollways when planning the route. + \value HighwayFeature + Consider highways when planning the route. + \value PublicTransitFeature + Consider public transit when planning the route. + \value FerryFeature + Consider ferries when planning the route. + \value TunnelFeature + Consider tunnels when planning the route. + \value DirtRoadFeature + Consider dirt roads when planning the route. + \value ParksFeature + Consider parks when planning the route. + \value MotorPoolLaneFeature + Consider motor pool lanes when planning the route. +*/ + +/*! + \enum QGeoRouteRequest::FeatureWeight + + Defines the weight to associate with a feature during the + planning of a route. + + These values will be used in combination with + QGeoRouteRequest::Feature to determine if they should or should + not be part of the route. + + \value NeutralFeatureWeight + The presence or absence of the feature will not affect the + planning of the route. + \value PreferFeatureWeight + Routes which contain the feature will be preferred over those that do + not. + \value RequireFeatureWeight + Only routes which contain the feature will be considered, otherwise + no route will be returned. + \value AvoidFeatureWeight + Routes which do not contain the feature will be preferred over those + that do. + \value DisallowFeatureWeight + Only routes which do not contain the feature will be considered, + otherwise no route will be returned. +*/ + +// TODO improve description of MostScenicRoute +/*! + \enum QGeoRouteRequest::RouteOptimization + + Defines the type of optimization which is applied to the planning of the route. + + \value ShortestRoute + Minimize the length of the journey. + \value FastestRoute + Minimize the traveling time for the journey. + \value MostEconomicRoute + Minimize the cost of the journey. + \value MostScenicRoute + Maximize the scenic potential of the journey. +*/ + +/*! + \enum QGeoRouteRequest::SegmentDetail + + Defines the amount of route segment information that should be included + with the route. + + \value NoSegmentData + No segment data should be included with the route. A route requested + with this level of segment detail will initialize + QGeoRouteSegment::path() as a straight line between the positions of + the previous and next QGeoManeuver instances. + + \value BasicSegmentData + Basic segment data will be included with the route. This will include + QGeoRouteSegment::path(). +*/ + +/*! + \enum QGeoRouteRequest::ManeuverDetail + + Defines the amount of maneuver information that should be included with + the route. + + \value NoManeuvers + No maneuvers should be included with the route. + + \value BasicManeuvers + Basic manevuers will be included with the route. This will + include QGeoManeuver::instructionText(). +*/ + +/*! + Constructs a request to calculate a route through the coordinates \a waypoints. + + The route will traverse the objects of \a waypoints in order. +*/ +QGeoRouteRequest::QGeoRouteRequest(const QList &waypoints) + : d_ptr(new QGeoRouteRequestPrivate()) +{ + d_ptr->waypoints = waypoints; +} + +/*! + Constructs a request to calculate a route between \a origin and + \a destination. +*/ +QGeoRouteRequest::QGeoRouteRequest(const QGeoCoordinate &origin, const QGeoCoordinate &destination) + : d_ptr(new QGeoRouteRequestPrivate()) +{ + d_ptr->waypoints.append(origin); + d_ptr->waypoints.append(destination); +} + +/*! + Constructs a route request object from the contents of \a other. +*/ +QGeoRouteRequest::QGeoRouteRequest(const QGeoRouteRequest &other) + : d_ptr(other.d_ptr) {} + +/*! + Destroys the request. +*/ +QGeoRouteRequest::~QGeoRouteRequest() {} + +/*! + Assigns \a other to this route request object and then returns a reference + to this route request object. +*/ +QGeoRouteRequest &QGeoRouteRequest::operator= (const QGeoRouteRequest & other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns whether this route request and \a other are equal. +*/ +bool QGeoRouteRequest::operator ==(const QGeoRouteRequest &other) const +{ + return (d_ptr.constData() == other.d_ptr.constData()); +} + +/*! + Returns whether this route request and \a other are equal. +*/ +bool QGeoRouteRequest::operator !=(const QGeoRouteRequest &other) const +{ + return (d_ptr.constData() != other.d_ptr.constData()); +} + +/*! + Sets \a waypoints as the waypoints that the route should pass through. + + The waypoints should be given in order from origin to destination. + + This request will be invalid until the waypoints have been set to a + list containing two or more coordinates. +*/ +void QGeoRouteRequest::setWaypoints(const QList &waypoints) +{ + d_ptr->waypoints = waypoints; +} + +/*! + Returns the waypoints that the route will pass through. +*/ +QList QGeoRouteRequest::waypoints() const +{ + return d_ptr->waypoints; +} + +/*! + Sets \a areas as excluded areas that the route must not cross. +*/ +void QGeoRouteRequest::setExcludeAreas(const QList &areas) +{ + d_ptr->excludeAreas = areas; +} + +/*! + Returns areas the route must not cross. +*/ +QList QGeoRouteRequest::excludeAreas() const +{ + return d_ptr->excludeAreas; +} + +/*! + Sets the number of alternative routes to request to \a alternatives. If \a alternatives is + negative the number of alternative routes is set to 0. + + The default value is 0. +*/ +void QGeoRouteRequest::setNumberAlternativeRoutes(int alternatives) +{ + d_ptr->numberAlternativeRoutes = qMax(0, alternatives); +} + +/*! + Returns the number of alternative routes which will be requested. +*/ +int QGeoRouteRequest::numberAlternativeRoutes() const +{ + return d_ptr->numberAlternativeRoutes; +} + +/*! + Sets the travel modes which should be considered during the planning of the + route to \a travelModes. + + The default value is QGeoRouteRequest::CarTravel. +*/ +void QGeoRouteRequest::setTravelModes(QGeoRouteRequest::TravelModes travelModes) +{ + d_ptr->travelModes = travelModes; +} + +/*! + Returns the travel modes which this request specifies should be considered + during the planning of the route. +*/ +QGeoRouteRequest::TravelModes QGeoRouteRequest::travelModes() const +{ + return d_ptr->travelModes; +} + +/*! + Assigns the weight \a featureWeight to the feature \a featureType during + the planning of the route. + + By default all features are assigned a weight of NeutralFeatureWeight. + + It is impossible to assign a weight to QGeoRouteRequest::NoFeature. +*/ +void QGeoRouteRequest::setFeatureWeight(QGeoRouteRequest::FeatureType featureType, QGeoRouteRequest::FeatureWeight featureWeight) +{ + if (featureWeight != QGeoRouteRequest::NeutralFeatureWeight) { + if (featureType != QGeoRouteRequest::NoFeature) + d_ptr->featureWeights[featureType] = featureWeight; + } else { + d_ptr->featureWeights.remove(featureType); + } +} + +/*! + Returns the weight assigned to \a featureType in the planning of the route. + + If no feature weight has been specified for \a featureType then + NeutralFeatureWeight will be returned. +*/ +QGeoRouteRequest::FeatureWeight QGeoRouteRequest::featureWeight(QGeoRouteRequest::FeatureType featureType) const +{ + return d_ptr->featureWeights.value(featureType, QGeoRouteRequest::NeutralFeatureWeight); +} + +/*! + Returns the list of features that will be considered when planning the + route. Features with a weight of NeutralFeatureWeight will not be returned. +*/ +QList QGeoRouteRequest::featureTypes() const +{ + return d_ptr->featureWeights.keys(); +} + +/*! + Sets the optimization criteria to use while planning the route to + \a optimization. + + The default value is QGeoRouteRequest::FastestRoute. +*/ +void QGeoRouteRequest::setRouteOptimization(QGeoRouteRequest::RouteOptimizations optimization) +{ + d_ptr->routeOptimization = optimization; +} + +/*! + Returns the optimization criteria which this request specifies should be + used while planning the route. +*/ +QGeoRouteRequest::RouteOptimizations QGeoRouteRequest::routeOptimization() const +{ + return d_ptr->routeOptimization; +} + +/*! + Sets the level of detail to use when representing routing segments to + \a segmentDetail. +*/ +void QGeoRouteRequest::setSegmentDetail(QGeoRouteRequest::SegmentDetail segmentDetail) +{ + d_ptr->segmentDetail = segmentDetail; +} + +/*! + Returns the level of detail which will be used in the representation of + routing segments. +*/ +QGeoRouteRequest::SegmentDetail QGeoRouteRequest::segmentDetail() const +{ + return d_ptr->segmentDetail; +} + +/*! + Sets the level of detail to use when representing routing maneuvers to + \a maneuverDetail. + + The default value is QGeoRouteRequest::BasicManeuvers. +*/ +void QGeoRouteRequest::setManeuverDetail(QGeoRouteRequest::ManeuverDetail maneuverDetail) +{ + d_ptr->maneuverDetail = maneuverDetail; +} + +/*! + Returns the level of detail which will be used in the representation of + routing maneuvers. +*/ +QGeoRouteRequest::ManeuverDetail QGeoRouteRequest::maneuverDetail() const +{ + return d_ptr->maneuverDetail; +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoRouteRequestPrivate::QGeoRouteRequestPrivate() + : QSharedData(), + numberAlternativeRoutes(0), + travelModes(QGeoRouteRequest::CarTravel), + routeOptimization(QGeoRouteRequest::FastestRoute), + segmentDetail(QGeoRouteRequest::BasicSegmentData), + maneuverDetail(QGeoRouteRequest::BasicManeuvers) {} + +QGeoRouteRequestPrivate::QGeoRouteRequestPrivate(const QGeoRouteRequestPrivate &other) + : QSharedData(other), + waypoints(other.waypoints), + excludeAreas(other.excludeAreas), + numberAlternativeRoutes(other.numberAlternativeRoutes), + travelModes(other.travelModes), + featureWeights(other.featureWeights), + routeOptimization(other.routeOptimization), + segmentDetail(other.segmentDetail), + maneuverDetail(other.maneuverDetail) {} + +QGeoRouteRequestPrivate::~QGeoRouteRequestPrivate() {} + +bool QGeoRouteRequestPrivate::operator ==(const QGeoRouteRequestPrivate &other) const +{ + return ((waypoints == other.waypoints) + && (excludeAreas == other.excludeAreas) + && (numberAlternativeRoutes == other.numberAlternativeRoutes) + && (travelModes == other.travelModes) + && (featureWeights == other.featureWeights) + && (routeOptimization == other.routeOptimization) + && (segmentDetail == other.segmentDetail) + && (maneuverDetail == other.maneuverDetail)); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeorouterequest.h b/src/location/maps/qgeorouterequest.h new file mode 100644 index 0000000..1692bbb --- /dev/null +++ b/src/location/maps/qgeorouterequest.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTEREQUEST_H +#define QGEOROUTEREQUEST_H + +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRectangle; +class QGeoRouteRequestPrivate; + +class Q_LOCATION_EXPORT QGeoRouteRequest +{ +public: + enum TravelMode { + CarTravel = 0x0001, + PedestrianTravel = 0x0002, + BicycleTravel = 0x0004, + PublicTransitTravel = 0x0008, + TruckTravel = 0x0010 + }; + Q_DECLARE_FLAGS(TravelModes, TravelMode) + + enum FeatureType { + NoFeature = 0x00000000, + TollFeature = 0x00000001, + HighwayFeature = 0x00000002, + PublicTransitFeature = 0x00000004, + FerryFeature = 0x00000008, + TunnelFeature = 0x00000010, + DirtRoadFeature = 0x00000020, + ParksFeature = 0x00000040, + MotorPoolLaneFeature = 0x00000080 + }; + Q_DECLARE_FLAGS(FeatureTypes, FeatureType) + + enum FeatureWeight { + NeutralFeatureWeight = 0x00000000, + PreferFeatureWeight = 0x00000001, + RequireFeatureWeight = 0x00000002, + AvoidFeatureWeight = 0x00000004, + DisallowFeatureWeight = 0x00000008 + }; + Q_DECLARE_FLAGS(FeatureWeights, FeatureWeight) + + enum RouteOptimization { + ShortestRoute = 0x0001, + FastestRoute = 0x0002, + MostEconomicRoute = 0x0004, + MostScenicRoute = 0x0008 + }; + Q_DECLARE_FLAGS(RouteOptimizations, RouteOptimization) + + enum SegmentDetail { + NoSegmentData = 0x0000, + BasicSegmentData = 0x0001 + }; + Q_DECLARE_FLAGS(SegmentDetails, SegmentDetail) + + enum ManeuverDetail { + NoManeuvers = 0x0000, + BasicManeuvers = 0x0001 + }; + Q_DECLARE_FLAGS(ManeuverDetails, ManeuverDetail) + + explicit QGeoRouteRequest(const QList &waypoints = QList()); + QGeoRouteRequest(const QGeoCoordinate &origin, + const QGeoCoordinate &destination); + QGeoRouteRequest(const QGeoRouteRequest &other); + + ~QGeoRouteRequest(); + + QGeoRouteRequest &operator= (const QGeoRouteRequest &other); + + bool operator == (const QGeoRouteRequest &other) const; + bool operator != (const QGeoRouteRequest &other) const; + + void setWaypoints(const QList &waypoints); + QList waypoints() const; + + void setExcludeAreas(const QList &areas); + QList excludeAreas() const; + + // defaults to 0 + void setNumberAlternativeRoutes(int alternatives); + int numberAlternativeRoutes() const; + + // defaults to TravelByCar + void setTravelModes(TravelModes travelModes); + TravelModes travelModes() const; + + void setFeatureWeight(FeatureType featureType, FeatureWeight featureWeight); + FeatureWeight featureWeight(FeatureType featureType) const; + QList featureTypes() const; + + // defaults to OptimizeFastest + void setRouteOptimization(RouteOptimizations optimization); + RouteOptimizations routeOptimization() const; + + // defaults to BasicSegmentData + void setSegmentDetail(SegmentDetail segmentDetail); + SegmentDetail segmentDetail() const; + + // defaults to BasicManeuvers + void setManeuverDetail(ManeuverDetail maneuverDetail); + ManeuverDetail maneuverDetail() const; + +private: + QExplicitlySharedDataPointer d_ptr; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoRouteRequest::TravelModes) +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoRouteRequest::FeatureTypes) +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoRouteRequest::FeatureWeights) +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoRouteRequest::RouteOptimizations) +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoRouteRequest::SegmentDetails) +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoRouteRequest::ManeuverDetails) + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeorouterequest_p.h b/src/location/maps/qgeorouterequest_p.h new file mode 100644 index 0000000..ea0b142 --- /dev/null +++ b/src/location/maps/qgeorouterequest_p.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTEREQUEST_P_H +#define QGEOROUTEREQUEST_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeorouterequest.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRouteRequestPrivate : public QSharedData +{ +public: + QGeoRouteRequestPrivate(); + QGeoRouteRequestPrivate(const QGeoRouteRequestPrivate &other); + ~QGeoRouteRequestPrivate(); + + bool operator ==(const QGeoRouteRequestPrivate &other) const; + + QList waypoints; + QList excludeAreas; + int numberAlternativeRoutes; + QGeoRouteRequest::TravelModes travelModes; + QMap < QGeoRouteRequest::FeatureType, + QGeoRouteRequest::FeatureWeight > featureWeights; + QGeoRouteRequest::RouteOptimizations routeOptimization; + QGeoRouteRequest::SegmentDetail segmentDetail; + QGeoRouteRequest::ManeuverDetail maneuverDetail; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoroutesegment.cpp b/src/location/maps/qgeoroutesegment.cpp new file mode 100644 index 0000000..45c2cc6 --- /dev/null +++ b/src/location/maps/qgeoroutesegment.cpp @@ -0,0 +1,275 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroutesegment.h" +#include "qgeoroutesegment_p.h" + +#include "qgeocoordinate.h" +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoRouteSegment + \inmodule QtLocation + \ingroup QtLocation-routing + \since 5.6 + + \brief The QGeoRouteSegment class represents a segment of a route. + + A QGeoRouteSegment instance has information about the physical layout + of the route segment, the length of the route and estimated time required + to traverse the route segment and an optional QGeoManeuver associated with + the end of the route segment. + + QGeoRouteSegment instances can be thought of as edges on a routing + graph, with QGeoManeuver instances as optional labels attached to the + vertices of the graph. +*/ + +/*! + Constructs an invalid route segment object. + + The route segment will remain invalid until one of setNextRouteSegment(), + setTravelTime(), setDistance(), setPath() or setManeuver() is called. +*/ +QGeoRouteSegment::QGeoRouteSegment() + : d_ptr(new QGeoRouteSegmentPrivate()) {} + +/*! + Constructs a route segment object from the contents of \a other. +*/ +QGeoRouteSegment::QGeoRouteSegment(const QGeoRouteSegment &other) + : d_ptr(other.d_ptr) {} + +/*! + \internal +*/ +QGeoRouteSegment::QGeoRouteSegment(QExplicitlySharedDataPointer &d_ptr) + : d_ptr(d_ptr) {} + +/*! + Destroys this route segment object. +*/ +QGeoRouteSegment::~QGeoRouteSegment() {} + + +/*! + Assigns \a other to this route segment object and then returns a + reference to this route segment object. +*/ +QGeoRouteSegment &QGeoRouteSegment::operator= (const QGeoRouteSegment & other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns whether this route segment and \a other are equal. + + The value of nextRouteSegment() is not considered in the comparison. +*/ +bool QGeoRouteSegment::operator ==(const QGeoRouteSegment &other) const +{ + return ( (d_ptr.constData() == other.d_ptr.constData()) + || (*d_ptr) == (*other.d_ptr)); +} + +/*! + Returns whether this route segment and \a other are not equal. + + The value of nextRouteSegment() is not considered in the comparison. +*/ +bool QGeoRouteSegment::operator !=(const QGeoRouteSegment &other) const +{ + return !(operator==(other)); +} + +/*! + Returns whether this route segment is valid or not. + + If nextRouteSegment() is called on the last route segment of a route, the + returned value will be an invalid route segment. +*/ +bool QGeoRouteSegment::isValid() const +{ + return d_ptr->valid; +} + +/*! + Sets the next route segment in the route to \a routeSegment. +*/ +void QGeoRouteSegment::setNextRouteSegment(const QGeoRouteSegment &routeSegment) +{ + d_ptr->valid = true; + d_ptr->nextSegment = routeSegment.d_ptr; +} + +/*! + Returns the next route segment in the route. + + Will return an invalid route segment if this is the last route + segment in the route. +*/ +QGeoRouteSegment QGeoRouteSegment::nextRouteSegment() const +{ + if (d_ptr->valid && d_ptr->nextSegment) + return QGeoRouteSegment(d_ptr->nextSegment); + + QGeoRouteSegment segment; + segment.d_ptr->valid = false; + return segment; +} + +/*! + Sets the estimated amount of time it will take to traverse this segment of + the route, in seconds, to \a secs. +*/ +void QGeoRouteSegment::setTravelTime(int secs) +{ + d_ptr->valid = true; + d_ptr->travelTime = secs; +} + +/*! + Returns the estimated amount of time it will take to traverse this segment + of the route, in seconds. +*/ +int QGeoRouteSegment::travelTime() const +{ + return d_ptr->travelTime; +} + +/*! + Sets the distance covered by this segment of the route, in meters, to \a distance. +*/ +void QGeoRouteSegment::setDistance(qreal distance) +{ + d_ptr->valid = true; + d_ptr->distance = distance; +} + +/*! + Returns the distance covered by this segment of the route, in meters. +*/ +qreal QGeoRouteSegment::distance() const +{ + return d_ptr->distance; +} + +/*! + Sets the geometric shape of this segment of the route to \a path. + + The coordinates in \a path should be listed in the order in which they + would be traversed by someone traveling along this segment of the route. +*/ +void QGeoRouteSegment::setPath(const QList &path) +{ + d_ptr->valid = true; + d_ptr->path = path; +} + +/*! + Returns the geometric shape of this route segment of the route. + + The coordinates should be listed in the order in which they + would be traversed by someone traveling along this segment of the route. +*/ + +QList QGeoRouteSegment::path() const +{ + return d_ptr->path; +} + +/*! + Sets the maneuver for this route segment to \a maneuver. +*/ +void QGeoRouteSegment::setManeuver(const QGeoManeuver &maneuver) +{ + d_ptr->valid = true; + d_ptr->maneuver = maneuver; +} + +/*! + Returns the maneuver for this route segment. + + Will return an invalid QGeoManeuver if no information has been attached + to the endpoint of this route segment. +*/ +QGeoManeuver QGeoRouteSegment::maneuver() const +{ + return d_ptr->maneuver; +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoRouteSegmentPrivate::QGeoRouteSegmentPrivate() + : valid(false), + travelTime(0), + distance(0.0) {} + +QGeoRouteSegmentPrivate::QGeoRouteSegmentPrivate(const QGeoRouteSegmentPrivate &other) + : QSharedData(other), + valid(other.valid), + travelTime(other.travelTime), + distance(other.distance), + path(other.path), + maneuver(other.maneuver), + nextSegment(other.nextSegment) {} + +QGeoRouteSegmentPrivate::~QGeoRouteSegmentPrivate() +{ + nextSegment.reset(); +} + +bool QGeoRouteSegmentPrivate::operator ==(const QGeoRouteSegmentPrivate &other) const +{ + return ((valid == other.valid) + && (travelTime == other.travelTime) + && (distance == other.distance) + && (path == other.path) + && (maneuver == other.maneuver)); +} + +/******************************************************************************* +*******************************************************************************/ + +QT_END_NAMESPACE + diff --git a/src/location/maps/qgeoroutesegment.h b/src/location/maps/qgeoroutesegment.h new file mode 100644 index 0000000..bddc172 --- /dev/null +++ b/src/location/maps/qgeoroutesegment.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTESEGMENT_H +#define QGEOROUTESEGMENT_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; +class QGeoManeuver; +class QGeoRouteSegmentPrivate; + +class Q_LOCATION_EXPORT QGeoRouteSegment +{ + +public: + QGeoRouteSegment(); + QGeoRouteSegment(const QGeoRouteSegment &other); + ~QGeoRouteSegment(); + + QGeoRouteSegment &operator= (const QGeoRouteSegment &other); + + bool operator ==(const QGeoRouteSegment &other) const; + bool operator !=(const QGeoRouteSegment &other) const; + + bool isValid() const; + + void setNextRouteSegment(const QGeoRouteSegment &routeSegment); + QGeoRouteSegment nextRouteSegment() const; + + void setTravelTime(int secs); + int travelTime() const; + + void setDistance(qreal distance); + qreal distance() const; + + void setPath(const QList &path); + QList path() const; + + void setManeuver(const QGeoManeuver &maneuver); + QGeoManeuver maneuver() const; + +protected: + QGeoRouteSegment(QExplicitlySharedDataPointer &d_ptr); + +private: + QExplicitlySharedDataPointer d_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoroutesegment_p.h b/src/location/maps/qgeoroutesegment_p.h new file mode 100644 index 0000000..1751266 --- /dev/null +++ b/src/location/maps/qgeoroutesegment_p.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTESEGMENT_P_H +#define QGEOROUTESEGMENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeomaneuver.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; + +class QGeoRouteSegmentPrivate : public QSharedData +{ +public: + QGeoRouteSegmentPrivate(); + QGeoRouteSegmentPrivate(const QGeoRouteSegmentPrivate &other); + ~QGeoRouteSegmentPrivate(); + + bool operator ==(const QGeoRouteSegmentPrivate &other) const; + + bool valid; + + int travelTime; + qreal distance; + QList path; + QGeoManeuver maneuver; + + QExplicitlySharedDataPointer nextSegment; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoroutingmanager.cpp b/src/location/maps/qgeoroutingmanager.cpp new file mode 100644 index 0000000..8eca671 --- /dev/null +++ b/src/location/maps/qgeoroutingmanager.cpp @@ -0,0 +1,413 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroutingmanager.h" +#include "qgeoroutingmanager_p.h" +#include "qgeoroutingmanagerengine.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoRoutingManager + \inmodule QtLocation + \ingroup QtLocation-routing + \since 5.6 + + \brief The QGeoRoutingManager class provides support for geographic routing + operations. + + The calculateRoute() and updateRoute() methods function QGeoRouteReply + objects, which manage these operations and report on the result of the + operations and any errors which may have occurred. + + The calculateRoute() function is used to find a route (or routes) that + follows a set of waypoints and matches various other criteria. The + QGeoRouteRequest class is used to specify this information. + + If supportsRouteUpdates() returns true then the QGeoRoutingManager + supports updating route information based on position updates. This + will cause the travel time and distance estimates to be updated, and + any QGeoRouteSegments already traversed to be removed from the route. + + The updates can be triggered with the updateRoute() function, which makes + use of the QGeoPositionInfo instances emitted as position updates by + QGeoPositionInfoSource. + + Instances of QGeoRoutingManager can be accessed with + QGeoServiceProvider::routingManager(). + + A small example of the usage of QGeoRoutingManager and QGeoRouteRequests + follows: + + \code +class MyRouteHandler : public QObject +{ + Q_OBJECT +public: + MyRouteHandler(QGeoRoutingManager *routingManager, + const QGeoCoordinate &origin, + const QGeoCoordinate &destination) { + + QGeoRouteRequest request(origin, destination); + + // The request defaults to the fastest route by car, which is + // equivalent to: + // request.setTravelMode(QGeoRouteRequest::CarTravel); + // request.setRouteOptimization(QGeoRouteRequest::FastestRoute); + + request.setAvoidFeatureTypes(QGeoRouteRequest::AvoidTolls); + request.setAvoidFeatureTypes(QGeoRouteRequest::AvoidMotorPoolLanes); + + QGeoRouteRequest::AvoidFeaturesTypes avoidableFeatures = routingManager->supportedAvoidFeatureTypes(); + + if (!(avoidableFeatures & request.avoidFeatureTypes())) { + // ... inform the user that the routing manager does not + // provide support for avoiding tolls and/or motor pool lanes ... + return; + } + + QGeoRouteReply *reply = routingManager->calculateRoute(request); + + if (reply->isFinished()) { + if (reply->error() == QGeoRouteReply::NoError) { + routeCalculated(reply); + } else { + routeError(reply, reply->error(), reply->errorString()); + } + return; + } + + connect(routingManager, + SIGNAL(finished(QGeoRouteReply*)), + this, + SLOT(routeCalculated(QGeoRouteReply*))); + + connect(routingManager, + SIGNAL(error(QGeoRouteReply*,QGeoRouteReply::Error,QString)), + this, + SLOT(routeError(QGeoRouteReply*,QGeoRouteReply::Error,QString))); + } + +private slots: + void routeCalculated(QGeoRouteReply *reply) + { + // A route request can ask for several alternative routes ... + if (reply->routes().size() != 0) { + + // ... but by default it will only get a single route + QGeoRoute route = reply->routes().at(0); + + //... now we have to make use of the route ... + } + + reply->deleteLater(); + } + + void routeError(QGeoRouteReply *reply, QGeoRouteReply:Error error, const QString &errorString) + { + // ... inform the user that an error has occurred ... + reply->deleteLater(); + } +}; + \endcode +*/ + +/*! + Constructs a new manager with the specified \a parent and with the + implementation provided by \a engine. + + This constructor is used internally by QGeoServiceProviderFactory. Regular + users should acquire instances of QGeoRoutingManager with + QGeoServiceProvider::routingManager(); +*/ +QGeoRoutingManager::QGeoRoutingManager(QGeoRoutingManagerEngine *engine, QObject *parent) + : QObject(parent), + d_ptr(new QGeoRoutingManagerPrivate()) +{ + d_ptr->engine = engine; + if (d_ptr->engine) { + d_ptr->engine->setParent(this); + + connect(d_ptr->engine, + SIGNAL(finished(QGeoRouteReply*)), + this, + SIGNAL(finished(QGeoRouteReply*))); + + connect(d_ptr->engine, + SIGNAL(error(QGeoRouteReply*,QGeoRouteReply::Error,QString)), + this, + SIGNAL(error(QGeoRouteReply*,QGeoRouteReply::Error,QString))); + } else { + qFatal("The routing manager engine that was set for this routing manager was NULL."); + } +} + +/*! + Destroys this manager. +*/ +QGeoRoutingManager::~QGeoRoutingManager() +{ + delete d_ptr; +} + +/*! + Returns the name of the engine which implements the behaviour of this + routing manager. + + The combination of managerName() and managerVersion() should be unique + amongst the plugin implementations. +*/ +QString QGeoRoutingManager::managerName() const +{ + return d_ptr->engine->managerName(); +} + +/*! + Returns the version of the engine which implements the behaviour of this + routin manager. + + The combination of managerName() and managerVersion() should be unique + amongst the plugin implementations. +*/ +int QGeoRoutingManager::managerVersion() const +{ + return d_ptr->engine->managerVersion(); +} + +/*! + Begins the calculation of the route specified by \a request. + + A QGeoRouteReply object will be returned, which can be used to manage the + routing operation and to return the results of the operation. + + This manager and the returned QGeoRouteReply object will emit signals + indicating if the operation completes or if errors occur. + + Once the operation has completed, QGeoRouteReply::routes can be used to + retrieve the calculated route or routes. + + If \a request includes features which are not supported by this manager, as + reported by the methods in this manager, then a + QGeoRouteReply::UnsupportedOptionError will occur. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoRoutingManager::finished(), + QGeoRoutingManager::error(), QGeoRouteReply::finished() or + QGeoRouteReply::error() with deleteLater(). +*/ +QGeoRouteReply *QGeoRoutingManager::calculateRoute(const QGeoRouteRequest &request) +{ + return d_ptr->engine->calculateRoute(request); +} + +/*! + Begins the process of updating \a route based on the current position \a + position. + + A QGeoRouteReply object will be returned, which can be used to manage the + routing operation and to return the results of the operation. + + This manager and the returned QGeoRouteReply object will emit signals + indicating if the operation completes or if errors occur. + + If supportsRouteUpdates() returns false an + QGeoRouteReply::UnsupportedOptionError will occur. + + Once the operation has completed, QGeoRouteReply::routes can be used to + retrieve the updated route. + + The returned route could be entirely different to the original route, + especially if \a position is far away from the initial route. + Otherwise the route will be similar, although the remaining time and + distance will be updated and any segments of the original route which + have been traversed will be removed. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoRoutingManager::finished(), + QGeoRoutingManager::error(), QGeoRouteReply::finished() or + QGeoRouteReply::error() with deleteLater(). +*/ +QGeoRouteReply *QGeoRoutingManager::updateRoute(const QGeoRoute &route, const QGeoCoordinate &position) +{ + return d_ptr->engine->updateRoute(route, position); +} + +/*! + Returns the travel modes supported by this manager. +*/ +QGeoRouteRequest::TravelModes QGeoRoutingManager::supportedTravelModes() const +{ + return d_ptr->engine->supportedTravelModes(); +} + +/*! + Returns the types of features that this manager can take into account + during route planning. +*/ +QGeoRouteRequest::FeatureTypes QGeoRoutingManager::supportedFeatureTypes() const +{ + return d_ptr->engine->supportedFeatureTypes(); +} + +/*! + Returns the weightings which this manager can apply to different features + during route planning. +*/ +QGeoRouteRequest::FeatureWeights QGeoRoutingManager::supportedFeatureWeights() const +{ + return d_ptr->engine->supportedFeatureWeights(); +} + +/*! + Returns the route optimizations supported by this manager. +*/ +QGeoRouteRequest::RouteOptimizations QGeoRoutingManager::supportedRouteOptimizations() const +{ + return d_ptr->engine->supportedRouteOptimizations(); +} + +/*! + Returns the levels of detail for routing segments which can be requested + with this manager. +*/ +QGeoRouteRequest::SegmentDetails QGeoRoutingManager::supportedSegmentDetails() const +{ + return d_ptr->engine->supportedSegmentDetails(); +} + +/*! + Returns the levels of detail for navigation maneuvers which can be + requested by this manager. +*/ +QGeoRouteRequest::ManeuverDetails QGeoRoutingManager::supportedManeuverDetails() const +{ + return d_ptr->engine->supportedManeuverDetails(); +} + +/*! + Sets the locale to be used by this manager to \a locale. + + If this routing manager supports returning addresses and instructions + in different languages, they will be returned in the language of \a locale. + + The locale used defaults to the system locale if this is not set. +*/ +void QGeoRoutingManager::setLocale(const QLocale &locale) +{ + d_ptr->engine->setLocale(locale); +} + +/*! + Returns the locale used to hint to this routing manager about what + language to use for addresses and instructions. +*/ +QLocale QGeoRoutingManager::locale() const +{ + return d_ptr->engine->locale(); +} + +/*! + Sets the measurement system used by this manager to \a system. + + The measurement system can be set independently of the locale. Both setLocale() and this + function set the measurement system. The value set by the last function called will be used. + + \sa measurementSystem(), locale(), setLocale() +*/ +void QGeoRoutingManager::setMeasurementSystem(QLocale::MeasurementSystem system) +{ + d_ptr->engine->setMeasurementSystem(system); +} + +/*! + Returns the measurement system used by this manager. + + If setMeasurementSystem() has been called then the value returned by this function may be + different to that returned by locale().\l {QLocale::measurementSystem()}{measurementSystem()}. + In which case the value returned by this function is what will be used by the manager. + + \sa setMeasurementSystem(), setLocale() +*/ +QLocale::MeasurementSystem QGeoRoutingManager::measurementSystem() const +{ + return d_ptr->engine->measurementSystem(); +} + +/*! +\fn void QGeoRoutingManager::finished(QGeoRouteReply *reply) + +This signal is emitted when \a reply has finished processing. + +If reply::error() equals QGeoRouteReply::NoError then the processing +finished successfully. + +This signal and QGeoRouteReply::finished() will be emitted at the same time. + +\note Do not delete the \a reply object in the slot connected to this signal. +Use deleteLater() instead. +*/ + +/*! +\fn void QGeoRoutingManager::error(QGeoRouteReply *reply, QGeoRouteReply::Error error, QString errorString) + +This signal is emitted when an error has been detected in the processing of +\a reply. The QGeoRoutingManager::finished() signal will probably follow. + +The error will be described by the error code \a error. If \a errorString is +not empty it will contain a textual description of the error. + +This signal and QGeoRouteReply::error() will be emitted at the same time. + +\note Do not delete the \a reply object in the slot connected to this signal. +Use deleteLater() instead. +*/ + +/******************************************************************************* +*******************************************************************************/ + +QGeoRoutingManagerPrivate::QGeoRoutingManagerPrivate() + : engine(0) {} + +QGeoRoutingManagerPrivate::~QGeoRoutingManagerPrivate() +{ + delete engine; +} + +#include "moc_qgeoroutingmanager.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroutingmanager.h b/src/location/maps/qgeoroutingmanager.h new file mode 100644 index 0000000..56cd8e5 --- /dev/null +++ b/src/location/maps/qgeoroutingmanager.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTINGMANAGER_H +#define QGEOROUTINGMANAGER_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRoutingManagerEngine; +class QGeoRoutingManagerPrivate; + +class Q_LOCATION_EXPORT QGeoRoutingManager : public QObject +{ + Q_OBJECT + +public: + ~QGeoRoutingManager(); + + QString managerName() const; + int managerVersion() const; + + QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request); + QGeoRouteReply *updateRoute(const QGeoRoute &route, const QGeoCoordinate &position); + + QGeoRouteRequest::TravelModes supportedTravelModes() const; + QGeoRouteRequest::FeatureTypes supportedFeatureTypes() const; + QGeoRouteRequest::FeatureWeights supportedFeatureWeights() const; + QGeoRouteRequest::RouteOptimizations supportedRouteOptimizations() const; + QGeoRouteRequest::SegmentDetails supportedSegmentDetails() const; + QGeoRouteRequest::ManeuverDetails supportedManeuverDetails() const; + + void setLocale(const QLocale &locale); + QLocale locale() const; + void setMeasurementSystem(QLocale::MeasurementSystem system); + QLocale::MeasurementSystem measurementSystem() const; + +Q_SIGNALS: + void finished(QGeoRouteReply *reply); + void error(QGeoRouteReply *reply, QGeoRouteReply::Error error, QString errorString = QString()); + +private: + explicit QGeoRoutingManager(QGeoRoutingManagerEngine *engine, QObject *parent = Q_NULLPTR); + + QGeoRoutingManagerPrivate *d_ptr; + Q_DISABLE_COPY(QGeoRoutingManager) + + friend class QGeoServiceProvider; + friend class QGeoServiceProviderPrivate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoroutingmanager_p.h b/src/location/maps/qgeoroutingmanager_p.h new file mode 100644 index 0000000..b3a9f2f --- /dev/null +++ b/src/location/maps/qgeoroutingmanager_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTINGMANAGER_P_H +#define QGEOROUTINGMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class QGeoRoutingManagerEngine; + +class QGeoRoutingManagerPrivate +{ +public: + QGeoRoutingManagerPrivate(); + ~QGeoRoutingManagerPrivate(); + + QGeoRoutingManagerEngine *engine; + +private: + Q_DISABLE_COPY(QGeoRoutingManagerPrivate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoroutingmanagerengine.cpp b/src/location/maps/qgeoroutingmanagerengine.cpp new file mode 100644 index 0000000..9c55268 --- /dev/null +++ b/src/location/maps/qgeoroutingmanagerengine.cpp @@ -0,0 +1,425 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroutingmanagerengine.h" +#include "qgeoroutingmanagerengine_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoRoutingManagerEngine + \inmodule QtLocation + \ingroup QtLocation-impl + \since 5.6 + + \brief The QGeoRoutingManagerEngine class provides an interface and + convenience methods to implementers of QGeoServiceProvider plugins who want + to provide access to geographic routing information. + + Subclasses of QGeoRoutingManagerEngine need to provide an implementation of + calculateRoute(). + + In the default implementation, supportsRouteUpdates() returns false and + updateRoute() returns a QGeoRouteReply object containing a + QGeoRouteReply::UnsupportedOptionError. + + If the routing service supports updating routes as they are being + traveled, the subclass should provide an implementation of updateRoute() + and call setSupportsRouteUpdates(true) at some point in time before + updateRoute() is called. + + The function setSupportsRouteUpdates() is one of several functions which + configure the reported capabilities of the engine. If the capabilities + of an engine differ from the default values these functions should be + used so that the reported capabilities are accurate. + + It is important that this is done before calculateRoute(), updateRoute() + or any of the capability reporting functions are used to prevent + incorrect or inconsistent behavior. + + A subclass of QGeoRouteManagerEngine will often make use of a subclass + fo QGeoRouteReply internally, in order to add any engine-specific + data (such as a QNetworkReply object for network-based services) to the + QGeoRouteReply instances used by the engine. + + \sa QGeoRoutingManager +*/ + +/*! + Constructs a new engine with the specified \a parent, using \a parameters + to pass any implementation specific data to the engine. +*/ +QGeoRoutingManagerEngine::QGeoRoutingManagerEngine(const QVariantMap ¶meters, QObject *parent) + : QObject(parent), + d_ptr(new QGeoRoutingManagerEnginePrivate()) +{ + Q_UNUSED(parameters) +} + +/*! + Destroys this engine. +*/ +QGeoRoutingManagerEngine::~QGeoRoutingManagerEngine() +{ + delete d_ptr; +} + +/*! + Sets the name which this engine implementation uses to distinguish itself + from the implementations provided by other plugins to \a managerName. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +void QGeoRoutingManagerEngine::setManagerName(const QString &managerName) +{ + d_ptr->managerName = managerName; +} + +/*! + Returns the name which this engine implementation uses to distinguish + itself from the implementations provided by other plugins. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +QString QGeoRoutingManagerEngine::managerName() const +{ + return d_ptr->managerName; +} + +/*! + Sets the version of this engine implementation to \a managerVersion. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +void QGeoRoutingManagerEngine::setManagerVersion(int managerVersion) +{ + d_ptr->managerVersion = managerVersion; +} + +/*! + Returns the version of this engine implementation. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +int QGeoRoutingManagerEngine::managerVersion() const +{ + return d_ptr->managerVersion; +} + +/*! +\fn QGeoRouteReply *QGeoRoutingManagerEngine::calculateRoute(const QGeoRouteRequest &request) + + Begins the calculation of the route specified by \a request. + + A QGeoRouteReply object will be returned, which can be used to manage the + routing operation and to return the results of the operation. + + This engine and the returned QGeoRouteReply object will emit signals + indicating if the operation completes or if errors occur. + + Once the operation has completed, QGeoRouteReply::routes can be used to + retrieve the calculated route or routes. + + If \a request includes features which are not supported by this engine, as + reported by the methods in this engine, then a + QGeoRouteReply::UnsupportedOptionError will occur. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoRoutingManagerEngine::finished(), + QGeoRoutingManagerEngine::error(), QGeoRouteReply::finished() or + QGeoRouteReply::error() with deleteLater(). +*/ + +/*! + Begins the process of updating \a route based on the current position \a + position. + + A QGeoRouteReply object will be returned, which can be used to manage the + routing operation and to return the results of the operation. + + This engine and the returned QGeoRouteReply object will emit signals + indicating if the operation completes or if errors occur. + + If supportsRouteUpdates() returns false an + QGeoRouteReply::UnsupportedOptionError will occur. + + Once the operation has completed, QGeoRouteReply::routes can be used to + retrieve the updated route. + + The returned route could be entirely different to the original route, + especially if \a position is far enough away from the initial route. + Otherwise the route will be similar, although the remaining time and + distance will be updated and any segments of the original route which + have been traversed will be removed. + + The user is responsible for deleting the returned reply object, although + this can be done in the slot connected to QGeoRoutingManagerEngine::finished(), + QGeoRoutingManagerEngine::error(), QGeoRouteReply::finished() or + QGeoRouteReply::error() with deleteLater(). +*/ +QGeoRouteReply *QGeoRoutingManagerEngine::updateRoute(const QGeoRoute &route, const QGeoCoordinate &position) +{ + Q_UNUSED(route) + Q_UNUSED(position) + return new QGeoRouteReply(QGeoRouteReply::UnsupportedOptionError, + QLatin1String("The updating of routes is not supported by this service provider."), this); +} + +/*! + Sets the travel modes supported by this engine to \a travelModes. + + It is important that subclasses use this method to ensure that the engine + reports its capabilities correctly. If this function is not used the + engine will report that it supports no travel modes at all. +*/ +void QGeoRoutingManagerEngine::setSupportedTravelModes(QGeoRouteRequest::TravelModes travelModes) +{ + d_ptr->supportedTravelModes = travelModes; +} + +/*! + Returns the travel modes supported by this engine. +*/ +QGeoRouteRequest::TravelModes QGeoRoutingManagerEngine::supportedTravelModes() const +{ + return d_ptr->supportedTravelModes; +} + +/*! + Sets the types of features that this engine can take into account + during route planning to \a featureTypes. + + It is important that subclasses use this method to ensure that the engine + reports its capabilities correctly. If this function is not used the + engine will report that it supports no feature types at all. +*/ +void QGeoRoutingManagerEngine::setSupportedFeatureTypes(QGeoRouteRequest::FeatureTypes featureTypes) +{ + d_ptr->supportedFeatureTypes = featureTypes; +} + +/*! + Returns the types of features that this engine can take into account + during route planning. +*/ +QGeoRouteRequest::FeatureTypes QGeoRoutingManagerEngine::supportedFeatureTypes() const +{ + return d_ptr->supportedFeatureTypes; +} + +/*! + Sets the weightings which this engine can apply to different features + during route planning to \a featureWeights. + + It is important that subclasses use this method to ensure that the engine + reports its capabilities correctly. If this function is not used the + engine will report that it supports no feature weights at all. +*/ +void QGeoRoutingManagerEngine::setSupportedFeatureWeights(QGeoRouteRequest::FeatureWeights featureWeights) +{ + d_ptr->supportedFeatureWeights = featureWeights; + d_ptr->supportedFeatureWeights |= QGeoRouteRequest::NeutralFeatureWeight; +} + +/*! + Returns the weightings which this engine can apply to different features + during route planning. +*/ +QGeoRouteRequest::FeatureWeights QGeoRoutingManagerEngine::supportedFeatureWeights() const +{ + return d_ptr->supportedFeatureWeights; +} + +/*! + Sets the route optimizations supported by this engine to \a optimizations. + + It is important that subclasses use this method to ensure that the engine + reports its capabilities correctly. If this function is not used the + engine will report that it supports no route optimizations at all. +*/ +void QGeoRoutingManagerEngine::setSupportedRouteOptimizations(QGeoRouteRequest::RouteOptimizations optimizations) +{ + d_ptr->supportedRouteOptimizations = optimizations; +} + +/*! + Returns the route optimizations supported by this engine. +*/ +QGeoRouteRequest::RouteOptimizations QGeoRoutingManagerEngine::supportedRouteOptimizations() const +{ + return d_ptr->supportedRouteOptimizations; +} + +/*! + Sets the levels of detail for routing segments which can be + requested by this engine to \a segmentDetails. + + It is important that subclasses use this method to ensure that the engine + reports its capabilities correctly. If this function is not used the + engine will report that it supports no segment detail at all. +*/ +void QGeoRoutingManagerEngine::setSupportedSegmentDetails(QGeoRouteRequest::SegmentDetails segmentDetails) +{ + d_ptr->supportedSegmentDetails = segmentDetails; +} + +/*! + Returns the levels of detail for routing segments which can be + requested by this engine. +*/ +QGeoRouteRequest::SegmentDetails QGeoRoutingManagerEngine::supportedSegmentDetails() const +{ + return d_ptr->supportedSegmentDetails; +} + +/*! + Sets the levels of detail for navigation maneuvers which can be + requested by this engine to \a maneuverDetails. + + It is important that subclasses use this method to ensure that the engine + reports its capabilities correctly. If this function is not used the + engine will report that it supports no maneuver details at all. +*/ +void QGeoRoutingManagerEngine::setSupportedManeuverDetails(QGeoRouteRequest::ManeuverDetails maneuverDetails) +{ + d_ptr->supportedManeuverDetails = maneuverDetails; +} + +/*! + Returns the levels of detail for navigation maneuvers which can be + requested by this engine. +*/ +QGeoRouteRequest::ManeuverDetails QGeoRoutingManagerEngine::supportedManeuverDetails() const +{ + return d_ptr->supportedManeuverDetails; +} + +/*! + Sets the locale to be used by this manager to \a locale. + + If this routing manager supports returning addresses and instructions + in different languages, they will be returned in the language of \a locale. + + The locale used defaults to the system locale if this is not set. +*/ +void QGeoRoutingManagerEngine::setLocale(const QLocale &locale) +{ + d_ptr->locale = locale; + d_ptr->measurementSystem = locale.measurementSystem(); +} + +/*! + Returns the locale used to hint to this routing manager about what + language to use for addresses and instructions. +*/ +QLocale QGeoRoutingManagerEngine::locale() const +{ + return d_ptr->locale; +} + +/*! + Sets the measurement system used by this manager to \a system. + + The measurement system can be set independently of the locale. Both setLocale() and this + function set the measurement system. The value set by the last function called will be used. + + \sa measurementSystem(), locale(), setLocale() +*/ +void QGeoRoutingManagerEngine::setMeasurementSystem(QLocale::MeasurementSystem system) +{ + d_ptr->measurementSystem = system; +} + +/*! + Returns the measurement system used by this manager. + + If setMeasurementSystem() has been called then the value returned by this function may be + different to that returned by locale().\l {QLocale::measurementSystem()}{measurementSystem()}. + In which case the value returned by this function is what will be used by the manager. + + \sa setMeasurementSystem(), setLocale() +*/ +QLocale::MeasurementSystem QGeoRoutingManagerEngine::measurementSystem() const +{ + return d_ptr->measurementSystem; +} + +/*! +\fn void QGeoRoutingManagerEngine::finished(QGeoRouteReply *reply) + +This signal is emitted when \a reply has finished processing. + +If reply::error() equals QGeoRouteReply::NoError then the processing +finished successfully. + +This signal and QGeoRouteReply::finished() will be emitted at the same time. + +\note Do not delete the \a reply object in the slot connected to this signal. +Use deleteLater() instead. +*/ + +/*! +\fn void QGeoRoutingManagerEngine::error(QGeoRouteReply *reply, QGeoRouteReply::Error error, QString errorString) + +This signal is emitted when an error has been detected in the processing of +\a reply. The QGeoRoutingManagerEngine::finished() signal will probably follow. + +The error will be described by the error code \a error. If \a errorString is +not empty it will contain a textual description of the error. + +This signal and QGeoRouteReply::error() will be emitted at the same time. + +\note Do not delete the \a reply object in the slot connected to this signal. +Use deleteLater() instead. +*/ + +/******************************************************************************* +*******************************************************************************/ + +QGeoRoutingManagerEnginePrivate::QGeoRoutingManagerEnginePrivate() +: managerVersion(-1), measurementSystem(locale.measurementSystem()) +{ +} + +QGeoRoutingManagerEnginePrivate::~QGeoRoutingManagerEnginePrivate() {} + +#include "moc_qgeoroutingmanagerengine.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroutingmanagerengine.h b/src/location/maps/qgeoroutingmanagerengine.h new file mode 100644 index 0000000..21aef7c --- /dev/null +++ b/src/location/maps/qgeoroutingmanagerengine.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTINGMANAGERENGINE_H +#define QGEOROUTINGMANAGERENGINE_H + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRoutingManagerEnginePrivate; + +class Q_LOCATION_EXPORT QGeoRoutingManagerEngine : public QObject +{ + Q_OBJECT +public: + explicit QGeoRoutingManagerEngine(const QVariantMap ¶meters, QObject *parent = Q_NULLPTR); + virtual ~QGeoRoutingManagerEngine(); + + QString managerName() const; + int managerVersion() const; + + virtual QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request) = 0; + virtual QGeoRouteReply *updateRoute(const QGeoRoute &route, const QGeoCoordinate &position); + + QGeoRouteRequest::TravelModes supportedTravelModes() const; + QGeoRouteRequest::FeatureTypes supportedFeatureTypes() const; + QGeoRouteRequest::FeatureWeights supportedFeatureWeights() const; + QGeoRouteRequest::RouteOptimizations supportedRouteOptimizations() const; + QGeoRouteRequest::SegmentDetails supportedSegmentDetails() const; + QGeoRouteRequest::ManeuverDetails supportedManeuverDetails() const; + + void setLocale(const QLocale &locale); + QLocale locale() const; + void setMeasurementSystem(QLocale::MeasurementSystem system); + QLocale::MeasurementSystem measurementSystem() const; + +Q_SIGNALS: + void finished(QGeoRouteReply *reply); + void error(QGeoRouteReply *reply, QGeoRouteReply::Error error, QString errorString = QString()); + +protected: + void setSupportedTravelModes(QGeoRouteRequest::TravelModes travelModes); + void setSupportedFeatureTypes(QGeoRouteRequest::FeatureTypes featureTypes); + void setSupportedFeatureWeights(QGeoRouteRequest::FeatureWeights featureWeights); + void setSupportedRouteOptimizations(QGeoRouteRequest::RouteOptimizations optimizations); + void setSupportedSegmentDetails(QGeoRouteRequest::SegmentDetails segmentDetails); + void setSupportedManeuverDetails(QGeoRouteRequest::ManeuverDetails maneuverDetails); + +private: + void setManagerName(const QString &managerName); + void setManagerVersion(int managerVersion); + + QGeoRoutingManagerEnginePrivate *d_ptr; + Q_DISABLE_COPY(QGeoRoutingManagerEngine) + + friend class QGeoServiceProvider; + friend class QGeoServiceProviderPrivate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoroutingmanagerengine_p.h b/src/location/maps/qgeoroutingmanagerengine_p.h new file mode 100644 index 0000000..7ba6c3d --- /dev/null +++ b/src/location/maps/qgeoroutingmanagerengine_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTINGMANAGERENGINE_P_H +#define QGEOROUTINGMANAGERENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeorouterequest.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRoutingManagerEnginePrivate +{ +public: + QGeoRoutingManagerEnginePrivate(); + ~QGeoRoutingManagerEnginePrivate(); + + QString managerName; + int managerVersion; + + QGeoRouteRequest::TravelModes supportedTravelModes; + QGeoRouteRequest::FeatureTypes supportedFeatureTypes; + QGeoRouteRequest::FeatureWeights supportedFeatureWeights; + QGeoRouteRequest::RouteOptimizations supportedRouteOptimizations; + QGeoRouteRequest::SegmentDetails supportedSegmentDetails; + QGeoRouteRequest::ManeuverDetails supportedManeuverDetails; + + QLocale locale; + QLocale::MeasurementSystem measurementSystem; + +private: + Q_DISABLE_COPY(QGeoRoutingManagerEnginePrivate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoserviceprovider.cpp b/src/location/maps/qgeoserviceprovider.cpp new file mode 100644 index 0000000..51b0de6 --- /dev/null +++ b/src/location/maps/qgeoserviceprovider.cpp @@ -0,0 +1,730 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoserviceprovider.h" +#include "qgeoserviceprovider_p.h" +#include "qgeoserviceproviderfactory.h" + +#include "qgeocodingmanager.h" +#include "qgeomappingmanager_p.h" +#include "qgeoroutingmanager.h" +#include "qplacemanager.h" +#include "qgeocodingmanagerengine.h" +#include "qgeomappingmanagerengine_p.h" +#include "qgeoroutingmanagerengine.h" +#include "qplacemanagerengine.h" +#include "qplacemanagerengine_p.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_LIBRARY +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + ("org.qt-project.qt.geoservice.serviceproviderfactory/5.0", + QLatin1String("/geoservices"))) +#endif + +/*! + \class QGeoServiceProvider + \inmodule QtLocation + \ingroup QtLocation-common + \since 5.6 + + \brief The QGeoServiceProvider class aggregates access to services which provide + geographical information. + + The Maps and Navigation API allows people to access various kinds of + geographical information, including functionality to perform geocoding, + routing and the display of maps. The QGeoServiceProvider aggregates the + access to a set of these services that are provided by a single vendor. + + It is possible to mix and match service providers for the various domains, + so that a geocoding manager from one service provider can be used with + a geographic routing manager from another service provider. + + This is not recommended unless the client is able to verify that the + data provided by the different services are compatible, as differences + in the underlying data sets could cause serious incongruences between + the services. + + Subclasses of QGeoServiceProvider guarantee that the different services + that they provide are interoperable. + + At this point there are two GeoServices plugins packaged with Qt. They are + accessible using their provider names: + + \list + \li "mapbox" -> \l {Qt Location Mapbox Plugin}{Mapbox service} + \li "here" -> \l {Qt Location HERE Plugin}{HERE Services} + \li "osm" -> \l {Qt Location Open Street Map Plugin}{OpenStreetMap Services} + \endlist + + Each service provider must follow a naming convention for their service specific + parameter names/keys. They use the provider name as prefix for all their + parameter names. For example, the \l {Qt Location HERE Plugin}{HERE} service provider + requires the \c here.app_id parameter. When a provider is loaded only those parameters are + passed on whose parameter names start with the provider name. This avoids the sharing + sensitive parameters such as confidential \c token or \c app_id parameters with other + plugins. + + Please check the GeoServices plugin specific documentation to + obtain a complete list of the available parameter names/keys and values. +*/ + +/*! + \enum QGeoServiceProvider::Error + + Describes an error related to the loading and setup of a service provider plugin. + + \value NoError + No error has occurred. + \value NotSupportedError + The plugin does not support this functionality. + \value UnknownParameterError + The plugin did not recognize one of the parameters it was given. + \value MissingRequiredParameterError + The plugin did not find one of the parameters it was expecting. + \value ConnectionError + The plugin could not connect to its backend service or database. +*/ + +/*! + \enum QGeoServiceProvider::RoutingFeature + + Describes the routing features supported by the geo service provider. + + \value NoRoutingFeatures No routing features are supported. + \value OnlineRoutingFeature Online routing is supported. + \value OfflineRoutingFeature Offline routing is supported. + \value LocalizedRoutingFeature Supports returning routes with localized addresses and + instructions. + \value RouteUpdatesFeature Updating an existing route based on the current position is + supported. + \value AlternativeRoutesFeature Supports returning alternative routes. + \value ExcludeAreasRoutingFeature Supports specifying a areas which the returned route must + not cross. + \value AnyRoutingFeatures Matches a geo service provider that provides any routing + features. +*/ + +/*! + \enum QGeoServiceProvider::GeocodingFeature + + Describes the geocoding features supported by the geo service provider. + + \value NoGeocodingFeatures No geocoding features are supported. + \value OnlineGeocodingFeature Online geocoding is supported. + \value OfflineGeocodingFeature Offline geocoding is supported. + \value ReverseGeocodingFeature Reverse geocoding is supported. + \value LocalizedGeocodingFeature Supports returning geocoding results with localized + addresses. + \value AnyGeocodingFeatures Matches a geo service provider that provides any geocoding + features. +*/ + +/*! + \enum QGeoServiceProvider::MappingFeature + + Describes the mapping features supported by the geo service provider. + + \value NoMappingFeatures No mapping features are supported. + \value OnlineMappingFeature Online mapping is supported. + \value OfflineMappingFeature Offline mapping is supported. + \value LocalizedMappingFeature Supports returning localized map data. + \value AnyMappingFeatures Matches a geo service provider that provides any mapping + features. +*/ + +/*! + \enum QGeoServiceProvider::PlacesFeature + + Describes the places features supported by the geo service provider. + + \value NoPlacesFeatures No places features are supported. + \value OnlinePlacesFeature Online places is supported. + \value OfflinePlacesFeature Offline places is supported. + \value SavePlaceFeature Saving places is supported. + \value RemovePlaceFeature Removing or deleting places is supported. + \value SaveCategoryFeature Saving categories is supported. + \value RemoveCategoryFeature Removing or deleting categories is supported. + \value PlaceRecommendationsFeature Searching for recommended places similar to another place + is supported. + \value SearchSuggestionsFeature Search suggestions is supported. + \value LocalizedPlacesFeature Supports returning localized place data. + \value NotificationsFeature Notifications of place and category changes is supported. + \value PlaceMatchingFeature Supports matching places from two different geo service + providers. + \value AnyPlacesFeatures Matches a geo service provider that provides any places + features. +*/ + +/*! + Returns a list of names of the available service providers, for use with + the QGeoServiceProvider constructors. +*/ +QStringList QGeoServiceProvider::availableServiceProviders() +{ + return QGeoServiceProviderPrivate::plugins().keys(); +} + +/*! + Constructs a QGeoServiceProvider whose backend has the name \a + providerName, using the provided \a parameters. + + If multiple plugins have the same \a providerName, the plugin with the + highest reported providerVersion() will be used. + + If \a allowExperimental is true then plugins marked as experimental may be used. By default + experimental plugins are not considered. + + If no plugin matching \a providerName was able to be loaded then error() + and errorString() will provide details about why this is the case. + + \note Before the list of \a parameters is passed on to the to-be-loaded + provider plugin, the list is filtered to avoid the sharing of plugin specific + parameters with unrelated provider plugins. Plugin specific parameter + keys must be prefixed with the provider name (e.g. \c here.app_id). +*/ +QGeoServiceProvider::QGeoServiceProvider(const QString &providerName, + const QVariantMap ¶meters, + bool allowExperimental) + : d_ptr(new QGeoServiceProviderPrivate()) +{ + d_ptr->experimental = allowExperimental; + d_ptr->parameterMap = parameters; + // TODO Qt 6 Remove silent nokia rename + if (providerName == QStringLiteral("nokia")) + d_ptr->providerName = QStringLiteral("here"); + else + d_ptr->providerName = providerName; + d_ptr->loadMeta(); +} + +/*! + Destroys the service provider object. +*/ +QGeoServiceProvider::~QGeoServiceProvider() +{ + delete d_ptr; +} + +/* Template for the routingFeatures(), geocodingFeatures() etc methods. + * Ideally, the enumName would be a template parameter, but strings + * are not a valid const expr. :( */ +template +Flags QGeoServiceProviderPrivate::features(const char *enumName) +{ + const QMetaObject *mo = &QGeoServiceProvider::staticMetaObject; + const QMetaEnum en = mo->enumerator( + mo->indexOfEnumerator(enumName)); + + /* We need the typename keyword here, or Flags::enum_type will be parsed + * as a non-type and lead to an error */ + Flags ret = typename Flags::enum_type(0); + if (this->metaData.contains(QStringLiteral("Features")) + && this->metaData.value(QStringLiteral("Features")).isArray()) { + QJsonArray features = this->metaData.value(QStringLiteral("Features")).toArray(); + foreach (const QJsonValue &v, features) { + int val = en.keyToValue(v.toString().toLatin1().constData()); + if (v.isString() && val != -1) { + ret |= typename Flags::enum_type(val); + } + } + } + + return ret; +} + +/*! + Returns the routing features supported by the geo service provider. +*/ +QGeoServiceProvider::RoutingFeatures QGeoServiceProvider::routingFeatures() const +{ + return d_ptr->features("RoutingFeatures"); +} + +/*! + Returns the geocoding features supported by the geo service provider. +*/ +QGeoServiceProvider::GeocodingFeatures QGeoServiceProvider::geocodingFeatures() const +{ + return d_ptr->features("GeocodingFeatures"); +} + +/*! + Returns the mapping features supported by the geo service provider. +*/ +QGeoServiceProvider::MappingFeatures QGeoServiceProvider::mappingFeatures() const +{ + return d_ptr->features("MappingFeatures"); +} + +/*! + Returns the places features supported by the geo service provider. +*/ +QGeoServiceProvider::PlacesFeatures QGeoServiceProvider::placesFeatures() const +{ + return d_ptr->features("PlacesFeatures"); +} + +/* Sadly, these are necessary to figure out which of the factory->createX + * methods we need to call. Ideally it would be nice to find a way to embed + * these into the manager() template. */ +template +Engine *createEngine(QGeoServiceProviderPrivate *) +{ + return 0; +} +template <> QGeoCodingManagerEngine *createEngine(QGeoServiceProviderPrivate *d_ptr) +{ + return d_ptr->factory->createGeocodingManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->geocodeError), &(d_ptr->geocodeErrorString)); +} +template <> QGeoRoutingManagerEngine *createEngine(QGeoServiceProviderPrivate *d_ptr) +{ + return d_ptr->factory->createRoutingManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->routingError), &(d_ptr->routingErrorString)); +} +template <> QGeoMappingManagerEngine *createEngine(QGeoServiceProviderPrivate *d_ptr) +{ + return d_ptr->factory->createMappingManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->mappingError), &(d_ptr->mappingErrorString)); +} +template <> QPlaceManagerEngine *createEngine(QGeoServiceProviderPrivate *d_ptr) +{ + return d_ptr->factory->createPlaceManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->placeError), &(d_ptr->placeErrorString)); +} + +/* Template for generating the code for each of the geocodingManager(), + * mappingManager() etc methods */ +template +Manager *QGeoServiceProviderPrivate::manager(QGeoServiceProvider::Error *_error, + QString *_errorString, Manager **_manager) +{ + // make local references just so this method is easier to read + QGeoServiceProvider::Error &error = *_error; + QString &errorString = *_errorString; + Manager *&manager = *_manager; + + if (!this->factory) { + this->filterParameterMap(); + this->loadPlugin(this->parameterMap); + } + + if (!this->factory || error != QGeoServiceProvider::NoError) + return 0; + + if (!manager) { + Engine *engine = createEngine(this); + + if (engine) { + engine->setManagerName( + this->metaData.value(QStringLiteral("Provider")).toString()); + engine->setManagerVersion( + int(this->metaData.value(QStringLiteral("Version")).toDouble())); + manager = new Manager(engine); + } else if (error == QGeoServiceProvider::NoError) { + error = QGeoServiceProvider::NotSupportedError; + errorString = QLatin1String("The service provider does not support the "); + errorString.append(QLatin1String(Manager::staticMetaObject.className())); + errorString.append(QLatin1String(" type.")); + } + + if (error != QGeoServiceProvider::NoError) { + delete manager; + manager = 0; + this->error = error; + this->errorString = errorString; + } + + if (manager && this->localeSet) + manager->setLocale(this->locale); + } + + if (manager) { + this->error = QGeoServiceProvider::NoError; + this->errorString.clear(); + } + + return manager; +} + +/*! + Returns the QGeoCodingManager made available by the service + provider. + + This function will return 0 if the service provider does not provide + any geocoding services. + + This function will attempt to construct a QGeoCodingManager instance + when it is called for the first time. If the attempt is successful the + QGeoCodingManager will be cached, otherwise each call of this function + will attempt to construct a QGeoCodingManager instance until the + construction is successful. + + The QGeoCodingManager is owned by this QGeoServiceProvider and should not + be deleted separately. Users should assume that deleting the + QGeoServiceProvider renders the pointer returned by this method invalid. + + After this function has been called, error() and errorString() will + report any errors which occurred during the construction of the + QGeoCodingManager. +*/ +QGeoCodingManager *QGeoServiceProvider::geocodingManager() const +{ + return d_ptr->manager( + &(d_ptr->geocodeError), &(d_ptr->geocodeErrorString), + &(d_ptr->geocodingManager)); +} + +/*! + Returns the QGeoMappingManager made available by the service provider. + + This function will return 0 if the service provider does not provide + any mapping services. + + This function will attempt to construct a QGeoMappingManager instance + when it is called for the first time. If the attempt is successful the + QGeoMappingManager will be cached, otherwise each call of this function + will attempt to construct a QGeoMappingManager instance until the + construction is successful. + + The QGeoMappingManager is owned by this QGeoServiceProvider and should not + be deleted separately. Users should assume that deleting the + QGeoServiceProvider renders the pointer returned by this method invalid. + + After this function has been called, error() and errorString() will + report any errors which occurred during the construction of the + QGeoMappingManager. + + \internal +*/ +QGeoMappingManager *QGeoServiceProvider::mappingManager() const +{ + return d_ptr->manager( + &(d_ptr->mappingError), &(d_ptr->mappingErrorString), + &(d_ptr->mappingManager)); +} + +/*! + Returns the QGeoRoutingManager made available by the service provider. + + This function will return 0 if the service provider does not provide + any geographic routing services. + + This function will attempt to construct a QGeoRoutingManager instance + when it is called for the first time. If the attempt is successful the + QGeoRoutingManager will be cached, otherwise each call of this function + will attempt to construct a QGeoRoutingManager instance until the + construction is successful. + + The QGeoRoutingManager is owned by this QGeoServiceProvider and should not + be deleted separately. Users should assume that deleting the + QGeoServiceProvider renders the pointer returned by this method invalid. + + After this function has been called, error() and errorString() will + report any errors which occurred during the construction of the + QGeoRoutingManager. +*/ +QGeoRoutingManager *QGeoServiceProvider::routingManager() const +{ + return d_ptr->manager( + &(d_ptr->routingError), &(d_ptr->routingErrorString), + &(d_ptr->routingManager)); +} + +/*! + Returns the QPlaceManager made available by the service provider. + + This function will attempt to construct a QPlaceManager instance + when it is called for the first time. If the attempt is successful the + QPlaceManager will be cached, otherwise each call of this function + will attempt to construct a QPlace instance until the + construction is successful. + + The QGeoPlaceManager is owned by this QGeoServiceProvider and should not + be deleted separately. Users should assume that deleting the + QGeoServiceProvider renders the pointer returned by this method invalid. + + After this function has been called, error() and errorString() will + report any errors which occurred during the construction of the QPlaceManager. +*/ +QPlaceManager *QGeoServiceProvider::placeManager() const +{ + return d_ptr->manager( + &(d_ptr->placeError), &(d_ptr->placeErrorString), + &(d_ptr->placeManager)); +} + +/*! + Returns an error code describing the error which occurred during the + last operation that was performed by this class. +*/ +QGeoServiceProvider::Error QGeoServiceProvider::error() const +{ + return d_ptr->error; +} + +/*! + Returns a string describing the error which occurred during the + last operation that was performed by this class. +*/ +QString QGeoServiceProvider::errorString() const +{ + return d_ptr->errorString; +} + +/*! + Sets whether experimental plugins are considered when locating the + correct plugin library for this service provider to \a allow. + + \b {Important:} this will destroy any existing managers held by this + service provider instance. You should be sure not to attempt to use any + pointers that you have previously retrieved after calling this method. +*/ +void QGeoServiceProvider::setAllowExperimental(bool allow) +{ + d_ptr->experimental = allow; + d_ptr->unload(); + d_ptr->loadMeta(); +} + +/*! + Sets the parameters used to construct individual manager classes for + this service provider to \a parameters. + + Before the list of \a parameters is passed on to the to-be-loaded + service provider, the list is filtered to avoid the sharing of provider specific + parameters with unrelated service providers. Provider specific parameter + keys must be prefixed with the provider name (e.g. \c here.app_id). + + \b {Important:} this will destroy any existing managers held by this + service provider instance. You should be sure not to attempt to use any + pointers that you have previously retrieved after calling this method. +*/ +void QGeoServiceProvider::setParameters(const QVariantMap ¶meters) +{ + d_ptr->parameterMap = parameters; + d_ptr->unload(); + d_ptr->loadMeta(); +} + +/*! + Sets the locale used by this service provider to \a locale. If the relevant features + (see LocalizedMappingFeature etc), this will change the languages, units + and other locale-specific attributes of the provider's data. +*/ +void QGeoServiceProvider::setLocale(const QLocale &locale) +{ + d_ptr->locale = locale; + d_ptr->localeSet = true; + + if (d_ptr->geocodingManager) + d_ptr->geocodingManager->setLocale(locale); + if (d_ptr->routingManager) + d_ptr->routingManager->setLocale(locale); + if (d_ptr->mappingManager) + d_ptr->mappingManager->setLocale(locale); + if (d_ptr->placeManager) + d_ptr->placeManager->setLocale(locale); +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoServiceProviderPrivate::QGeoServiceProviderPrivate() + : factory(0), + experimental(false), + geocodingManager(0), + routingManager(0), + mappingManager(0), + placeManager(0), + geocodeError(QGeoServiceProvider::NoError), + routingError(QGeoServiceProvider::NoError), + mappingError(QGeoServiceProvider::NoError), + placeError(QGeoServiceProvider::NoError), + error(QGeoServiceProvider::NoError), + localeSet(false) +{ + metaData.insert(QStringLiteral("index"), -1); +} + +QGeoServiceProviderPrivate::~QGeoServiceProviderPrivate() +{ + delete geocodingManager; + delete routingManager; + delete mappingManager; + delete placeManager; +} + +void QGeoServiceProviderPrivate::unload() +{ + delete geocodingManager; + geocodingManager = 0; + + delete routingManager; + routingManager = 0; + + delete mappingManager; + mappingManager = 0; + + delete placeManager; + placeManager = 0; + + factory = 0; + error = QGeoServiceProvider::NoError; + errorString = QLatin1String(""); + metaData = QJsonObject(); + metaData.insert(QStringLiteral("index"), -1); +} + +/* Filter out any parameter that doesn't match any plugin */ +void QGeoServiceProviderPrivate::filterParameterMap() +{ + const auto availablePlugins = QGeoServiceProviderPrivate::plugins(); + + cleanedParameterMap = parameterMap; + for (auto it = availablePlugins.keyBegin(), end = availablePlugins.keyEnd(); it != end; ++it) { + if (*it == providerName) // don't remove parameters for current provider + continue; + + QVariantMap::iterator i = cleanedParameterMap.begin(); + while (i != cleanedParameterMap.end()) { + // remove every parameter meant for other plugins + if (i.key().startsWith(QString(*it + QLatin1Char('.')))) + i = cleanedParameterMap.erase(i); + else + ++i; + } + } +} + +void QGeoServiceProviderPrivate::loadMeta() +{ + factory = 0; + metaData = QJsonObject(); + metaData.insert(QStringLiteral("index"), -1); + error = QGeoServiceProvider::NotSupportedError; + errorString = QString(QLatin1String("The geoservices provider %1 is not supported.")).arg(providerName); + + QList candidates = QGeoServiceProviderPrivate::plugins().values(providerName); + + int versionFound = -1; + int idx = -1; + + // figure out which version of the plugin we want + // (always latest unless experimental) + for (int i = 0; i < candidates.size(); ++i) { + QJsonObject meta = candidates[i]; + if (meta.contains(QStringLiteral("Version")) + && meta.value(QStringLiteral("Version")).isDouble() + && meta.contains(QStringLiteral("Experimental")) + && meta.value(QStringLiteral("Experimental")).isBool()) { + int ver = int(meta.value(QStringLiteral("Version")).toDouble()); + if (ver > versionFound && !(!experimental && meta.value(QStringLiteral("Experimental")).toBool())) { + versionFound = ver; + idx = i; + } + } + } + + if (idx != -1) { + error = QGeoServiceProvider::NoError; + errorString = QStringLiteral(""); + metaData = candidates[idx]; + } +} + +void QGeoServiceProviderPrivate::loadPlugin(const QVariantMap ¶meters) +{ + Q_UNUSED(parameters) + + if (int(metaData.value(QStringLiteral("index")).toDouble()) < 0) { + error = QGeoServiceProvider::NotSupportedError; + errorString = QString(QLatin1String("The geoservices provider is not supported.")); + factory = 0; + return; + } + + error = QGeoServiceProvider::NoError; + errorString = QLatin1String(""); + + int idx = int(metaData.value(QStringLiteral("index")).toDouble()); + + // load the actual plugin + factory = qobject_cast(loader()->instance(idx)); +} + +QHash QGeoServiceProviderPrivate::plugins(bool reload) +{ + static QHash plugins; + static bool alreadyDiscovered = false; + + if (reload == true) + alreadyDiscovered = false; + + if (!alreadyDiscovered) { + loadPluginMetadata(plugins); + alreadyDiscovered = true; + } + return plugins; +} + +void QGeoServiceProviderPrivate::loadPluginMetadata(QHash &list) +{ + QFactoryLoader *l = loader(); + QList meta = l->metaData(); + for (int i = 0; i < meta.size(); ++i) { + QJsonObject obj = meta.at(i).value(QStringLiteral("MetaData")).toObject(); + obj.insert(QStringLiteral("index"), i); + list.insertMulti(obj.value(QStringLiteral("Provider")).toString(), obj); + } +} + + +QT_END_NAMESPACE + diff --git a/src/location/maps/qgeoserviceprovider.h b/src/location/maps/qgeoserviceprovider.h new file mode 100644 index 0000000..ea8c2b6 --- /dev/null +++ b/src/location/maps/qgeoserviceprovider.h @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDER_H +#define QGEOSERVICEPROVIDER_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QLocale; +class QStringList; +class QGeoCodingManager; +class QGeoMappingManager; +class QGeoRoutingManager; +class QPlaceManager; +class QGeoCodingManagerEngine; +class QGeoMappingManagerEngine; +class QGeoRoutingManagerEngine; +class QPlaceManagerEngine; +class QGeoServiceProviderPrivate; + +class Q_LOCATION_EXPORT QGeoServiceProvider : public QObject +{ + Q_OBJECT + Q_ENUMS(Error) +public: + enum Error { + NoError, + NotSupportedError, + UnknownParameterError, + MissingRequiredParameterError, + ConnectionError + }; + + enum RoutingFeature { + NoRoutingFeatures = 0, + OnlineRoutingFeature = (1<<0), + OfflineRoutingFeature = (1<<1), + LocalizedRoutingFeature = (1<<2), + RouteUpdatesFeature = (1<<3), + AlternativeRoutesFeature = (1<<4), + ExcludeAreasRoutingFeature = (1<<5), + AnyRoutingFeatures = ~(0) + }; + + enum GeocodingFeature { + NoGeocodingFeatures = 0, + OnlineGeocodingFeature = (1<<0), + OfflineGeocodingFeature = (1<<1), + ReverseGeocodingFeature = (1<<2), + LocalizedGeocodingFeature = (1<<3), + AnyGeocodingFeatures = ~(0) + }; + + enum MappingFeature { + NoMappingFeatures = 0, + OnlineMappingFeature = (1<<0), + OfflineMappingFeature = (1<<1), + LocalizedMappingFeature = (1<<2), + AnyMappingFeatures = ~(0) + }; + + enum PlacesFeature { + NoPlacesFeatures = 0, + OnlinePlacesFeature = (1<<0), + OfflinePlacesFeature = (1<<1), + SavePlaceFeature = (1<<2), + RemovePlaceFeature = (1<<3), + SaveCategoryFeature = (1<<4), + RemoveCategoryFeature = (1<<5), + PlaceRecommendationsFeature = (1<<6), + SearchSuggestionsFeature = (1<<7), + LocalizedPlacesFeature = (1<<8), + NotificationsFeature = (1<<9), + PlaceMatchingFeature = (1<<10), + AnyPlacesFeatures = ~(0) + }; + + Q_DECLARE_FLAGS(RoutingFeatures, RoutingFeature) + Q_FLAGS(RoutingFeatures) + + Q_DECLARE_FLAGS(GeocodingFeatures, GeocodingFeature) + Q_FLAGS(GeocodingFeatures) + + Q_DECLARE_FLAGS(MappingFeatures, MappingFeature) + Q_FLAGS(MappingFeatures) + + Q_DECLARE_FLAGS(PlacesFeatures, PlacesFeature) + Q_FLAGS(PlacesFeatures) + + static QStringList availableServiceProviders(); + QGeoServiceProvider(const QString &providerName, + const QVariantMap ¶meters = QVariantMap(), + bool allowExperimental = false); + + ~QGeoServiceProvider(); + + RoutingFeatures routingFeatures() const; + GeocodingFeatures geocodingFeatures() const; + MappingFeatures mappingFeatures() const; + PlacesFeatures placesFeatures() const; + + QGeoCodingManager *geocodingManager() const; + QGeoMappingManager *mappingManager() const; + QGeoRoutingManager *routingManager() const; + QPlaceManager *placeManager() const; + + Error error() const; + QString errorString() const; + + void setParameters(const QVariantMap ¶meters); + void setLocale(const QLocale &locale); + void setAllowExperimental(bool allow); + +private: + QGeoServiceProviderPrivate *d_ptr; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoServiceProvider::RoutingFeatures) +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoServiceProvider::GeocodingFeatures) +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoServiceProvider::MappingFeatures) +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoServiceProvider::PlacesFeatures) + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoserviceprovider_p.h b/src/location/maps/qgeoserviceprovider_p.h new file mode 100644 index 0000000..6bfb9b2 --- /dev/null +++ b/src/location/maps/qgeoserviceprovider_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDER_P_H +#define QGEOSERVICEPROVIDER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeoserviceprovider.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCodingManager; +class QGeoRoutingManager; +class QGeoMappingManager; + +class QGeoServiceProviderFactory; + +class QGeoServiceProviderPrivate +{ +public: + QGeoServiceProviderPrivate(); + ~QGeoServiceProviderPrivate(); + + void loadMeta(); + void loadPlugin(const QVariantMap ¶meters); + void unload(); + void filterParameterMap(); + + /* helper templates for generating the feature and manager accessors */ + template + Manager *manager(QGeoServiceProvider::Error *error, + QString *errorString, Manager **manager); + template + Flags features(const char *enumName); + + QGeoServiceProviderFactory *factory; + QJsonObject metaData; + + QVariantMap parameterMap; + QVariantMap cleanedParameterMap; + + bool experimental; + + QGeoCodingManager *geocodingManager; + QGeoRoutingManager *routingManager; + QGeoMappingManager *mappingManager; + QPlaceManager *placeManager; + + QGeoServiceProvider::Error geocodeError; + QGeoServiceProvider::Error routingError; + QGeoServiceProvider::Error mappingError; + QGeoServiceProvider::Error placeError; + + QString geocodeErrorString; + QString routingErrorString; + QString mappingErrorString; + QString placeErrorString; + + QGeoServiceProvider::Error error; + QString errorString; + + QString providerName; + + QLocale locale; + bool localeSet; + + static QHash plugins(bool reload = false); + static void loadPluginMetadata(QHash &list); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeoserviceproviderfactory.cpp b/src/location/maps/qgeoserviceproviderfactory.cpp new file mode 100644 index 0000000..7efc8a9 --- /dev/null +++ b/src/location/maps/qgeoserviceproviderfactory.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoserviceproviderfactory.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoServiceProviderFactory + \inmodule QtLocation + \ingroup QtLocation-impl + \since 5.6 + + \brief The QGeoServiceProviderFactory class is a factory class used as the + plugin interface for services related to geographical information. + + Implementers must provide a unique combination of providerName() and + providerVersion() per plugin. + + The other functions should be overridden if the plugin supports the + associated set of functionality. +*/ + +/*! +\fn QGeoServiceProviderFactory::~QGeoServiceProviderFactory() + +Destroys this QGeoServiceProviderFactory instance. +*/ + +/*! + Returns a new QGeoCodingManagerEngine instance, initialized with \a + parameters, which implements the location geocoding functionality. + + If \a error is not 0 it should be set to QGeoServiceProvider::NoError on + success or an appropriate QGeoServiceProvider::Error on failure. + + If \a errorString is not 0 it should be set to a string describing any + error which occurred. + + The default implementation returns 0, which causes a + QGeoServiceProvider::NotSupportedError in QGeoServiceProvider. +*/ +QGeoCodingManagerEngine *QGeoServiceProviderFactory::createGeocodingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const +{ + Q_UNUSED(parameters) + Q_UNUSED(error) + Q_UNUSED(errorString) + + return 0; +} + +/*! + Returns a new QGeoMappingManagerEngine instance, initialized with \a + parameters, which implements mapping functionality. + + If \a error is not 0 it should be set to QGeoServiceProvider::NoError on + success or an appropriate QGeoServiceProvider::Error on failure. + + If \a errorString is not 0 it should be set to a string describing any + error which occurred. + + The default implementation returns 0, which causes a + QGeoServiceProvider::NotSupportedError in QGeoServiceProvider. + + \internal +*/ +QGeoMappingManagerEngine *QGeoServiceProviderFactory::createMappingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const +{ + Q_UNUSED(parameters) + Q_UNUSED(error) + Q_UNUSED(errorString) + + return 0; +} + +/*! + Returns a new QGeoRoutingManagerEngine instance, initialized with \a + parameters, which implements routing functionality. + + If \a error is not 0 it should be set to QGeoServiceProvider::NoError on + success or an appropriate QGeoServiceProvider::Error on failure. + + If \a errorString is not 0 it should be set to a string describing any + error which occurred. + + The default implementation returns 0, which causes a + QGeoServiceProvider::NotSupportedError in QGeoServiceProvider. +*/ +QGeoRoutingManagerEngine *QGeoServiceProviderFactory::createRoutingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const + +{ + Q_UNUSED(parameters) + Q_UNUSED(error) + Q_UNUSED(errorString) + + return 0; +} + +/*! + Returns a new QPlaceManagerEngine instance, initialized with \a + parameters, which implements the place searching functionality. + + If \a error is not 0 it should be set to QGeoServiceProvider::NoError on + success or an appropriate QGeoServiceProvider::Error on failure. + + If \a errorString is not 0 it should be set to a string describing any + error which occurred. + + The default implementation returns 0, which causes a + QGeoServiceProvider::NotSupportedError in QGeoServiceProvider. +*/ +QPlaceManagerEngine *QGeoServiceProviderFactory::createPlaceManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const + +{ + Q_UNUSED(parameters) + Q_UNUSED(error) + Q_UNUSED(errorString) + + return 0; +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeoserviceproviderfactory.h b/src/location/maps/qgeoserviceproviderfactory.h new file mode 100644 index 0000000..cc60cf7 --- /dev/null +++ b/src/location/maps/qgeoserviceproviderfactory.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDERFACTORY_H +#define QGEOSERVICEPROVIDERFACTORY_H + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_LOCATION_EXPORT QGeoServiceProviderFactory +{ +public: + virtual ~QGeoServiceProviderFactory() {} + + virtual QGeoCodingManagerEngine *createGeocodingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + virtual QGeoMappingManagerEngine *createMappingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + virtual QGeoRoutingManagerEngine *createRoutingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + virtual QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; +}; + +Q_DECLARE_INTERFACE(QGeoServiceProviderFactory, + "org.qt-project.qt.geoservice.serviceproviderfactory/5.0") + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp new file mode 100644 index 0000000..a6cbb29 --- /dev/null +++ b/src/location/maps/qgeotiledmap.cpp @@ -0,0 +1,414 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeotiledmap_p.h" +#include "qgeotiledmap_p_p.h" + +#include "qgeotiledmappingmanagerengine_p.h" +#include "qabstractgeotilecache_p.h" +#include "qgeotilespec_p.h" + +#include "qgeocameratiles_p.h" +#include "qgeotilerequestmanager_p.h" +#include "qgeotiledmapscene_p.h" +#include "qgeocameracapabilities_p.h" +#include + +QT_BEGIN_NAMESPACE +#define PREFETCH_FRUSTUM_SCALE 2.0 + +QGeoTiledMap::QGeoTiledMap(QGeoTiledMappingManagerEngine *engine, QObject *parent) + : QGeoMap(*new QGeoTiledMapPrivate(engine), parent) +{ + Q_D(QGeoTiledMap); + + d->m_tileRequests = new QGeoTileRequestManager(this, engine); + + QObject::connect(engine,&QGeoTiledMappingManagerEngine::tileVersionChanged, + this,&QGeoTiledMap::handleTileVersionChanged); +} + +QGeoTiledMap::~QGeoTiledMap() +{ + Q_D(QGeoTiledMap); + delete d->m_tileRequests; + d->m_tileRequests = 0; + + if (!d->m_engine.isNull()) { + QGeoTiledMappingManagerEngine *engine = qobject_cast(d->m_engine); + Q_ASSERT(engine); + engine->releaseMap(this); + } +} + +QGeoTileRequestManager *QGeoTiledMap::requestManager() +{ + Q_D(QGeoTiledMap); + return d->m_tileRequests; +} + +void QGeoTiledMap::updateTile(const QGeoTileSpec &spec) +{ + Q_D(QGeoTiledMap); + d->updateTile(spec); +} + +void QGeoTiledMap::setPrefetchStyle(QGeoTiledMap::PrefetchStyle style) +{ + Q_D(QGeoTiledMap); + d->m_prefetchStyle = style; +} + +QAbstractGeoTileCache *QGeoTiledMap::tileCache() +{ + Q_D(QGeoTiledMap); + return d->m_cache; +} + +QSGNode *QGeoTiledMap::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window) +{ + Q_D(QGeoTiledMap); + return d->updateSceneGraph(oldNode, window); +} + +void QGeoTiledMap::prefetchData() +{ + Q_D(QGeoTiledMap); + d->prefetchTiles(); +} + +void QGeoTiledMap::clearData() +{ + Q_D(QGeoTiledMap); + d->m_cache->clearAll(); + d->m_mapScene->clearTexturedTiles(); +} + +void QGeoTiledMap::handleTileVersionChanged() +{ + Q_D(QGeoTiledMap); + if (!d->m_engine.isNull()) { + QGeoTiledMappingManagerEngine* engine = qobject_cast(d->m_engine); + Q_ASSERT(engine); + d->changeTileVersion(engine->tileVersion()); + } +} + +void QGeoTiledMap::evaluateCopyrights(const QSet &visibleTiles) +{ + Q_UNUSED(visibleTiles); +} + +QGeoCoordinate QGeoTiledMap::itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport) const +{ + Q_D(const QGeoTiledMap); + if (clipToViewport) { + int w = width(); + int h = height(); + + if ((pos.x() < 0) || (w < pos.x()) || (pos.y() < 0) || (h < pos.y())) + return QGeoCoordinate(); + } + + return d->itemPositionToCoordinate(pos); +} + +QDoubleVector2D QGeoTiledMap::coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport) const +{ + Q_D(const QGeoTiledMap); + QDoubleVector2D pos = d->coordinateToItemPosition(coordinate); + + if (clipToViewport) { + int w = width(); + int h = height(); + double x = pos.x(); + double y = pos.y(); + if ((x < 0.0) || (x > w) || (y < 0) || (y > h) || qIsNaN(x) || qIsNaN(y)) + return QDoubleVector2D(qQNaN(), qQNaN()); + } + + return pos; +} + +// This method returns the minimum zoom level that this specific qgeomap type allows +// at a given canvas size (width,height) and for a given tile size (usually 256). +double QGeoTiledMap::minimumZoomForMapSize(int width, int height) const +{ + Q_D(const QGeoTiledMap); + double maxSize = qMax(width,height); + double numTiles = maxSize / d->m_visibleTiles->tileSize(); + return std::log(numTiles) / std::log(2.0); +} + +// This method recalculates the "no-trespassing" limits for the map center. +// This has to be done when: +// 1) the map is resized, because the meters per pixel remain the same, but +// the amount of pixels between the center and the borders changes +// 2) when the zoom level changes, because the amount of pixels between the center +// and the borders stays the same, but the meters per pixel change +double QGeoTiledMap::maximumLatitudeForZoom(double zoomLevel) const +{ + Q_D(const QGeoTiledMap); + double mapEdgeSize = std::pow(2.0,zoomLevel); + mapEdgeSize *= d->m_visibleTiles->tileSize(); + + // At init time weird things happen + int clampedWindowHeight = (height() > mapEdgeSize) ? mapEdgeSize : height(); + + // Use the window height divided by 2 as the topmost allowed center, with respect to the map size in pixels + double mercatorTopmost = (clampedWindowHeight * 0.5) / mapEdgeSize ; + QGeoCoordinate topMost = QGeoProjection::mercatorToCoord(QDoubleVector2D(0.0,mercatorTopmost)); + + return topMost.latitude(); +} + +QDoubleVector2D QGeoTiledMap::referenceCoordinateToItemPosition(const QGeoCoordinate &coordinate) const +{ + Q_D(const QGeoTiledMap); + QDoubleVector2D point = QGeoProjection::coordToMercator(coordinate); + return point * std::pow(2.0, d->m_cameraData.zoomLevel()) * d->m_visibleTiles->tileSize(); +} + +QGeoCoordinate QGeoTiledMap::referenceItemPositionToCoordinate(const QDoubleVector2D &pos) const +{ + Q_D(const QGeoTiledMap); + QDoubleVector2D point = pos / (std::pow(2.0, d->m_cameraData.zoomLevel()) * d->m_visibleTiles->tileSize()); + return QGeoProjection::mercatorToCoord(point); +} + +QGeoTiledMapPrivate::QGeoTiledMapPrivate(QGeoTiledMappingManagerEngine *engine) + : QGeoMapPrivate(engine), + m_cache(engine->tileCache()), + m_visibleTiles(new QGeoCameraTiles()), + m_prefetchTiles(new QGeoCameraTiles()), + m_mapScene(new QGeoTiledMapScene()), + m_tileRequests(0), + m_maxZoomLevel(static_cast(std::ceil(engine->cameraCapabilities().maximumZoomLevel()))), + m_minZoomLevel(static_cast(std::ceil(engine->cameraCapabilities().minimumZoomLevel()))), + m_prefetchStyle(QGeoTiledMap::PrefetchTwoNeighbourLayers) +{ + int tileSize = engine->tileSize().width(); + QString pluginString(engine->managerName() + QLatin1Char('_') + QString::number(engine->managerVersion())); + m_visibleTiles->setTileSize(tileSize); + m_prefetchTiles->setTileSize(tileSize); + m_visibleTiles->setPluginString(pluginString); + m_prefetchTiles->setPluginString(pluginString); + m_mapScene->setTileSize(tileSize); +} + +QGeoTiledMapPrivate::~QGeoTiledMapPrivate() +{ + // controller_ is a child of map_, don't need to delete it here + + delete m_mapScene; + delete m_visibleTiles; + delete m_prefetchTiles; + + // TODO map items are not deallocated! + // However: how to ensure this is done in rendering thread? +} + +void QGeoTiledMapPrivate::prefetchTiles() +{ + if (m_tileRequests) { + + QSet tiles; + QGeoCameraData camera = m_visibleTiles->cameraData(); + int currentIntZoom = static_cast(std::floor(camera.zoomLevel())); + + m_prefetchTiles->setCameraData(camera); + m_prefetchTiles->setViewExpansion(PREFETCH_FRUSTUM_SCALE); + tiles = m_prefetchTiles->createTiles(); + + switch (m_prefetchStyle) { + + case QGeoTiledMap::PrefetchNeighbourLayer: { + double zoomFraction = camera.zoomLevel() - currentIntZoom; + int nearestNeighbourLayer = zoomFraction > 0.5 ? currentIntZoom + 1 : currentIntZoom - 1; + if (nearestNeighbourLayer <= m_maxZoomLevel && nearestNeighbourLayer >= m_minZoomLevel) { + camera.setZoomLevel(nearestNeighbourLayer); + // Approx heuristic, keeping total # prefetched tiles roughly independent of the + // fractional zoom level. + double neighbourScale = (1.0 + zoomFraction)/2.0; + m_prefetchTiles->setCameraData(camera); + m_prefetchTiles->setViewExpansion(PREFETCH_FRUSTUM_SCALE * neighbourScale); + tiles += m_prefetchTiles->createTiles(); + } + } + break; + + case QGeoTiledMap::PrefetchTwoNeighbourLayers: { + // This is a simpler strategy, we just prefetch from layer above and below + // for the layer below we only use half the size as this fills the screen + if (currentIntZoom > m_minZoomLevel) { + camera.setZoomLevel(currentIntZoom - 1); + m_prefetchTiles->setCameraData(camera); + m_prefetchTiles->setViewExpansion(0.5); + tiles += m_prefetchTiles->createTiles(); + } + + if (currentIntZoom < m_maxZoomLevel) { + camera.setZoomLevel(currentIntZoom + 1); + m_prefetchTiles->setCameraData(camera); + m_prefetchTiles->setViewExpansion(1.0); + tiles += m_prefetchTiles->createTiles(); + } + + } + } + + m_tileRequests->requestTiles(tiles - m_mapScene->texturedTiles()); + } +} + +void QGeoTiledMapPrivate::changeCameraData(const QGeoCameraData &cameraData) +{ + Q_Q(QGeoTiledMap); + + // For zoomlevel, "snap" 0.01 either side of a whole number. + // This is so that when we turn off bilinear scaling, we're + // snapped to the exact pixel size of the tiles + QGeoCameraData cam = cameraData; + int izl = static_cast(std::floor(cam.zoomLevel())); + float delta = cam.zoomLevel() - izl; + + if (delta > 0.5) { + izl++; + delta -= 1.0; + } + if (qAbs(delta) < 0.01) { + cam.setZoomLevel(izl); + } + + m_visibleTiles->setCameraData(cam); + m_mapScene->setCameraData(cam); + + updateScene(); + q->sgNodeChanged(); +} + +void QGeoTiledMapPrivate::updateScene() +{ + Q_Q(QGeoTiledMap); + // detect if new tiles introduced + const QSet& tiles = m_visibleTiles->createTiles(); + bool newTilesIntroduced = !m_mapScene->visibleTiles().contains(tiles); + m_mapScene->setVisibleTiles(tiles); + + if (newTilesIntroduced) + q->evaluateCopyrights(tiles); + + // don't request tiles that are already built and textured + QList > cachedTiles = + m_tileRequests->requestTiles(m_visibleTiles->createTiles() - m_mapScene->texturedTiles()); + + foreach (const QSharedPointer &tex, cachedTiles) { + m_mapScene->addTile(tex->spec, tex); + } + + if (!cachedTiles.isEmpty()) + emit q->sgNodeChanged(); +} + +void QGeoTiledMapPrivate::changeActiveMapType(const QGeoMapType mapType) +{ + m_visibleTiles->setMapType(mapType); + m_prefetchTiles->setMapType(mapType); + updateScene(); +} + +void QGeoTiledMapPrivate::changeTileVersion(int version) +{ + m_visibleTiles->setMapVersion(version); + m_prefetchTiles->setMapVersion(version); + updateScene(); +} + +void QGeoTiledMapPrivate::changeMapSize(const QSize& size) +{ + Q_Q(QGeoTiledMap); + + m_visibleTiles->setScreenSize(size); + m_prefetchTiles->setScreenSize(size); + m_mapScene->setScreenSize(size); + + + if (!size.isEmpty() && m_cache) { + // absolute minimum size: one tile each side of display, 32-bit colour + int texCacheSize = (size.width() + m_visibleTiles->tileSize() * 2) * + (size.height() + m_visibleTiles->tileSize() * 2) * 4; + + // multiply by 3 so the 'recent' list in the cache is big enough for + // an entire display of tiles + texCacheSize *= 3; + // TODO: move this reasoning into the tilecache + + int newSize = qMax(m_cache->minTextureUsage(), texCacheSize); + m_cache->setMinTextureUsage(newSize); + } + + q->evaluateCopyrights(m_visibleTiles->createTiles()); + updateScene(); +} + +void QGeoTiledMapPrivate::updateTile(const QGeoTileSpec &spec) +{ + Q_Q(QGeoTiledMap); + // Only promote the texture up to GPU if it is visible + if (m_visibleTiles->createTiles().contains(spec)){ + QSharedPointer tex = m_tileRequests->tileTexture(spec); + if (!tex.isNull()) { + m_mapScene->addTile(spec, tex); + emit q->sgNodeChanged(); + } + } +} + +QSGNode *QGeoTiledMapPrivate::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window) +{ + return m_mapScene->updateSceneGraph(oldNode, window); +} + +QGeoCoordinate QGeoTiledMapPrivate::itemPositionToCoordinate(const QDoubleVector2D &pos) const +{ + return QGeoProjection::mercatorToCoord(m_mapScene->itemPositionToMercator(pos)); +} + +QDoubleVector2D QGeoTiledMapPrivate::coordinateToItemPosition(const QGeoCoordinate &coordinate) const +{ + return m_mapScene->mercatorToItemPosition(QGeoProjection::coordToMercator(coordinate)); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotiledmap_p.h b/src/location/maps/qgeotiledmap_p.h new file mode 100644 index 0000000..813e342 --- /dev/null +++ b/src/location/maps/qgeotiledmap_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOTILEDMAP_P_H +#define QGEOTILEDMAP_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include "qgeomap_p.h" +#include "qgeocameradata_p.h" +#include "qgeomaptype_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoTileSpec; +class QGeoTileTexture; +class QAbstractGeoTileCache; +class QGeoTiledMapPrivate; +class QGeoTiledMappingManagerEngine; +class QGeoTileRequestManager; + +class QQuickWindow; +class QSGNode; + +class QPointF; + +class Q_LOCATION_EXPORT QGeoTiledMap : public QGeoMap +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGeoTiledMap) +public: + enum PrefetchStyle { PrefetchNeighbourLayer, PrefetchTwoNeighbourLayers }; + QGeoTiledMap(QGeoTiledMappingManagerEngine *engine, QObject *parent); + virtual ~QGeoTiledMap(); + + QAbstractGeoTileCache *tileCache(); + QGeoTileRequestManager *requestManager(); + void updateTile(const QGeoTileSpec &spec); + void setPrefetchStyle(PrefetchStyle style); + + QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const Q_DECL_OVERRIDE; + QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const Q_DECL_OVERRIDE; + + double minimumZoomForMapSize(int width, int height) const Q_DECL_OVERRIDE; + double maximumLatitudeForZoom(double zoomLevel) const Q_DECL_OVERRIDE; + + QDoubleVector2D referenceCoordinateToItemPosition(const QGeoCoordinate &coordinate) const Q_DECL_OVERRIDE; + QGeoCoordinate referenceItemPositionToCoordinate(const QDoubleVector2D &pos) const Q_DECL_OVERRIDE; + + void prefetchData() Q_DECL_OVERRIDE; + void clearData() Q_DECL_OVERRIDE; + +protected: + QSGNode *updateSceneGraph(QSGNode *, QQuickWindow *window) Q_DECL_OVERRIDE; + virtual void evaluateCopyrights(const QSet &visibleTiles); + +private Q_SLOTS: + void handleTileVersionChanged(); + +private: + Q_DISABLE_COPY(QGeoTiledMap) + +}; + +QT_END_NAMESPACE + +#endif // QGEOMAP_P_H diff --git a/src/location/maps/qgeotiledmap_p_p.h b/src/location/maps/qgeotiledmap_p_p.h new file mode 100644 index 0000000..c1b190b --- /dev/null +++ b/src/location/maps/qgeotiledmap_p_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOTILEDMAP_P_P_H +#define QGEOTILEDMAP_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeomap_p_p.h" +#include "qgeocameradata_p.h" +#include "qgeomaptype_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCameraTiles; +class QGeoTiledMapScene; +class QAbstractGeoTileCache; +class QGeoTiledMappingManagerEngine; +class QGeoTiledMap; +class QGeoTileRequestManager; +class QGeoTileSpec; +class QSGNode; +class QQuickWindow; + +class QGeoTiledMapPrivate : public QGeoMapPrivate +{ + Q_DECLARE_PUBLIC(QGeoTiledMap) +public: + QGeoTiledMapPrivate(QGeoTiledMappingManagerEngine *engine); + ~QGeoTiledMapPrivate(); + + QSGNode *updateSceneGraph(QSGNode *node, QQuickWindow *window); + + QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos) const; + QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate) const; + + void updateTile(const QGeoTileSpec &spec); + void prefetchTiles(); + +protected: + void changeMapSize(const QSize& size) Q_DECL_OVERRIDE; + void changeCameraData(const QGeoCameraData &cameraData) Q_DECL_OVERRIDE; + void changeActiveMapType(const QGeoMapType mapType) Q_DECL_OVERRIDE; + void changeTileVersion(int version); + +private: + void updateScene(); + +private: + QAbstractGeoTileCache *m_cache; + QGeoCameraTiles *m_visibleTiles; + QGeoCameraTiles *m_prefetchTiles; + QGeoTiledMapScene *m_mapScene; + QGeoTileRequestManager *m_tileRequests; + int m_maxZoomLevel; + int m_minZoomLevel; + QGeoTiledMap::PrefetchStyle m_prefetchStyle; + bool m_geomoteryUpdated; + Q_DISABLE_COPY(QGeoTiledMapPrivate) +}; + +QT_END_NAMESPACE + +#endif // QGEOTILEDMAP_P_P_H diff --git a/src/location/maps/qgeotiledmappingmanagerengine.cpp b/src/location/maps/qgeotiledmappingmanagerengine.cpp new file mode 100644 index 0000000..dc5f188 --- /dev/null +++ b/src/location/maps/qgeotiledmappingmanagerengine.cpp @@ -0,0 +1,328 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotiledmappingmanagerengine_p.h" +#include "qgeotiledmappingmanagerengine_p_p.h" +#include "qgeotilefetcher_p.h" + + +#include "qgeotiledmap_p.h" +#include "qgeotilerequestmanager_p.h" +#include "qgeofiletilecache_p.h" +#include "qgeotilespec_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoTiledMappingManagerEngine::QGeoTiledMappingManagerEngine(QObject *parent) + : QGeoMappingManagerEngine(parent), + d_ptr(new QGeoTiledMappingManagerEnginePrivate) +{ +} + +/*! + Destroys this mapping manager. +*/ +QGeoTiledMappingManagerEngine::~QGeoTiledMappingManagerEngine() +{ + delete d_ptr; +} + +/*! + Sets the tile fetcher. Takes ownership of the QObject. +*/ +void QGeoTiledMappingManagerEngine::setTileFetcher(QGeoTileFetcher *fetcher) +{ + Q_D(QGeoTiledMappingManagerEngine); + + if (d->fetcher_) + d->fetcher_->deleteLater(); + fetcher->setParent(this); + d->fetcher_ = fetcher; + + qRegisterMetaType(); + + connect(d->fetcher_, + SIGNAL(tileFinished(QGeoTileSpec,QByteArray,QString)), + this, + SLOT(engineTileFinished(QGeoTileSpec,QByteArray,QString)), + Qt::QueuedConnection); + connect(d->fetcher_, + SIGNAL(tileError(QGeoTileSpec,QString)), + this, + SLOT(engineTileError(QGeoTileSpec,QString)), + Qt::QueuedConnection); + + engineInitialized(); +} + +QGeoTileFetcher *QGeoTiledMappingManagerEngine::tileFetcher() +{ + Q_D(QGeoTiledMappingManagerEngine); + return d->fetcher_; +} + +QGeoMap *QGeoTiledMappingManagerEngine::createMap() +{ + return NULL; +} + +void QGeoTiledMappingManagerEngine::releaseMap(QGeoTiledMap *map) +{ + d_ptr->mapHash_.remove(map); + + QHash > newTileHash = d_ptr->tileHash_; + typedef QHash >::const_iterator h_iter; + h_iter hi = d_ptr->tileHash_.constBegin(); + h_iter hend = d_ptr->tileHash_.constEnd(); + for (; hi != hend; ++hi) { + QSet maps = hi.value(); + if (maps.contains(map)) { + maps.remove(map); + if (maps.isEmpty()) + newTileHash.remove(hi.key()); + else + newTileHash.insert(hi.key(), maps); + } + } + d_ptr->tileHash_ = newTileHash; +} + +void QGeoTiledMappingManagerEngine::updateTileRequests(QGeoTiledMap *map, + const QSet &tilesAdded, + const QSet &tilesRemoved) +{ + Q_D(QGeoTiledMappingManagerEngine); + + typedef QSet::const_iterator tile_iter; + + // add and remove tiles from tileset for this map + + QSet oldTiles = d->mapHash_.value(map); + + tile_iter rem = tilesRemoved.constBegin(); + tile_iter remEnd = tilesRemoved.constEnd(); + for (; rem != remEnd; ++rem) { + oldTiles.remove(*rem); + } + + tile_iter add = tilesAdded.constBegin(); + tile_iter addEnd = tilesAdded.constEnd(); + for (; add != addEnd; ++add) { + oldTiles.insert(*add); + } + + d->mapHash_.insert(map, oldTiles); + + // add and remove map from mapset for the tiles + + QSet reqTiles; + QSet cancelTiles; + + rem = tilesRemoved.constBegin(); + for (; rem != remEnd; ++rem) { + QSet mapSet = d->tileHash_.value(*rem); + mapSet.remove(map); + if (mapSet.isEmpty()) { + cancelTiles.insert(*rem); + d->tileHash_.remove(*rem); + } else { + d->tileHash_.insert(*rem, mapSet); + } + } + + add = tilesAdded.constBegin(); + for (; add != addEnd; ++add) { + QSet mapSet = d->tileHash_.value(*add); + if (mapSet.isEmpty()) { + reqTiles.insert(*add); + } + mapSet.insert(map); + d->tileHash_.insert(*add, mapSet); + } + + cancelTiles -= reqTiles; + + QMetaObject::invokeMethod(d->fetcher_, "updateTileRequests", + Qt::QueuedConnection, + Q_ARG(QSet, reqTiles), + Q_ARG(QSet, cancelTiles)); +} + +void QGeoTiledMappingManagerEngine::engineTileFinished(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format) +{ + Q_D(QGeoTiledMappingManagerEngine); + + QSet maps = d->tileHash_.value(spec); + + typedef QSet::const_iterator map_iter; + + map_iter map = maps.constBegin(); + map_iter mapEnd = maps.constEnd(); + for (; map != mapEnd; ++map) { + QSet tileSet = d->mapHash_.value(*map); + tileSet.remove(spec); + if (tileSet.isEmpty()) + d->mapHash_.remove(*map); + else + d->mapHash_.insert(*map, tileSet); + } + + d->tileHash_.remove(spec); + tileCache()->insert(spec, bytes, format, d->cacheHint_); + + map = maps.constBegin(); + mapEnd = maps.constEnd(); + for (; map != mapEnd; ++map) { + (*map)->requestManager()->tileFetched(spec); + } +} + +void QGeoTiledMappingManagerEngine::engineTileError(const QGeoTileSpec &spec, const QString &errorString) +{ + Q_D(QGeoTiledMappingManagerEngine); + + QSet maps = d->tileHash_.value(spec); + typedef QSet::const_iterator map_iter; + map_iter map = maps.constBegin(); + map_iter mapEnd = maps.constEnd(); + for (; map != mapEnd; ++map) { + QSet tileSet = d->mapHash_.value(*map); + + tileSet.remove(spec); + if (tileSet.isEmpty()) + d->mapHash_.remove(*map); + else + d->mapHash_.insert(*map, tileSet); + } + d->tileHash_.remove(spec); + + for (map = maps.constBegin(); map != mapEnd; ++map) { + (*map)->requestManager()->tileError(spec, errorString); + } + + emit tileError(spec, errorString); +} + +void QGeoTiledMappingManagerEngine::setTileSize(const QSize &tileSize) +{ + Q_D(QGeoTiledMappingManagerEngine); + d->tileSize_ = tileSize; +} + +void QGeoTiledMappingManagerEngine::setTileVersion(int version) +{ + Q_D(QGeoTiledMappingManagerEngine); + if (d->m_tileVersion != version) { + d->m_tileVersion = version; + emit tileVersionChanged(); + } +} + +QSize QGeoTiledMappingManagerEngine::tileSize() const +{ + Q_D(const QGeoTiledMappingManagerEngine); + return d->tileSize_; +} + +int QGeoTiledMappingManagerEngine::tileVersion() const +{ + Q_D(const QGeoTiledMappingManagerEngine); + return d->m_tileVersion; +} + +QGeoTiledMappingManagerEngine::CacheAreas QGeoTiledMappingManagerEngine::cacheHint() const +{ + Q_D(const QGeoTiledMappingManagerEngine); + return d->cacheHint_; +} + +void QGeoTiledMappingManagerEngine::setCacheHint(QGeoTiledMappingManagerEngine::CacheAreas cacheHint) +{ + Q_D(QGeoTiledMappingManagerEngine); + d->cacheHint_ = cacheHint; +} + +/*! + Sets the tile cache. Takes ownership of the QObject. +*/ +void QGeoTiledMappingManagerEngine::setTileCache(QAbstractGeoTileCache *cache) +{ + Q_D(QGeoTiledMappingManagerEngine); + Q_ASSERT_X(!d->tileCache_, Q_FUNC_INFO, "This should be called only once"); + cache->setParent(this); + d->tileCache_ = cache; +} + +QAbstractGeoTileCache *QGeoTiledMappingManagerEngine::tileCache() +{ + Q_D(QGeoTiledMappingManagerEngine); + if (!d->tileCache_) { + QString cacheDirectory; + if (!managerName().isEmpty()) + cacheDirectory = QAbstractGeoTileCache::baseCacheDirectory() + managerName(); + d->tileCache_ = new QGeoFileTileCache(cacheDirectory); + } + return d->tileCache_; +} + +QSharedPointer QGeoTiledMappingManagerEngine::getTileTexture(const QGeoTileSpec &spec) +{ + return d_ptr->tileCache_->get(spec); +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoTiledMappingManagerEnginePrivate::QGeoTiledMappingManagerEnginePrivate() +: m_tileVersion(-1), + cacheHint_(QGeoTiledMappingManagerEngine::AllCaches), + tileCache_(0), + fetcher_(0) +{ +} + +QGeoTiledMappingManagerEnginePrivate::~QGeoTiledMappingManagerEnginePrivate() +{ +} + +#include "moc_qgeotiledmappingmanagerengine_p.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotiledmappingmanagerengine_p.h b/src/location/maps/qgeotiledmappingmanagerengine_p.h new file mode 100644 index 0000000..86c5b63 --- /dev/null +++ b/src/location/maps/qgeotiledmappingmanagerengine_p.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEDMAPPINGMANAGERENGINE_H +#define QGEOTILEDMAPPINGMANAGERENGINE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include "qgeomaptype_p.h" +#include "qgeomappingmanagerengine_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoTiledMappingManagerEnginePrivate; +class QGeoMapRequestOptions; +class QGeoTileFetcher; +class QGeoTileTexture; + +class QGeoTileSpec; +class QGeoTiledMap; +class QAbstractGeoTileCache; + +class Q_LOCATION_EXPORT QGeoTiledMappingManagerEngine : public QGeoMappingManagerEngine +{ + Q_OBJECT + +public: + enum CacheArea { + DiskCache = 0x01, + MemoryCache = 0x02, + AllCaches = 0xFF + }; + Q_DECLARE_FLAGS(CacheAreas, CacheArea) + + explicit QGeoTiledMappingManagerEngine(QObject *parent = 0); + virtual ~QGeoTiledMappingManagerEngine(); + + QGeoTileFetcher *tileFetcher(); + + QGeoMap *createMap() Q_DECL_OVERRIDE; + void releaseMap(QGeoTiledMap *map); + + QSize tileSize() const; + int tileVersion() const; + + void updateTileRequests(QGeoTiledMap *map, + const QSet &tilesAdded, + const QSet &tilesRemoved); + + QAbstractGeoTileCache *tileCache(); + QSharedPointer getTileTexture(const QGeoTileSpec &spec); + + + QGeoTiledMappingManagerEngine::CacheAreas cacheHint() const; + +private Q_SLOTS: + void engineTileFinished(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format); + void engineTileError(const QGeoTileSpec &spec, const QString &errorString); + +Q_SIGNALS: + void tileError(const QGeoTileSpec &spec, const QString &errorString); + void tileVersionChanged(); + +protected: + void setTileFetcher(QGeoTileFetcher *fetcher); + void setTileSize(const QSize &tileSize); + void setTileVersion(int version); + void setCacheHint(QGeoTiledMappingManagerEngine::CacheAreas cacheHint); + void setTileCache(QAbstractGeoTileCache *cache); + +private: + QGeoTiledMappingManagerEnginePrivate *d_ptr; + + Q_DECLARE_PRIVATE(QGeoTiledMappingManagerEngine) + Q_DISABLE_COPY(QGeoTiledMappingManagerEngine) + + friend class QGeoTileFetcher; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoTiledMappingManagerEngine::CacheAreas) + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeotiledmappingmanagerengine_p_p.h b/src/location/maps/qgeotiledmappingmanagerengine_p_p.h new file mode 100644 index 0000000..86ad0f0 --- /dev/null +++ b/src/location/maps/qgeotiledmappingmanagerengine_p_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QGEOTILEDMAPPINGMANAGER_P_H +#define QGEOTILEDMAPPINGMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include "qgeotiledmappingmanagerengine_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoTiledMap; +class QAbstractGeoTileCache; +class QGeoTileSpec; +class QGeoTileFetcher; + +class QGeoTiledMappingManagerEnginePrivate +{ +public: + QGeoTiledMappingManagerEnginePrivate(); + ~QGeoTiledMappingManagerEnginePrivate(); + + QSize tileSize_; + int m_tileVersion; + QHash > mapHash_; + QHash > tileHash_; + QGeoTiledMappingManagerEngine::CacheAreas cacheHint_; + QAbstractGeoTileCache *tileCache_; + QGeoTileFetcher *fetcher_; + +private: + Q_DISABLE_COPY(QGeoTiledMappingManagerEnginePrivate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeotiledmapreply.cpp b/src/location/maps/qgeotiledmapreply.cpp new file mode 100644 index 0000000..f2dfd9e --- /dev/null +++ b/src/location/maps/qgeotiledmapreply.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotiledmapreply_p.h" +#include "qgeotiledmapreply_p_p.h" + +#include + +QT_BEGIN_NAMESPACE +/*! + \class QGeoTiledMapReply + \inmodule QtLocation + \ingroup QtLocation-impl + \since 5.6 + \internal + + \brief The QGeoTiledMapReply class manages a tile fetch operation started + by an instance of QGeoTiledManagerEngine. + + Instances of QGeoTiledMapReply manage the state and results of these + operations. + + The isFinished(), error() and errorString() methods provide information + on whether the operation has completed and if it completed successfully. + + The finished() and error(QGeoTiledMapReply::Error,QString) + signals can be used to monitor the progress of the operation. + + It is possible that a newly created QGeoTiledMapReply may be in a finished + state, most commonly because an error has occurred. Since such an instance + will never emit the finished() or + error(QGeoTiledMapReply::Error,QString) signals, it is + important to check the result of isFinished() before making the connections + to the signals. + + If the operation completes successfully the results are accessed by + mapImageData() and mapImageFormat(). +*/ + +/*! + \enum QGeoTiledMapReply::Error + + Describes an error which prevented the completion of the operation. + + \value NoError + No error has occurred. + \value CommunicationError + An error occurred while communicating with the service provider. + \value ParseError + The response from the service provider was in an unrecognizable format + supported by the service provider. + \value UnknownError + An error occurred which does not fit into any of the other categories. +*/ + +/*! + Constructs a tiled map reply object based on \a request, with parent \a parent. +*/ +QGeoTiledMapReply::QGeoTiledMapReply(const QGeoTileSpec &spec, QObject *parent) + : QObject(parent), + d_ptr(new QGeoTiledMapReplyPrivate(spec)) +{ +} + +/*! + Constructs a tiled map reply object with a given \a error and \a errorString and the specified \a parent. +*/ +QGeoTiledMapReply::QGeoTiledMapReply(Error error, const QString &errorString, QObject *parent) + : QObject(parent), + d_ptr(new QGeoTiledMapReplyPrivate(error, errorString)) {} + +/*! + Destroys this tiled map reply object. +*/ +QGeoTiledMapReply::~QGeoTiledMapReply() +{ + delete d_ptr; +} + +/*! + Sets whether or not this reply has finished to \a finished. + + If \a finished is true, this will cause the finished() signal to be + emitted. + + If the operation completed successfully, + QGeoTiledMapReply::setMapImageData() should be called before this + function. If an error occurred, QGeoTiledMapReply::setError() should be used + instead. +*/ +void QGeoTiledMapReply::setFinished(bool finished) +{ + d_ptr->isFinished = finished; + if (d_ptr->isFinished) + emit this->finished(); +} + +/*! + Return true if the operation completed successfully or encountered an + error which cause the operation to come to a halt. +*/ +bool QGeoTiledMapReply::isFinished() const +{ + return d_ptr->isFinished; +} + +/*! + Sets the error state of this reply to \a error and the textual + representation of the error to \a errorString. + + This will also cause error() and finished() signals to be emitted, in that + order. +*/ +void QGeoTiledMapReply::setError(QGeoTiledMapReply::Error error, const QString &errorString) +{ + d_ptr->error = error; + d_ptr->errorString = errorString; + emit this->error(error, errorString); + setFinished(true); +} + +/*! + Returns the error state of this reply. + + If the result is QGeoTiledMapReply::NoError then no error has occurred. +*/ +QGeoTiledMapReply::Error QGeoTiledMapReply::error() const +{ + return d_ptr->error; +} + +/*! + Returns the textual representation of the error state of this reply. + + If no error has occurred this will return an empty string. It is possible + that an error occurred which has no associated textual representation, in + which case this will also return an empty string. + + To determine whether an error has occurred, check to see if + QGeoTiledMapReply::error() is equal to QGeoTiledMapReply::NoError. +*/ +QString QGeoTiledMapReply::errorString() const +{ + return d_ptr->errorString; +} + +/*! + Returns whether the reply is coming from a cache. +*/ +bool QGeoTiledMapReply::isCached() const +{ + return d_ptr->isCached; +} + +/*! + Sets whether the reply is coming from a cache to \a cached. +*/ +void QGeoTiledMapReply::setCached(bool cached) +{ + d_ptr->isCached = cached; +} + +/*! + Returns the request which corresponds to this reply. +*/ +QGeoTileSpec QGeoTiledMapReply::tileSpec() const +{ + return d_ptr->spec; +} + +/*! + Returns the tile image data. +*/ +QByteArray QGeoTiledMapReply::mapImageData() const +{ + return d_ptr->mapImageData; +} + +/*! + Sets the tile image data to \a data. +*/ +void QGeoTiledMapReply::setMapImageData(const QByteArray &data) +{ + d_ptr->mapImageData = data; +} + +/*! + Returns the format of the tile image. +*/ +QString QGeoTiledMapReply::mapImageFormat() const +{ + return d_ptr->mapImageFormat; +} + +/*! + Sets the format of the tile image to \a format. +*/ +void QGeoTiledMapReply::setMapImageFormat(const QString &format) +{ + d_ptr->mapImageFormat = format; +} + +/*! + Cancels the operation immediately. + + This will do nothing if the reply is finished. +*/ +void QGeoTiledMapReply::abort() +{ + if (!isFinished()) + setFinished(true); +} + +/* + \fn void QGeoTiledMapReply::finished() + + This signal is emitted when this reply has finished processing. + + If error() equals QGeoTiledMapReply::NoError then the processing + finished successfully. + + This signal and QGeoRoutingManager::finished() will be + emitted at the same time. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. + + \fn void QGeoTiledMapReply::error(QGeoTiledMapReply::Error error, const QString &errorString) + + This signal is emitted when an error has been detected in the processing of + this reply. The finished() signal will probably follow. + + The error will be described by the error code \a error. If \a errorString is + not empty it will contain a textual description of the error. + + This signal and QGeoRoutingManager::error() will be emitted at the same time. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ + +/*! + \fn void QGeoTiledMapReply::finished() + + This signal is emitted when this reply has finished processing. + + If error() equals QGeoTiledMapReply::NoError then the processing + finished successfully. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ +/*! + \fn void QGeoTiledMapReply::error(QGeoTiledMapReply::Error error, const QString &errorString) + + This signal is emitted when an error has been detected in the processing of + this reply. The finished() signal will probably follow. + + The error will be described by the error code \a error. If \a errorString is + not empty it will contain a textual description of the error. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ + +/******************************************************************************* +*******************************************************************************/ + +QGeoTiledMapReplyPrivate::QGeoTiledMapReplyPrivate(const QGeoTileSpec &spec) + : error(QGeoTiledMapReply::NoError), + isFinished(false), + isCached(false), + spec(spec) {} + +QGeoTiledMapReplyPrivate::QGeoTiledMapReplyPrivate(QGeoTiledMapReply::Error error, const QString &errorString) + : error(error), + errorString(errorString), + isFinished(true), + isCached(false) {} + +QGeoTiledMapReplyPrivate::~QGeoTiledMapReplyPrivate() {} + +#include "moc_qgeotiledmapreply_p.cpp" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotiledmapreply_p.h b/src/location/maps/qgeotiledmapreply_p.h new file mode 100644 index 0000000..91852cc --- /dev/null +++ b/src/location/maps/qgeotiledmapreply_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEDMAPREPLY_H +#define QGEOTILEDMAPREPLY_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoTileSpec; +class QGeoTiledMapReplyPrivate; + +class Q_LOCATION_EXPORT QGeoTiledMapReply : public QObject +{ + Q_OBJECT + +public: + enum Error { + NoError, + CommunicationError, + ParseError, + UnknownError + }; + + QGeoTiledMapReply(const QGeoTileSpec &spec, QObject *parent = 0); + QGeoTiledMapReply(Error error, const QString &errorString, QObject *parent = 0); + virtual ~QGeoTiledMapReply(); + + bool isFinished() const; + Error error() const; + QString errorString() const; + + bool isCached() const; + + QGeoTileSpec tileSpec() const; + + QByteArray mapImageData() const; + QString mapImageFormat() const; + + virtual void abort(); + +Q_SIGNALS: + void finished(); + void error(QGeoTiledMapReply::Error error, const QString &errorString = QString()); + +protected: + void setError(Error error, const QString &errorString); + void setFinished(bool finished); + + void setCached(bool cached); + + void setMapImageData(const QByteArray &data); + void setMapImageFormat(const QString &format); + +private: + QGeoTiledMapReplyPrivate *d_ptr; + Q_DISABLE_COPY(QGeoTiledMapReply) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeotiledmapreply_p_p.h b/src/location/maps/qgeotiledmapreply_p_p.h new file mode 100644 index 0000000..5dcf5a7 --- /dev/null +++ b/src/location/maps/qgeotiledmapreply_p_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEDMAPREPLY_P_H +#define QGEOTILEDMAPREPLY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeotiledmapreply_p.h" +#include "qgeotilespec_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoTiledMapReplyPrivate +{ +public: + QGeoTiledMapReplyPrivate(const QGeoTileSpec &spec); + QGeoTiledMapReplyPrivate(QGeoTiledMapReply::Error error, const QString &errorString); + ~QGeoTiledMapReplyPrivate(); + + QGeoTiledMapReply::Error error; + QString errorString; + bool isFinished; + bool isCached; + + QGeoTileSpec spec; + QByteArray mapImageData; + QString mapImageFormat; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeotiledmapscene.cpp b/src/location/maps/qgeotiledmapscene.cpp new file mode 100644 index 0000000..57750f4 --- /dev/null +++ b/src/location/maps/qgeotiledmapscene.cpp @@ -0,0 +1,749 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2014 Jolla Ltd, author: +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeotiledmapscene_p.h" +#include "qgeocameradata_p.h" +#include "qabstractgeotilecache_p.h" +#include "qgeotilespec_p.h" +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoTiledMapScenePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGeoTiledMapScene) +public: + QGeoTiledMapScenePrivate(); + ~QGeoTiledMapScenePrivate(); + + QSize m_screenSize; // in pixels + int m_tileSize; // the pixel resolution for each tile + QGeoCameraData m_cameraData; + QSet m_visibleTiles; + + QDoubleVector3D m_cameraUp; + QDoubleVector3D m_cameraEye; + QDoubleVector3D m_cameraCenter; + QMatrix4x4 m_projectionMatrix; + + // scales up the tile geometry and the camera altitude, resulting in no visible effect + // other than to control the accuracy of the render by keeping the values in a sensible range + double m_scaleFactor; + + // rounded down, positive zoom is zooming in, corresponding to reduced altitude + int m_intZoomLevel; + + // mercatorToGrid transform + // the number of tiles in each direction for the whole map (earth) at the current zoom level. + // it is 1< > m_textures; + + // tilesToGrid transform + int m_minTileX; // the minimum tile index, i.e. 0 to sideLength which is 1<< zoomLevel + int m_minTileY; + int m_maxTileX; + int m_maxTileY; + int m_tileXWrapsBelow; // the wrap point as a tile index + + // cameraToGrid transform + double m_mercatorCenterX; // center of camera in grid space (0 to sideLength) + double m_mercatorCenterY; + double m_mercatorWidth; // width of camera in grid space (0 to sideLength) + double m_mercatorHeight; + + // screenToWindow transform + double m_screenOffsetX; // in pixels + double m_screenOffsetY; // in pixels + // cameraToScreen transform + double m_screenWidth; // in pixels + double m_screenHeight; // in pixels + + bool m_useVerticalLock; + bool m_verticalLock; + bool m_linearScaling; + + void addTile(const QGeoTileSpec &spec, QSharedPointer texture); + + QDoubleVector2D itemPositionToMercator(const QDoubleVector2D &pos) const; + QDoubleVector2D mercatorToItemPosition(const QDoubleVector2D &mercator) const; + + void setVisibleTiles(const QSet &tiles); + void removeTiles(const QSet &oldTiles); + bool buildGeometry(const QGeoTileSpec &spec, QSGGeometry::TexturedPoint2D *vertices); + void setTileBounds(const QSet &tiles); + void setupCamera(); +}; + +QGeoTiledMapScene::QGeoTiledMapScene(QObject *parent) + : QObject(*new QGeoTiledMapScenePrivate(),parent) +{ +} + +QGeoTiledMapScene::~QGeoTiledMapScene() +{ +} + +void QGeoTiledMapScene::setUseVerticalLock(bool lock) +{ + Q_D(QGeoTiledMapScene); + d->m_useVerticalLock = lock; +} + +void QGeoTiledMapScene::setScreenSize(const QSize &size) +{ + Q_D(QGeoTiledMapScene); + d->m_screenSize = size; +} + +void QGeoTiledMapScene::setTileSize(int tileSize) +{ + Q_D(QGeoTiledMapScene); + d->m_tileSize = tileSize; +} + +void QGeoTiledMapScene::setCameraData(const QGeoCameraData &cameraData) +{ + Q_D(QGeoTiledMapScene); + d->m_cameraData = cameraData; + d->m_intZoomLevel = static_cast(std::floor(d->m_cameraData.zoomLevel())); + float delta = cameraData.zoomLevel() - d->m_intZoomLevel; + d->m_linearScaling = qAbs(delta) > 0.05; + d->m_sideLength = 1 << d->m_intZoomLevel; +} + +void QGeoTiledMapScene::setVisibleTiles(const QSet &tiles) +{ + Q_D(QGeoTiledMapScene); + d->setVisibleTiles(tiles); +} + +const QSet &QGeoTiledMapScene::visibleTiles() const +{ + Q_D(const QGeoTiledMapScene); + return d->m_visibleTiles; +} + +void QGeoTiledMapScene::addTile(const QGeoTileSpec &spec, QSharedPointer texture) +{ + Q_D(QGeoTiledMapScene); + d->addTile(spec, texture); +} + +QDoubleVector2D QGeoTiledMapScene::itemPositionToMercator(const QDoubleVector2D &pos) const +{ + Q_D(const QGeoTiledMapScene); + return d->itemPositionToMercator(pos); +} + +QDoubleVector2D QGeoTiledMapScene::mercatorToItemPosition(const QDoubleVector2D &mercator) const +{ + Q_D(const QGeoTiledMapScene); + return d->mercatorToItemPosition(mercator); +} + +bool QGeoTiledMapScene::verticalLock() const +{ + Q_D(const QGeoTiledMapScene); + return d->m_verticalLock; +} + +QSet QGeoTiledMapScene::texturedTiles() +{ + Q_D(QGeoTiledMapScene); + QSet textured; + foreach (const QGeoTileSpec &tile, d->m_textures.keys()) { + textured += tile; + } + return textured; +} + +void QGeoTiledMapScene::clearTexturedTiles() +{ + Q_D(QGeoTiledMapScene); + d->m_textures.clear(); +} + +QGeoTiledMapScenePrivate::QGeoTiledMapScenePrivate() + : QObjectPrivate(), + m_tileSize(0), + m_scaleFactor(10.0), + m_intZoomLevel(0), + m_sideLength(0), + m_minTileX(-1), + m_minTileY(-1), + m_maxTileX(-1), + m_maxTileY(-1), + m_tileXWrapsBelow(0), + m_mercatorCenterX(0.0), + m_mercatorCenterY(0.0), + m_mercatorWidth(0.0), + m_mercatorHeight(0.0), + m_screenOffsetX(0.0), + m_screenOffsetY(0.0), + m_screenWidth(0.0), + m_screenHeight(0.0), + m_useVerticalLock(false), + m_verticalLock(false), + m_linearScaling(false) +{ +} + +QGeoTiledMapScenePrivate::~QGeoTiledMapScenePrivate() +{ +} + +QDoubleVector2D QGeoTiledMapScenePrivate::itemPositionToMercator(const QDoubleVector2D &pos) const +{ + double x = m_mercatorWidth * (((pos.x() - m_screenOffsetX) / m_screenWidth) - 0.5); + x += m_mercatorCenterX; + + if (x > 1.0 * m_sideLength) + x -= 1.0 * m_sideLength; + if (x < 0.0) + x += 1.0 * m_sideLength; + + x /= 1.0 * m_sideLength; + + double y = m_mercatorHeight * (((pos.y() - m_screenOffsetY) / m_screenHeight) - 0.5); + y += m_mercatorCenterY; + y /= 1.0 * m_sideLength; + + return QDoubleVector2D(x, y); +} + +QDoubleVector2D QGeoTiledMapScenePrivate::mercatorToItemPosition(const QDoubleVector2D &mercator) const +{ + double mx = m_sideLength * mercator.x(); + + double lb = m_mercatorCenterX - m_mercatorWidth / 2.0; + if (lb < 0.0) + lb += m_sideLength; + double ub = m_mercatorCenterX + m_mercatorWidth / 2.0; + if (m_sideLength < ub) + ub -= m_sideLength; + + double m = (mx - m_mercatorCenterX) / m_mercatorWidth; + + double mWrapLower = (mx - m_mercatorCenterX - m_sideLength) / m_mercatorWidth; + double mWrapUpper = (mx - m_mercatorCenterX + m_sideLength) / m_mercatorWidth; + + // correct for crossing dateline + if (qFuzzyCompare(ub - lb + 1.0, 1.0) || (ub < lb) ) { + if (m_mercatorCenterX < ub) { + if (lb < mx) { + m = mWrapLower; + } + } else if (lb < m_mercatorCenterX) { + if (mx <= ub) { + m = mWrapUpper; + } + } + } + + // apply wrapping if necessary so we don't return unreasonably large pos/neg screen positions + // also allows map items to be drawn properly if some of their coords are out of the screen + if ( qAbs(mWrapLower) < qAbs(m) ) + m = mWrapLower; + if ( qAbs(mWrapUpper) < qAbs(m) ) + m = mWrapUpper; + + double x = m_screenWidth * (0.5 + m); + double y = m_screenHeight * (0.5 + (m_sideLength * mercator.y() - m_mercatorCenterY) / m_mercatorHeight); + + return QDoubleVector2D(x + m_screenOffsetX, y + m_screenOffsetY); +} + +bool QGeoTiledMapScenePrivate::buildGeometry(const QGeoTileSpec &spec, QSGGeometry::TexturedPoint2D *vertices) +{ + int x = spec.x(); + + if (x < m_tileXWrapsBelow) + x += m_sideLength; + + if ((x < m_minTileX) + || (m_maxTileX < x) + || (spec.y() < m_minTileY) + || (m_maxTileY < spec.y()) + || (spec.zoom() != m_intZoomLevel)) { + return false; + } + + double edge = m_scaleFactor * m_tileSize; + + double x1 = (x - m_minTileX); + double x2 = x1 + 1.0; + + double y1 = (m_minTileY - spec.y()); + double y2 = y1 - 1.0; + + x1 *= edge; + x2 *= edge; + y1 *= edge; + y2 *= edge; + + //Texture coordinate order for veritcal flip of texture + vertices[0].set(x1, y1, 0, 0); + vertices[1].set(x1, y2, 0, 1); + vertices[2].set(x2, y1, 1, 0); + vertices[3].set(x2, y2, 1, 1); + + return true; +} + +void QGeoTiledMapScenePrivate::addTile(const QGeoTileSpec &spec, QSharedPointer texture) +{ + if (!m_visibleTiles.contains(spec)) // Don't add the geometry if it isn't visible + return; + + m_textures.insert(spec, texture); +} + +void QGeoTiledMapScenePrivate::setVisibleTiles(const QSet &tiles) +{ + // work out the tile bounds for the new scene + setTileBounds(tiles); + + // set up the gl camera for the new scene + setupCamera(); + + QSet toRemove = m_visibleTiles - tiles; + if (!toRemove.isEmpty()) + removeTiles(toRemove); + + m_visibleTiles = tiles; +} + +void QGeoTiledMapScenePrivate::removeTiles(const QSet &oldTiles) +{ + typedef QSet::const_iterator iter; + iter i = oldTiles.constBegin(); + iter end = oldTiles.constEnd(); + + for (; i != end; ++i) { + QGeoTileSpec tile = *i; + m_textures.remove(tile); + } +} + +void QGeoTiledMapScenePrivate::setTileBounds(const QSet &tiles) +{ + if (tiles.isEmpty()) { + m_minTileX = -1; + m_minTileY = -1; + m_maxTileX = -1; + m_maxTileY = -1; + return; + } + + typedef QSet::const_iterator iter; + iter i = tiles.constBegin(); + iter end = tiles.constEnd(); + + // determine whether the set of map tiles crosses the dateline. + // A gap in the tiles indicates dateline crossing + bool hasFarLeft = false; + bool hasFarRight = false; + bool hasMidLeft = false; + bool hasMidRight = false; + + for (; i != end; ++i) { + if ((*i).zoom() != m_intZoomLevel) + continue; + int x = (*i).x(); + if (x == 0) + hasFarLeft = true; + else if (x == (m_sideLength - 1)) + hasFarRight = true; + else if (x == ((m_sideLength / 2) - 1)) { + hasMidLeft = true; + } else if (x == (m_sideLength / 2)) { + hasMidRight = true; + } + } + + // if dateline crossing is detected we wrap all x pos of tiles + // that are in the left half of the map. + m_tileXWrapsBelow = 0; + + if (hasFarLeft && hasFarRight) { + if (!hasMidRight) { + m_tileXWrapsBelow = m_sideLength / 2; + } else if (!hasMidLeft) { + m_tileXWrapsBelow = (m_sideLength / 2) - 1; + } + } + + // finally, determine the min and max bounds + i = tiles.constBegin(); + + QGeoTileSpec tile = *i; + + int x = tile.x(); + if (tile.x() < m_tileXWrapsBelow) + x += m_sideLength; + + m_minTileX = x; + m_maxTileX = x; + m_minTileY = tile.y(); + m_maxTileY = tile.y(); + + ++i; + + for (; i != end; ++i) { + tile = *i; + if (tile.zoom() != m_intZoomLevel) + continue; + + int x = tile.x(); + if (tile.x() < m_tileXWrapsBelow) + x += m_sideLength; + + m_minTileX = qMin(m_minTileX, x); + m_maxTileX = qMax(m_maxTileX, x); + m_minTileY = qMin(m_minTileY, tile.y()); + m_maxTileY = qMax(m_maxTileY, tile.y()); + } +} + +void QGeoTiledMapScenePrivate::setupCamera() +{ + double f = 1.0 * qMin(m_screenSize.width(), m_screenSize.height()); + + // fraction of zoom level + double z = std::pow(2.0, m_cameraData.zoomLevel() - m_intZoomLevel) * m_tileSize; + + // calculate altitdue that allows the visible map tiles + // to fit in the screen correctly (note that a larger f will cause + // the camera be higher, resulting in gray areas displayed around + // the tiles) + double altitude = f / (2.0 * z) ; + + // mercatorWidth_ and mercatorHeight_ define the ratio for + // mercator and screen coordinate conversion, + // see mercatorToItemPosition() and itemPositionToMercator() + m_mercatorHeight = m_screenSize.height() / z; + m_mercatorWidth = m_screenSize.width() / z; + + // calculate center + double edge = m_scaleFactor * m_tileSize; + + // first calculate the camera center in map space in the range of 0 <-> sideLength (2^z) + QDoubleVector3D center = (m_sideLength * QGeoProjection::coordToMercator(m_cameraData.center())); + + // wrap the center if necessary (due to dateline crossing) + if (center.x() < m_tileXWrapsBelow) + center.setX(center.x() + 1.0 * m_sideLength); + + m_mercatorCenterX = center.x(); + m_mercatorCenterY = center.y(); + + // work out where the camera center is w.r.t minimum tile bounds + center.setX(center.x() - 1.0 * m_minTileX); + center.setY(1.0 * m_minTileY - center.y()); + + // letter box vertically + if (m_useVerticalLock && (m_mercatorHeight > 1.0 * m_sideLength)) { + center.setY(-1.0 * m_sideLength / 2.0); + m_mercatorCenterY = m_sideLength / 2.0; + m_screenOffsetY = m_screenSize.height() * (0.5 - m_sideLength / (2 * m_mercatorHeight)); + m_screenHeight = m_screenSize.height() - 2 * m_screenOffsetY; + m_mercatorHeight = 1.0 * m_sideLength; + m_verticalLock = true; + } else { + m_screenOffsetY = 0.0; + m_screenHeight = m_screenSize.height(); + m_verticalLock = false; + } + + if (m_mercatorWidth > 1.0 * m_sideLength) { + m_screenOffsetX = m_screenSize.width() * (0.5 - (m_sideLength / (2 * m_mercatorWidth))); + m_screenWidth = m_screenSize.width() - 2 * m_screenOffsetX; + m_mercatorWidth = 1.0 * m_sideLength; + } else { + m_screenOffsetX = 0.0; + m_screenWidth = m_screenSize.width(); + } + + // apply necessary scaling to the camera center + center *= edge; + + // calculate eye + + QDoubleVector3D eye = center; + eye.setZ(altitude * edge); + + // calculate up + + QDoubleVector3D view = eye - center; + QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); + QDoubleVector3D up = QDoubleVector3D::normal(side, view); + + // old bearing, tilt and roll code + // QMatrix4x4 mBearing; + // mBearing.rotate(-1.0 * camera.bearing(), view); + // up = mBearing * up; + + // QDoubleVector3D side2 = QDoubleVector3D::normal(up, view); + // QMatrix4x4 mTilt; + // mTilt.rotate(camera.tilt(), side2); + // eye = (mTilt * view) + center; + + // view = eye - center; + // side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); + // up = QDoubleVector3D::normal(view, side2); + + // QMatrix4x4 mRoll; + // mRoll.rotate(camera.roll(), view); + // up = mRoll * up; + + // near plane and far plane + + double nearPlane = 1.0; + double farPlane = (altitude + 1.0) * edge; + + m_cameraUp = up; + m_cameraCenter = center; + m_cameraEye = eye; + + double aspectRatio = 1.0 * m_screenSize.width() / m_screenSize.height(); + float halfWidth = 1; + float halfHeight = 1; + if (aspectRatio > 1.0) { + halfWidth *= aspectRatio; + } else if (aspectRatio > 0.0f && aspectRatio < 1.0f) { + halfHeight /= aspectRatio; + } + m_projectionMatrix.setToIdentity(); + m_projectionMatrix.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight, nearPlane, farPlane); +} + +class QGeoTiledMapTileContainerNode : public QSGTransformNode +{ +public: + void addChild(const QGeoTileSpec &spec, QSGSimpleTextureNode *node) + { + tiles.insert(spec, node); + appendChildNode(node); + } + QHash tiles; +}; + +class QGeoTiledMapRootNode : public QSGClipNode +{ +public: + QGeoTiledMapRootNode() + : isTextureLinear(false) + , geometry(QSGGeometry::defaultAttributes_Point2D(), 4) + , root(new QSGTransformNode()) + , tiles(new QGeoTiledMapTileContainerNode()) + , wrapLeft(new QGeoTiledMapTileContainerNode()) + , wrapRight(new QGeoTiledMapTileContainerNode()) + { + setIsRectangular(true); + setGeometry(&geometry); + root->appendChildNode(tiles); + root->appendChildNode(wrapLeft); + root->appendChildNode(wrapRight); + appendChildNode(root); + } + + ~QGeoTiledMapRootNode() + { + qDeleteAll(textures); + } + + void setClipRect(const QRect &rect) + { + if (rect != clipRect) { + QSGGeometry::updateRectGeometry(&geometry, rect); + QSGClipNode::setClipRect(rect); + clipRect = rect; + markDirty(DirtyGeometry); + } + } + + void updateTiles(QGeoTiledMapTileContainerNode *root, QGeoTiledMapScenePrivate *d, double camAdjust); + + bool isTextureLinear; + + QSGGeometry geometry; + QRect clipRect; + + QSGTransformNode *root; + + QGeoTiledMapTileContainerNode *tiles; // The majority of the tiles + QGeoTiledMapTileContainerNode *wrapLeft; // When zoomed out, the tiles that wrap around on the left. + QGeoTiledMapTileContainerNode *wrapRight; // When zoomed out, the tiles that wrap around on the right + + QHash textures; +}; + +static bool qgeotiledmapscene_isTileInViewport(const QSGGeometry::TexturedPoint2D *tp, const QMatrix4x4 &matrix) { + QPolygonF polygon; polygon.reserve(4); + for (int i=0; i<4; ++i) + polygon << matrix * QPointF(tp[i].x, tp[i].y); + return QRectF(-1, -1, 2, 2).intersects(polygon.boundingRect()); +} + +static QVector3D toVector3D(const QDoubleVector3D& in) +{ + return QVector3D(in.x(), in.y(), in.z()); +} + +void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root, + QGeoTiledMapScenePrivate *d, + double camAdjust) +{ + // Set up the matrix... + QDoubleVector3D eye = d->m_cameraEye; + eye.setX(eye.x() + camAdjust); + QDoubleVector3D center = d->m_cameraCenter; + center.setX(center.x() + camAdjust); + QMatrix4x4 cameraMatrix; + cameraMatrix.lookAt(toVector3D(eye), toVector3D(center), toVector3D(d->m_cameraUp)); + root->setMatrix(d->m_projectionMatrix * cameraMatrix); + + QSet tilesInSG = QSet::fromList(root->tiles.keys()); + QSet toRemove = tilesInSG - d->m_visibleTiles; + QSet toAdd = d->m_visibleTiles - tilesInSG; + + foreach (const QGeoTileSpec &s, toRemove) + delete root->tiles.take(s); + + for (QHash::iterator it = root->tiles.begin(); + it != root->tiles.end(); ) { + QSGGeometry visualGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4); + QSGGeometry::TexturedPoint2D *v = visualGeometry.vertexDataAsTexturedPoint2D(); + bool ok = d->buildGeometry(it.key(), v) && qgeotiledmapscene_isTileInViewport(v, root->matrix()); + QSGSimpleTextureNode *node = it.value(); + QSGNode::DirtyState dirtyBits = 0; + + // Check and handle changes to vertex data. + if (ok && memcmp(node->geometry()->vertexData(), v, 4 * sizeof(QSGGeometry::TexturedPoint2D)) != 0) { + if (v[0].x == v[3].x || v[0].y == v[3].y) { // top-left == bottom-right => invalid => remove + ok = false; + } else { + memcpy(node->geometry()->vertexData(), v, 4 * sizeof(QSGGeometry::TexturedPoint2D)); + dirtyBits |= QSGNode::DirtyGeometry; + } + } + + if (!ok) { + it = root->tiles.erase(it); + delete node; + } else { + if (isTextureLinear != d->m_linearScaling) { + node->setFiltering(d->m_linearScaling ? QSGTexture::Linear : QSGTexture::Nearest); + dirtyBits |= QSGNode::DirtyMaterial; + } + if (dirtyBits != 0) + node->markDirty(dirtyBits); + it++; + } + } + + foreach (const QGeoTileSpec &s, toAdd) { + QGeoTileTexture *tileTexture = d->m_textures.value(s).data(); + if (!tileTexture || tileTexture->image.isNull()) + continue; + QSGSimpleTextureNode *tileNode = new QSGSimpleTextureNode(); + // note: setTexture will update coordinates so do it here, before we buildGeometry + tileNode->setTexture(textures.value(s)); + Q_ASSERT(tileNode->geometry()); + Q_ASSERT(tileNode->geometry()->attributes() == QSGGeometry::defaultAttributes_TexturedPoint2D().attributes); + Q_ASSERT(tileNode->geometry()->vertexCount() == 4); + if (d->buildGeometry(s, tileNode->geometry()->vertexDataAsTexturedPoint2D()) + && qgeotiledmapscene_isTileInViewport(tileNode->geometry()->vertexDataAsTexturedPoint2D(), root->matrix())) { + tileNode->setFiltering(d->m_linearScaling ? QSGTexture::Linear : QSGTexture::Nearest); + root->addChild(s, tileNode); + } else { + delete tileNode; + } + } +} + +QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window) +{ + Q_D(QGeoTiledMapScene); + float w = d->m_screenSize.width(); + float h = d->m_screenSize.height(); + if (w <= 0 || h <= 0) { + delete oldNode; + return 0; + } + + QGeoTiledMapRootNode *mapRoot = static_cast(oldNode); + if (!mapRoot) + mapRoot = new QGeoTiledMapRootNode(); + + mapRoot->setClipRect(QRect(d->m_screenOffsetX, d->m_screenOffsetY, d->m_screenWidth, d->m_screenHeight)); + + QMatrix4x4 itemSpaceMatrix; + itemSpaceMatrix.scale(w / 2, h / 2); + itemSpaceMatrix.translate(1, 1); + itemSpaceMatrix.scale(1, -1); + mapRoot->root->setMatrix(itemSpaceMatrix); + + QSet textures = QSet::fromList(mapRoot->textures.keys()); + QSet toRemove = textures - d->m_visibleTiles; + QSet toAdd = d->m_visibleTiles - textures; + + foreach (const QGeoTileSpec &spec, toRemove) + mapRoot->textures.take(spec)->deleteLater(); + foreach (const QGeoTileSpec &spec, toAdd) { + QGeoTileTexture *tileTexture = d->m_textures.value(spec).data(); + if (!tileTexture || tileTexture->image.isNull()) + continue; + mapRoot->textures.insert(spec, window->createTextureFromImage(tileTexture->image)); + } + + double sideLength = d->m_scaleFactor * d->m_tileSize * d->m_sideLength; + mapRoot->updateTiles(mapRoot->tiles, d, 0); + mapRoot->updateTiles(mapRoot->wrapLeft, d, +sideLength); + mapRoot->updateTiles(mapRoot->wrapRight, d, -sideLength); + + mapRoot->isTextureLinear = d->m_linearScaling; + + return mapRoot; +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotiledmapscene_p.h b/src/location/maps/qgeotiledmapscene_p.h new file mode 100644 index 0000000..1e3a9bc --- /dev/null +++ b/src/location/maps/qgeotiledmapscene_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOTILEDMAPSCENE_P_H +#define QGEOTILEDMAPSCENE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCameraData; +class QGeoTileSpec; +class QDoubleVector2D; +class QGeoTileTexture; +class QSGNode; +class QQuickWindow; +class QGeoTiledMapScenePrivate; + +class Q_LOCATION_EXPORT QGeoTiledMapScene : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGeoTiledMapScene) +public: + explicit QGeoTiledMapScene(QObject *parent = 0); + virtual ~QGeoTiledMapScene(); + + void setScreenSize(const QSize &size); + void setTileSize(int tileSize); + void setCameraData(const QGeoCameraData &cameraData); + + void setVisibleTiles(const QSet &tiles); + const QSet &visibleTiles() const; + + void setUseVerticalLock(bool lock); + + void addTile(const QGeoTileSpec &spec, QSharedPointer texture); + + QDoubleVector2D itemPositionToMercator(const QDoubleVector2D &pos) const; + QDoubleVector2D mercatorToItemPosition(const QDoubleVector2D &mercator) const; + + QSGNode *updateSceneGraph(QSGNode *oldNode, QQuickWindow *window); + + bool verticalLock() const; + QSet texturedTiles(); + + void clearTexturedTiles(); + +Q_SIGNALS: + void newTilesVisible(const QSet &newTiles); + +private: + Q_DISABLE_COPY(QGeoTiledMapScene) +}; + +QT_END_NAMESPACE + +#endif // QGEOTILEDMAPSCENE_P_H diff --git a/src/location/maps/qgeotilefetcher.cpp b/src/location/maps/qgeotilefetcher.cpp new file mode 100644 index 0000000..0e0e81c --- /dev/null +++ b/src/location/maps/qgeotilefetcher.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "qgeomappingmanagerengine_p.h" +#include "qgeotilefetcher_p.h" +#include "qgeotilefetcher_p_p.h" +#include "qgeotiledmapreply_p.h" +#include "qgeotilespec_p.h" +#include "qgeotiledmap_p.h" + +QT_BEGIN_NAMESPACE + +QGeoTileFetcher::QGeoTileFetcher(QObject *parent) +: QObject(parent), d_ptr(new QGeoTileFetcherPrivate) +{ + Q_D(QGeoTileFetcher); + + d->enabled_ = true; + + if (!d->queue_.isEmpty()) + d->timer_.start(0, this); +} + +QGeoTileFetcher::~QGeoTileFetcher() +{ + + delete d_ptr; +} + +void QGeoTileFetcher::updateTileRequests(const QSet &tilesAdded, + const QSet &tilesRemoved) +{ + Q_D(QGeoTileFetcher); + + QMutexLocker ml(&d->queueMutex_); + + cancelTileRequests(tilesRemoved); + + d->queue_ += tilesAdded.toList(); + + if (d->enabled_ && initialized() && !d->queue_.isEmpty() && !d->timer_.isActive()) + d->timer_.start(0, this); +} + +void QGeoTileFetcher::cancelTileRequests(const QSet &tiles) +{ + Q_D(QGeoTileFetcher); + + typedef QSet::const_iterator tile_iter; + tile_iter tile = tiles.constBegin(); + tile_iter end = tiles.constEnd(); + for (; tile != end; ++tile) { + QGeoTiledMapReply *reply = d->invmap_.value(*tile, 0); + if (reply) { + d->invmap_.remove(*tile); + reply->abort(); + if (reply->isFinished()) + reply->deleteLater(); + } + d->queue_.removeAll(*tile); + } +} + +void QGeoTileFetcher::requestNextTile() +{ + Q_D(QGeoTileFetcher); + + QMutexLocker ml(&d->queueMutex_); + + if (!d->enabled_) + return; + + if (d->queue_.isEmpty()) + return; + + QGeoTileSpec ts = d->queue_.takeFirst(); + + QGeoTiledMapReply *reply = getTileImage(ts); + + if (reply->isFinished()) { + handleReply(reply, ts); + } else { + connect(reply, + SIGNAL(finished()), + this, + SLOT(finished()), + Qt::QueuedConnection); + + d->invmap_.insert(ts, reply); + } + + if (d->queue_.isEmpty()) + d->timer_.stop(); +} + +void QGeoTileFetcher::finished() +{ + Q_D(QGeoTileFetcher); + + QMutexLocker ml(&d->queueMutex_); + + QGeoTiledMapReply *reply = qobject_cast(sender()); + if (!reply) + return; + + QGeoTileSpec spec = reply->tileSpec(); + + if (!d->invmap_.contains(spec)) { + reply->deleteLater(); + return; + } + + d->invmap_.remove(spec); + + handleReply(reply, spec); +} + +void QGeoTileFetcher::timerEvent(QTimerEvent *event) +{ + Q_D(QGeoTileFetcher); + if (event->timerId() != d->timer_.timerId()) { + QObject::timerEvent(event); + return; + } + + if (d->queue_.isEmpty() || !initialized()) { + d->timer_.stop(); + return; + } + + requestNextTile(); +} + +bool QGeoTileFetcher::initialized() const +{ + return true; +} + +void QGeoTileFetcher::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec) +{ + Q_D(QGeoTileFetcher); + + if (!d->enabled_) { + reply->deleteLater(); + return; + } + + if (reply->error() == QGeoTiledMapReply::NoError) { + emit tileFinished(spec, reply->mapImageData(), reply->mapImageFormat()); + } else { + emit tileError(spec, reply->errorString()); + } + + reply->deleteLater(); +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoTileFetcherPrivate::QGeoTileFetcherPrivate() +: enabled_(false) +{ +} + +QGeoTileFetcherPrivate::~QGeoTileFetcherPrivate() +{ +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotilefetcher_p.h b/src/location/maps/qgeotilefetcher_p.h new file mode 100644 index 0000000..cbd8b99 --- /dev/null +++ b/src/location/maps/qgeotilefetcher_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEFETCHER_H +#define QGEOTILEFETCHER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include "qgeomaptype_p.h" +#include "qgeotiledmappingmanagerengine_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoMapRequestOptions; + +class QGeoTileFetcherPrivate; +class QGeoTiledMappingManagerEngine; +class QGeoTiledMapReply; +class QGeoTileSpec; + +class Q_LOCATION_EXPORT QGeoTileFetcher : public QObject +{ + Q_OBJECT + +public: + QGeoTileFetcher(QObject *parent = 0); + virtual ~QGeoTileFetcher(); + +public Q_SLOTS: + void updateTileRequests(const QSet &tilesAdded, const QSet &tilesRemoved); + +private Q_SLOTS: + void cancelTileRequests(const QSet &tiles); + void requestNextTile(); + void finished(); + +Q_SIGNALS: + void tileFinished(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format); + void tileError(const QGeoTileSpec &spec, const QString &errorString); + +protected: + void timerEvent(QTimerEvent *event); + QGeoTiledMappingManagerEngine::CacheAreas cacheHint() const; + virtual bool initialized() const; + +private: + QGeoTileFetcherPrivate *d_ptr; + + virtual QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec) = 0; + void handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec); + + Q_DECLARE_PRIVATE(QGeoTileFetcher) + Q_DISABLE_COPY(QGeoTileFetcher) + + friend class QGeoTiledMappingManagerEngine; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeotilefetcher_p_p.h b/src/location/maps/qgeotilefetcher_p_p.h new file mode 100644 index 0000000..acd7288 --- /dev/null +++ b/src/location/maps/qgeotilefetcher_p_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEFETCHER_P_H +#define QGEOTILEFETCHER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qgeomaptype_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoTileSpec; +class QGeoTiledMapReply; +class QGeoTiledMappingManagerEngine; + +class QGeoTileFetcherPrivate +{ +public: + QGeoTileFetcherPrivate(); + virtual ~QGeoTileFetcherPrivate(); + + bool enabled_; + QBasicTimer timer_; + QMutex queueMutex_; + QList queue_; + QHash invmap_; + +private: + Q_DISABLE_COPY(QGeoTileFetcherPrivate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/maps/qgeotilerequestmanager.cpp b/src/location/maps/qgeotilerequestmanager.cpp new file mode 100644 index 0000000..1409856 --- /dev/null +++ b/src/location/maps/qgeotilerequestmanager.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeotilerequestmanager_p.h" +#include "qgeotilespec_p.h" +#include "qgeotiledmap_p.h" +#include "qgeotiledmappingmanagerengine_p.h" +#include "qabstractgeotilecache_p.h" +#include + +QT_BEGIN_NAMESPACE + +class RetryFuture; + +class QGeoTileRequestManagerPrivate +{ +public: + explicit QGeoTileRequestManagerPrivate(QGeoTiledMap *map, QGeoTiledMappingManagerEngine *engine); + ~QGeoTileRequestManagerPrivate(); + + QGeoTiledMap *m_map; + QPointer m_engine; + + QList > requestTiles(const QSet &tiles); + void tileError(const QGeoTileSpec &tile, const QString &errorString); + + QHash m_retries; + QHash > m_futures; + QSet m_requested; + + void tileFetched(const QGeoTileSpec &spec); +}; + +QGeoTileRequestManager::QGeoTileRequestManager(QGeoTiledMap *map, QGeoTiledMappingManagerEngine *engine) + : d_ptr(new QGeoTileRequestManagerPrivate(map, engine)) +{ + +} + +QGeoTileRequestManager::~QGeoTileRequestManager() +{ + +} + +QList > QGeoTileRequestManager::requestTiles(const QSet &tiles) +{ + return d_ptr->requestTiles(tiles); +} + +void QGeoTileRequestManager::tileFetched(const QGeoTileSpec &spec) +{ + d_ptr->tileFetched(spec); +} + +QSharedPointer QGeoTileRequestManager::tileTexture(const QGeoTileSpec &spec) +{ + if (d_ptr->m_engine) + return d_ptr->m_engine->getTileTexture(spec); + else + return QSharedPointer(); +} + +void QGeoTileRequestManager::tileError(const QGeoTileSpec &tile, const QString &errorString) +{ + d_ptr->tileError(tile, errorString); +} + +QGeoTileRequestManagerPrivate::QGeoTileRequestManagerPrivate(QGeoTiledMap *map,QGeoTiledMappingManagerEngine *engine) + : m_map(map), + m_engine(engine) +{ +} + +QGeoTileRequestManagerPrivate::~QGeoTileRequestManagerPrivate() +{ +} + +QList > QGeoTileRequestManagerPrivate::requestTiles(const QSet &tiles) +{ + QSet cancelTiles = m_requested - tiles; + QSet requestTiles = tiles - m_requested; + QSet cached; +// int tileSize = tiles.size(); +// int newTiles = requestTiles.size(); + + typedef QSet::const_iterator iter; + + QList > cachedTex; + + // remove tiles in cache from request tiles + if (!m_engine.isNull()) { + iter i = requestTiles.constBegin(); + iter end = requestTiles.constEnd(); + for (; i != end; ++i) { + QGeoTileSpec tile = *i; + QSharedPointer tex = m_engine->getTileTexture(tile); + if (tex) { + cachedTex << tex; + cached.insert(tile); + } + } + } + + requestTiles -= cached; + + m_requested -= cancelTiles; + m_requested += requestTiles; + +// qDebug() << "required # tiles: " << tileSize << ", new tiles: " << newTiles << ", total server requests: " << requested_.size(); + + if (!requestTiles.isEmpty() || !cancelTiles.isEmpty()) { + if (!m_engine.isNull()) { +// qDebug() << "new server requests: " << requestTiles.size() << ", server cancels: " << cancelTiles.size(); + m_engine->updateTileRequests(m_map, requestTiles, cancelTiles); + + // Remove any cancelled tiles from the error retry hash to avoid + // re-using the numbers for a totally different request cycle. + iter i = cancelTiles.constBegin(); + iter end = cancelTiles.constEnd(); + for (; i != end; ++i) { + m_retries.remove(*i); + m_futures.remove(*i); + } + } + } + + return cachedTex; +} + +void QGeoTileRequestManagerPrivate::tileFetched(const QGeoTileSpec &spec) +{ + m_map->updateTile(spec); + m_requested.remove(spec); + m_retries.remove(spec); + m_futures.remove(spec); +} + +// Represents a tile that needs to be retried after a certain period of time +class RetryFuture : public QObject +{ + Q_OBJECT +public: + RetryFuture(const QGeoTileSpec &tile, QGeoTiledMap *map, QGeoTiledMappingManagerEngine* engine, QObject *parent = 0); + +public Q_SLOTS: + void retry(); + +private: + QGeoTileSpec m_tile; + QGeoTiledMap *m_map; + QPointer m_engine; +}; + +RetryFuture::RetryFuture(const QGeoTileSpec &tile, QGeoTiledMap *map, QGeoTiledMappingManagerEngine* engine, QObject *parent) + : QObject(parent), m_tile(tile), m_map(map), m_engine(engine) +{} + +void RetryFuture::retry() +{ + QSet requestTiles; + QSet cancelTiles; + requestTiles.insert(m_tile); + if (!m_engine.isNull()) + m_engine->updateTileRequests(m_map, requestTiles, cancelTiles); +} + +void QGeoTileRequestManagerPrivate::tileError(const QGeoTileSpec &tile, const QString &errorString) +{ + if (m_requested.contains(tile)) { + int count = m_retries.value(tile, 0); + m_retries.insert(tile, count + 1); + + if (count >= 5) { + qWarning("QGeoTileRequestManager: Failed to fetch tile (%d,%d,%d) 5 times, giving up. " + "Last error message was: '%s'", + tile.x(), tile.y(), tile.zoom(), qPrintable(errorString)); + m_requested.remove(tile); + m_retries.remove(tile); + m_futures.remove(tile); + + } else { + // Exponential time backoff when retrying + int delay = (1 << count) * 500; + + QSharedPointer future(new RetryFuture(tile,m_map,m_engine)); + m_futures.insert(tile, future); + + QTimer::singleShot(delay, future.data(), SLOT(retry())); + // Passing .data() to singleShot is ok -- Qt will clean up the + // connection if the target qobject is deleted + } + } +} + +#include "qgeotilerequestmanager.moc" + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotilerequestmanager_p.h b/src/location/maps/qgeotilerequestmanager_p.h new file mode 100644 index 0000000..66d2251 --- /dev/null +++ b/src/location/maps/qgeotilerequestmanager_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOTILEREQUESTMANAGER_P_H +#define QGEOTILEREQUESTMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE + +class QGeoTiledMap; +class QGeoTiledMappingManagerEngine; +class QGeoTileSpec; +class QGeoTileTexture; + +class QGeoTileRequestManagerPrivate; + +class QGeoTileRequestManager +{ +public: + explicit QGeoTileRequestManager(QGeoTiledMap *map, QGeoTiledMappingManagerEngine *engine); + ~QGeoTileRequestManager(); + + QList > requestTiles(const QSet &tiles); + + void tileError(const QGeoTileSpec &tile, const QString &errorString); + void tileFetched(const QGeoTileSpec &spec); + QSharedPointer tileTexture(const QGeoTileSpec &spec); + +private: + QScopedPointer d_ptr; + Q_DISABLE_COPY(QGeoTileRequestManager) +}; + +QT_END_NAMESPACE + +#endif // QGEOTILEREQUESTMANAGER_P_H diff --git a/src/location/maps/qgeotilespec.cpp b/src/location/maps/qgeotilespec.cpp new file mode 100644 index 0000000..2e04b53 --- /dev/null +++ b/src/location/maps/qgeotilespec.cpp @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotilespec_p.h" +#include "qgeotilespec_p_p.h" + +#include + +QT_BEGIN_NAMESPACE + +QGeoTileSpec::QGeoTileSpec() + : d(QSharedDataPointer(new QGeoTileSpecPrivate())) {} + +QGeoTileSpec::QGeoTileSpec(const QString &plugin, int mapId, int zoom, int x, int y, int version) + : d(QSharedDataPointer(new QGeoTileSpecPrivate(plugin, mapId, zoom, x, y, version))) {} + +QGeoTileSpec::QGeoTileSpec(const QGeoTileSpec &other) + : d(other.d) {} + +QGeoTileSpec::~QGeoTileSpec() { +} + +QGeoTileSpec &QGeoTileSpec::operator = (const QGeoTileSpec &other) +{ + if (this == &other) + return *this; + + d = other.d; + return *this; +} + +QString QGeoTileSpec::plugin() const +{ + return d->plugin_; +} + +void QGeoTileSpec::setZoom(int zoom) +{ + d->zoom_ = zoom; +} + +int QGeoTileSpec::zoom() const +{ + return d->zoom_; +} + +void QGeoTileSpec::setX(int x) +{ + d->x_ = x; +} + +int QGeoTileSpec::x() const +{ + return d->x_; +} + +void QGeoTileSpec::setY(int y) +{ + d->y_ = y; +} + +int QGeoTileSpec::y() const +{ + return d->y_; +} + +void QGeoTileSpec::setMapId(int mapId) +{ + d->mapId_ = mapId; +} + +int QGeoTileSpec::mapId() const +{ + return d->mapId_; +} + +void QGeoTileSpec::setVersion(int version) +{ + d->version_ = version; +} + +int QGeoTileSpec::version() const +{ + return d->version_; +} + +bool QGeoTileSpec::operator == (const QGeoTileSpec &rhs) const +{ + return (*(d.constData()) == *(rhs.d.constData())); +} + +bool QGeoTileSpec::operator < (const QGeoTileSpec &rhs) const +{ + return (*(d.constData()) < *(rhs.d.constData())); +} + +unsigned int qHash(const QGeoTileSpec &spec) +{ + unsigned int result = (qHash(spec.plugin()) * 13) % 31; + result += ((spec.mapId() * 17) % 31) << 5; + result += ((spec.zoom() * 19) % 31) << 10; + result += ((spec.x() * 23) % 31) << 15; + result += ((spec.y() * 29) % 31) << 20; + result += (spec.version() % 3) << 25; + return result; +} + +QDebug operator<< (QDebug dbg, const QGeoTileSpec &spec) +{ + dbg << spec.plugin() << spec.mapId() << spec.zoom() << spec.x() << spec.y() << spec.version(); + return dbg; +} + +QGeoTileSpecPrivate::QGeoTileSpecPrivate() + : mapId_(0), + zoom_(-1), + x_(-1), + y_(-1), + version_(-1) {} + +QGeoTileSpecPrivate::QGeoTileSpecPrivate(const QGeoTileSpecPrivate &other) + : QSharedData(other), + plugin_(other.plugin_), + mapId_(other.mapId_), + zoom_(other.zoom_), + x_(other.x_), + y_(other.y_), + version_(other.version_) {} + +QGeoTileSpecPrivate::QGeoTileSpecPrivate(const QString &plugin, int mapId, int zoom, int x, int y, int version) + : plugin_(plugin), + mapId_(mapId), + zoom_(zoom), + x_(x), + y_(y), + version_(version) {} + +QGeoTileSpecPrivate::~QGeoTileSpecPrivate() {} + +QGeoTileSpecPrivate &QGeoTileSpecPrivate::operator = (const QGeoTileSpecPrivate &other) +{ + if (this == &other) + return *this; + + plugin_ = other.plugin_; + mapId_ = other.mapId_; + zoom_ = other.zoom_; + x_ = other.x_; + y_ = other.y_; + version_ = other.version_; + + return *this; +} + +bool QGeoTileSpecPrivate::operator == (const QGeoTileSpecPrivate &rhs) const +{ + if (plugin_ != rhs.plugin_) + return false; + + if (mapId_ != rhs.mapId_) + return false; + + if (zoom_ != rhs.zoom_) + return false; + + if (x_ != rhs.x_) + return false; + + if (y_ != rhs.y_) + return false; + + if (version_ != rhs.version_) + return false; + + return true; +} + +bool QGeoTileSpecPrivate::operator < (const QGeoTileSpecPrivate &rhs) const +{ + if (plugin_ < rhs.plugin_) + return true; + if (plugin_ > rhs.plugin_) + return false; + + if (mapId_ < rhs.mapId_) + return true; + if (mapId_ > rhs.mapId_) + return false; + + if (zoom_ < rhs.zoom_) + return true; + if (zoom_ > rhs.zoom_) + return false; + + if (x_ < rhs.x_) + return true; + if (x_ > rhs.x_) + return false; + + if (y_ < rhs.y_) + return true; + if (y_ > rhs.y_) + return false; + + return (version_ < rhs.version_); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotilespec_p.h b/src/location/maps/qgeotilespec_p.h new file mode 100644 index 0000000..b277824 --- /dev/null +++ b/src/location/maps/qgeotilespec_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILESPEC_H +#define QGEOTILESPEC_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoTileSpecPrivate; + +class Q_LOCATION_EXPORT QGeoTileSpec +{ +public: + QGeoTileSpec(); + QGeoTileSpec(const QGeoTileSpec &other); + QGeoTileSpec(const QString &plugin, int mapId, int zoom, int x, int y, int version = -1); + ~QGeoTileSpec(); + + QGeoTileSpec &operator = (const QGeoTileSpec &other); + + QString plugin() const; + + void setZoom(int zoom); + int zoom() const; + + void setX(int x); + int x() const; + + void setY(int y); + int y() const; + + void setMapId(int mapId); + int mapId() const; + + void setVersion(int version); + int version() const; + + bool operator == (const QGeoTileSpec &rhs) const; + bool operator < (const QGeoTileSpec &rhs) const; + +private: + QSharedDataPointer d; +}; + +Q_LOCATION_EXPORT unsigned int qHash(const QGeoTileSpec &spec); + +Q_LOCATION_EXPORT QDebug operator<<(QDebug, const QGeoTileSpec &); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoTileSpec) + +#endif // QGEOTILESPEC_H diff --git a/src/location/maps/qgeotilespec_p_p.h b/src/location/maps/qgeotilespec_p_p.h new file mode 100644 index 0000000..1e7442f --- /dev/null +++ b/src/location/maps/qgeotilespec_p_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOTILESPEC_P_H +#define QGEOTILESPEC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoTileSpecPrivate : public QSharedData +{ +public: + QGeoTileSpecPrivate(); + QGeoTileSpecPrivate(const QGeoTileSpecPrivate &other); + QGeoTileSpecPrivate(const QString &plugin, int mapId, int zoom, int x, int y, int version); + ~QGeoTileSpecPrivate(); + + QGeoTileSpecPrivate &operator = (const QGeoTileSpecPrivate &other); + + bool operator == (const QGeoTileSpecPrivate &rhs) const; + bool operator < (const QGeoTileSpecPrivate &rhs) const; + + QString plugin_; + int mapId_; + int zoom_; + int x_; + int y_; + int version_; +}; + +QT_END_NAMESPACE + +#endif // QGEOTILESPEC_P_H diff --git a/src/location/places/placemacro.h b/src/location/places/placemacro.h new file mode 100644 index 0000000..e0603fc --- /dev/null +++ b/src/location/places/placemacro.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PLACE_MACRO_H +#define PLACE_MACRO_H + +#include + +QT_BEGIN_NAMESPACE + +#define Q_DECLARE_D_FUNC(Class) \ + inline Class##Private *d_func(); \ + inline const Class##Private *d_func() const;\ + friend class Class##Private; + +#define Q_DECLARE_COPY_CTOR(Class, BaseClass) \ + Class(const BaseClass &other); + +#define Q_IMPLEMENT_D_FUNC(Class) \ + Class##Private *Class::d_func() { return reinterpret_cast(d_ptr.data()); } \ + const Class##Private *Class::d_func() const { return reinterpret_cast(d_ptr.constData()); } + +#define Q_IMPLEMENT_COPY_CTOR(Class, BaseClass) \ + Class::Class(const BaseClass &other) : BaseClass() { Class##Private::copyIfPossible(d_ptr, other); } + +#define Q_DEFINE_PRIVATE_HELPER(Class, BaseClass, ClassType) \ + BaseClass##Private *clone() const { return new Class##Private(*this); } \ + static void copyIfPossible(QSharedDataPointer &d_ptr, const BaseClass &other) \ + { \ + if (other.type() == ClassType) \ + d_ptr = extract_d(other); \ + else \ + d_ptr = new Class##Private; \ + } + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/places.pri b/src/location/places/places.pri new file mode 100644 index 0000000..1a3796f --- /dev/null +++ b/src/location/places/places.pri @@ -0,0 +1,93 @@ +INCLUDEPATH += places + +PUBLIC_HEADERS += \ + places/placemacro.h \ +#data classes + places/qplace.h \ + places/qplaceattribute.h \ + places/qplacecontactdetail.h \ + places/qplacecategory.h \ + places/qplacecontent.h \ + places/qplacecontentreply.h \ + places/qplaceeditorial.h \ + places/qplaceimage.h \ + places/qplaceicon.h \ + places/qplaceratings.h \ + places/qplacereview.h \ + places/qplacesupplier.h \ + places/qplaceuser.h \ +#result + places/qplacesearchresult.h \ + places/qplaceresult.h \ + places/qplaceproposedsearchresult.h \ +#request classes + places/qplacecontentrequest.h \ + places/qplacematchrequest.h \ + places/qplacesearchrequest.h \ +#reply classes + places/qplacereply.h \ + places/qplacedetailsreply.h \ + places/qplaceidreply.h \ + places/qplacematchreply.h \ + places/qplacesearchreply.h \ + places/qplacesearchsuggestionreply.h \ + places/unsupportedreplies_p.h \ +#manager and engine + places/qplacemanager.h \ + places/qplacemanagerengine.h + +PRIVATE_HEADERS += \ + places/qplace_p.h \ + places/qplaceattribute_p.h \ + places/qplacecategory_p.h \ + places/qplacecontent_p.h \ + places/qplacecontactdetail_p.h \ + places/qplaceeditorial_p.h \ + places/qplaceicon_p.h \ + places/qplaceimage_p.h \ + places/qplaceratings_p.h \ + places/qplaceresult_p.h \ + places/qplaceproposedsearchresult_p.h \ + places/qplacereview_p.h \ + places/qplacesupplier_p.h \ + places/qplacesearchresult_p.h \ + places/qplacereply_p.h \ + places/qplacemanagerengine_p.h \ + places/qplacecontentrequest_p.h \ + places/qplaceuser_p.h + +SOURCES += \ +#data classes + places/qplace.cpp \ + places/qplaceattribute.cpp \ + places/qplacecategory.cpp \ + places/qplacecontactdetail.cpp \ + places/qplacecontent.cpp \ + places/qplacecontentreply.cpp \ + places/qplaceeditorial.cpp \ + places/qplaceuser.cpp \ +#result + places/qplaceicon.cpp \ + places/qplaceimage.cpp \ + places/qplaceratings.cpp \ + places/qplacereview.cpp \ + places/qplaceidreply.cpp \ + places/qplacesupplier.cpp \ +#result + places/qplacesearchresult.cpp \ + places/qplaceresult.cpp \ + places/qplaceproposedsearchresult.cpp \ +#request classes + places/qplacecontentrequest.cpp \ + places/qplacematchrequest.cpp \ + places/qplacesearchrequest.cpp \ +#reply classes + places/qplacereply.cpp \ + places/qplacedetailsreply.cpp \ + places/qplacematchreply.cpp \ + places/qplacesearchreply.cpp \ + places/qplacesearchsuggestionreply.cpp \ +#manager and engine + places/qplacemanager.cpp \ + places/qplacemanagerengine.cpp + diff --git a/src/location/places/qplace.cpp b/src/location/places/qplace.cpp new file mode 100644 index 0000000..82f9f64 --- /dev/null +++ b/src/location/places/qplace.cpp @@ -0,0 +1,721 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplace.h" +#include "qplace_p.h" + +#ifdef QPLACE_DEBUG +#include +#endif + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QPlace + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlace class represents a set of data about a place. + + \input place-definition.qdocinc + + \section2 Contact Information + The contact information of a place is based around a common set of + \l {Contact Types}{contact types}. To retrieve all the phone numbers + of a place, one would do: + + \snippet places/requesthandler.h Phone numbers + + The contact types are string values by design to allow for providers + to introduce new contact types. + + For convenience there are a set of functions which return the value + of the first contact detail of each type. + \list + \li QPlace::primaryPhone() + \li QPlace::primaryEmail() + \li QPlace::primaryWebsite() + \li QPlace::primaryFax() + \endlist + + \section2 Extended Attributes + Places may have additional attributes which are not covered in the formal API. + Similar to contacts attributes are based around a common set of + \l {Attribute Types}{attribute types}. To retrieve an extended attribute one + would do: + \snippet places/requesthandler.h Opening hours + + The attribute types are string values by design to allow providers + to introduce new attribute types. + + \section2 Content + The QPlace object is only meant to be a convenient container to hold + rich content such as images, reviews and so on. Retrieval of content + should happen via QPlaceManager::getPlaceContent(). + + The content is stored as a QPlaceContent::Collection which contains + both the index of the content, as well as the content itself. This enables + developers to check whether a particular item has already been retrieved + and if not, then request that content. + + \section3 Attribution + Places have a field for a rich text attribution string. Some providers + may require that the attribution be shown when a place is displayed + to a user. + + \section2 Categories + Different categories may be assigned to a place to indicate that the place + is associated with those categories. When saving a place, the only meaningful + data is the category id, the rest of the category data is effectively ignored. + The category must already exist before saving the place (it is not possible + to create a new category, assign it to the place, save the place and expect + the category to be created). + + \section2 Saving Caveats + \input place-caveats.qdocinc +*/ + +/*! + Constructs an empty place object. +*/ +QPlace::QPlace() + : d_ptr(new QPlacePrivate()) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QPlace::QPlace(const QPlace &other) + : d_ptr(other.d_ptr) +{ +} + +/*! + Destroys this place. +*/ +QPlace::~QPlace() +{ +} + +/*! + Assigns \a other to this place and returns a reference + to this place. +*/ +QPlace &QPlace::operator= (const QPlace & other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +inline QPlacePrivate *QPlace::d_func() +{ + return static_cast(d_ptr.data()); +} + +inline const QPlacePrivate *QPlace::d_func() const +{ + return static_cast(d_ptr.constData()); +} + +/*! + Returns true if \a other is equal to this place, + otherwise returns false. +*/ +bool QPlace::operator== (const QPlace &other) const +{ + Q_D(const QPlace); + return *d == *other.d_func(); +} + +/*! + Returns true if \a other is not equal to this place, + otherwise returns false. +*/ +bool QPlace::operator!= (const QPlace &other) const +{ + Q_D(const QPlace); + return !(*d == *other.d_func()); +} + +/*! + Returns categories that this place belongs to. +*/ +QList QPlace::categories() const +{ + Q_D(const QPlace); + return d->categories; +} + +/*! + Sets a single \a category that this place belongs to. +*/ +void QPlace::setCategory(const QPlaceCategory &category) +{ + Q_D(QPlace); + d->categories.clear(); + d->categories.append(category); +} + +/*! + Sets the \a categories that this place belongs to. +*/ +void QPlace::setCategories(const QList &categories) +{ + Q_D(QPlace); + d->categories = categories; +} + +/*! + Returns the location of the place. +*/ +QGeoLocation QPlace::location() const +{ + Q_D(const QPlace); + return d->location; +} + +/*! + Sets the \a location of the place. +*/ +void QPlace::setLocation(const QGeoLocation &location) +{ + Q_D(QPlace); + d->location = location; +} + +/*! + Returns an aggregated rating of the place. +*/ +QPlaceRatings QPlace::ratings() const +{ + Q_D(const QPlace); + return d->ratings; +} + +/*! + Sets the aggregated \a rating of the place. +*/ +void QPlace::setRatings(const QPlaceRatings &rating) +{ + Q_D(QPlace); + d->ratings = rating; +} + +/*! + Returns the supplier of this place. +*/ +QPlaceSupplier QPlace::supplier() const +{ + Q_D(const QPlace); + return d->supplier; +} + +/*! + Sets the supplier of this place to \a supplier. +*/ +void QPlace::setSupplier(const QPlaceSupplier &supplier) +{ + Q_D(QPlace); + d->supplier = supplier; +} + +/*! + Returns a collection of content associated with a place. + This collection is a map with the key being the index of the content object + and value being the content object itself. + + The \a type specifies which kind of content is to be retrieved. +*/ +QPlaceContent::Collection QPlace::content(QPlaceContent::Type type) const +{ + Q_D(const QPlace); + return d->contentCollections.value(type); +} + +/*! + Sets a collection of \a content for the given \a type. +*/ +void QPlace::setContent(QPlaceContent::Type type, const QPlaceContent::Collection &content) +{ + Q_D(QPlace); + d->contentCollections.insert(type, content); +} + +/*! + Adds a collection of \a content of the given \a type to the place. Any index in \a content + that already exists is overwritten. +*/ +void QPlace::insertContent(QPlaceContent::Type type, const QPlaceContent::Collection &content) +{ + Q_D(QPlace); + QMapIterator iter(content); + while (iter.hasNext()) { + iter.next(); + d->contentCollections[type].insert(iter.key(), iter.value()); + } +} + +/*! + Returns the total count of content objects of the given \a type. + This total count indicates how many the manager/provider should have available. + (As opposed to how many objects this place instance is currently assigned). + + A negative count indicates that the total number of items is unknown. + By default the total content count is set to 0. +*/ +int QPlace::totalContentCount(QPlaceContent::Type type) const +{ + Q_D(const QPlace); + return d->contentCounts.value(type, 0); +} + +/*! + Sets the \a totalCount of content objects of the given \a type. +*/ +void QPlace::setTotalContentCount(QPlaceContent::Type type, int totalCount) +{ + Q_D(QPlace); + d->contentCounts.insert(type, totalCount); +} + +/*! + Returns the name of the place. +*/ +QString QPlace::name() const +{ + Q_D(const QPlace); + return d->name; +} + +/*! + Sets the \a name of the place. +*/ +void QPlace::setName(const QString &name) +{ + Q_D(QPlace); + d->name = name; +} + +/*! + Returns the identifier of the place. The place identifier is only meaningful to the QPlaceManager that + generated it and is not transferable between managers. The place identifier is not guaranteed + to be universally unique, but unique for the manager that generated it. +*/ +QString QPlace::placeId() const +{ + Q_D(const QPlace); + return d->placeId; +} + +/*! + Sets the \a identifier of the place. +*/ +void QPlace::setPlaceId(const QString &identifier) +{ + Q_D(QPlace); + d->placeId = identifier; +} + +/*! + Returns a rich text attribution string of the place. Note, some providers may have a + requirement where the attribution must be shown whenever a place is displayed to an end user. +*/ +QString QPlace::attribution() const +{ + Q_D(const QPlace); + return d->attribution; +} + +/*! + Sets the \a attribution string of the place. +*/ +void QPlace::setAttribution(const QString &attribution) +{ + Q_D(QPlace); + d->attribution = attribution; +} + +/*! + Returns the icon of the place. +*/ +QPlaceIcon QPlace::icon() const +{ + Q_D(const QPlace); + return d->icon; +} + +/*! + Sets the \a icon of the place. +*/ +void QPlace::setIcon(const QPlaceIcon &icon) +{ + Q_D(QPlace); + d->icon = icon; +} + +/*! + Returns the primary phone number for this place. This accesses the first contact detail + of the \l {QPlaceContactDetail::Phone}{phone number type}. If no phone details exist, then an empty string is returned. +*/ +QString QPlace::primaryPhone() const +{ + Q_D(const QPlace); + QList phoneNumbers = d->contacts.value(QPlaceContactDetail::Phone); + if (!phoneNumbers.isEmpty()) + return phoneNumbers.at(0).value(); + else + return QString(); +} + +/*! + Returns the primary fax number for this place. This convenience function accesses the first contact + detail of the \l {QPlaceContactDetail::Fax}{fax type}. If no fax details exist, then an empty string is returned. +*/ +QString QPlace::primaryFax() const +{ + Q_D(const QPlace); + QList faxNumbers = d->contacts.value(QPlaceContactDetail::Fax); + if (!faxNumbers.isEmpty()) + return faxNumbers.at(0).value(); + else + return QString(); +} + +/*! + Returns the primary email address for this place. This convenience function accesses the first + contact detail of the \l {QPlaceContactDetail::Email}{email type}. If no email addresses exist, then + an empty string is returned. +*/ +QString QPlace::primaryEmail() const +{ + Q_D(const QPlace); + QList emailAddresses = d->contacts.value(QPlaceContactDetail::Email); + if (!emailAddresses.isEmpty()) + return emailAddresses.at(0).value(); + else + return QString(); +} + +/*! + Returns the primary website of the place. This convenience function accesses the first + contact detail of the \l {QPlaceContactDetail::Website}{website type}. If no websites exist, + then an empty string is returned. +*/ +QUrl QPlace::primaryWebsite() const +{ + Q_D(const QPlace); + QList websites = d->contacts.value(QPlaceContactDetail::Website); + if (!websites.isEmpty()) + return QUrl(websites.at(0).value()); + else + return QString(); +} + +/*! + Returns true if the details of this place have been fetched, + otherwise returns false. +*/ +bool QPlace::detailsFetched() const +{ + Q_D(const QPlace); + return d->detailsFetched; +} + +/*! + Sets whether the details of this place have been \a fetched or not. +*/ +void QPlace::setDetailsFetched(bool fetched) +{ + Q_D(QPlace); + d->detailsFetched = fetched; +} + +/*! + Returns the types of extended attributes that this place has. +*/ +QStringList QPlace::extendedAttributeTypes() const +{ + Q_D(const QPlace); + return d->extendedAttributes.keys(); +} + +/*! + Returns the exteded attribute corresponding to the specified \a attributeType. + If the place does not have that particular attribute type, a default constructed + QPlaceExtendedAttribute is returned. +*/ +QPlaceAttribute QPlace::extendedAttribute(const QString &attributeType) const +{ + Q_D(const QPlace); + return d->extendedAttributes.value(attributeType); +} + +/*! + Assigns an \a attribute of the given \a attributeType to a place. If the given \a attributeType + already exists in the place, then it is overwritten. + + If \a attribute is a default constructed QPlaceAttribute, then the \a attributeType + is removed from the place which means it will not be listed by QPlace::extendedAttributeTypes(). +*/ +void QPlace::setExtendedAttribute(const QString &attributeType, + const QPlaceAttribute &attribute) +{ + Q_D(QPlace); + if (attribute == QPlaceAttribute()) + d->extendedAttributes.remove(attributeType); + else + d->extendedAttributes.insert(attributeType, attribute); +} + +/*! + Remove the attribute of \a attributeType from the place. + + The attribute will no longer be listed by QPlace::extendedAttributeTypes() +*/ +void QPlace::removeExtendedAttribute(const QString &attributeType) +{ + Q_D(QPlace); + d->extendedAttributes.remove(attributeType); +} + +/*! + Returns the type of contact details this place has. + + See QPlaceContactDetail for a list of common \l {QPlaceContactDetail::Email}{contact types}. +*/ +QStringList QPlace::contactTypes() const +{ + Q_D(const QPlace); + return d->contacts.keys(); +} + +/*! + Returns a list of contact details of the specified \a contactType. + + See QPlaceContactDetail for a list of common \l {QPlaceContactDetail::Email}{contact types}. +*/ +QList QPlace::contactDetails(const QString &contactType) const +{ + Q_D(const QPlace); + return d->contacts.value(contactType); +} + +/*! + Sets the contact \a details of a specified \a contactType. + + If \a details is empty, then the \a contactType is removed from the place such + that it is no longer returned by QPlace::contactTypes(). + + See QPlaceContactDetail for a list of common \l {QPlaceContactDetail::Email}{contact types}. +*/ +void QPlace::setContactDetails(const QString &contactType, QList details) +{ + Q_D(QPlace); + if (details.isEmpty()) + d->contacts.remove(contactType); + else + d->contacts.insert(contactType, details); +} + +/*! + Appends a contact \a detail of a specified \a contactType. + + See QPlaceContactDetail for a list of common \l {QPlaceContactDetail::Email}{contact types}. +*/ +void QPlace::appendContactDetail(const QString &contactType, const QPlaceContactDetail &detail) +{ + Q_D(QPlace); + QList details = d->contacts.value(contactType); + details.append(detail); + d->contacts.insert(contactType, details); +} + +/*! + Removes all the contact details of a given \a contactType. + + The \a contactType is no longer returned when QPlace::contactTypes() is called. +*/ +void QPlace::removeContactDetails(const QString &contactType) +{ + Q_D(QPlace); + d->contacts.remove(contactType); +} + +/*! + Sets the visibility of the place to \a visibility. +*/ +void QPlace::setVisibility(QLocation::Visibility visibility) +{ + Q_D(QPlace); + d->visibility = visibility; +} + +/*! + Returns the visibility of the place. + + The default visibility of a new place is set to QtLocatin::Unspecified visibility. + If a place is saved with unspecified visibility the backend chooses an appropriate + default visibility to use when saving. +*/ +QLocation::Visibility QPlace::visibility() const +{ + Q_D(const QPlace); + return d->visibility; +} + +/*! + Returns a boolean indicating whether the all the fields of the place are empty or not. +*/ +bool QPlace::isEmpty() const +{ + Q_D(const QPlace); + return d->isEmpty(); +} + +/******************************************************************************* +*******************************************************************************/ + +QPlacePrivate::QPlacePrivate() +: QSharedData(), visibility(QLocation::UnspecifiedVisibility), detailsFetched(false) +{ +} + +QPlacePrivate::QPlacePrivate(const QPlacePrivate &other) + : QSharedData(other), + categories(other.categories), + location(other.location), + ratings(other.ratings), + supplier(other.supplier), + name(other.name), + placeId(other.placeId), + attribution(other.attribution), + contentCollections(other.contentCollections), + contentCounts(other.contentCounts), + extendedAttributes(other.extendedAttributes), + contacts(other.contacts), + visibility(other.visibility), + icon(other.icon), + detailsFetched(other.detailsFetched) +{ +} + +QPlacePrivate::~QPlacePrivate() {} + +QPlacePrivate &QPlacePrivate::operator= (const QPlacePrivate & other) +{ + if (this == &other) + return *this; + + categories = other.categories; + location = other.location; + ratings = other.ratings; + supplier = other.supplier; + name = other.name; + placeId = other.placeId; + attribution = other.attribution; + contentCollections = other.contentCollections; + contentCounts = other.contentCounts; + contacts = other.contacts; + extendedAttributes = other.extendedAttributes; + visibility = other.visibility; + detailsFetched = other.detailsFetched; + icon = other.icon; + + return *this; +} + +bool QPlacePrivate::operator== (const QPlacePrivate &other) const +{ +#ifdef QPLACE_DEBUG + qDebug() << "categories: " << (categories == other.categories); + qDebug() << "location:" << (location == other.location); + qDebug() << "ratings" << (ratings == other.ratings); + qDebug() << "supplier" << (supplier == other.supplier); + qDebug() << "contentCollections " << (contentCollections == other.contentCollections); + qDebug() << "contentCounts " << (contentCounts == other.contentCounts); + qDebug() << "name " << (name == other.name); + qDebug() << "placeId" << (placeId == other.placeId); + qDebug() << "attribution" << (attribution == other.attribution); + qDebug() << "contacts" << (contacts == other.contacts); + qDebug() << "extendedAttributes" << (extendedAttributes == other.extendedAttributes); + qDebug() << "visibility" << (visibility == other.visibility); + qDebug() << "icon" << (icon == other.icon); +#endif + + return (categories == other.categories + && location == other.location + && ratings == other.ratings + && supplier == other.supplier + && contentCollections == other.contentCollections + && contentCounts == other.contentCounts + && name == other.name + && placeId == other.placeId + && attribution == other.attribution + && contacts == other.contacts + && extendedAttributes == other.extendedAttributes + && visibility == other.visibility + && icon == other.icon + ); +} + + +bool QPlacePrivate::isEmpty() const +{ + return (categories.isEmpty() + && location.isEmpty() + && ratings.isEmpty() + && supplier.isEmpty() + && contentCollections.isEmpty() + && contentCounts.isEmpty() + && name.isEmpty() + && placeId.isEmpty() + && attribution.isEmpty() + && contacts.isEmpty() + && extendedAttributes.isEmpty() + && QLocation::UnspecifiedVisibility == visibility + && icon.isEmpty() + ); +} + +QT_END_NAMESPACE diff --git a/src/location/places/qplace.h b/src/location/places/qplace.h new file mode 100644 index 0000000..a36ce08 --- /dev/null +++ b/src/location/places/qplace.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACE_H +#define QPLACE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QString; +class QPlaceIcon; +class QPlacePrivate; + +class Q_LOCATION_EXPORT QPlace +{ +public: + QPlace(); + QPlace(const QPlace &other); + ~QPlace(); + + QPlace &operator=(const QPlace &other); + + bool operator==(const QPlace &other) const; + bool operator!=(const QPlace &other) const; + + QList categories() const; + void setCategory(const QPlaceCategory &category); + void setCategories(const QList &categories); + QGeoLocation location() const; + void setLocation(const QGeoLocation &location); + QPlaceRatings ratings() const; + void setRatings(const QPlaceRatings &ratings); + QPlaceSupplier supplier() const; + void setSupplier(const QPlaceSupplier &supplier); + + QString attribution() const; + void setAttribution(const QString &attribution); + + QPlaceIcon icon() const; + void setIcon(const QPlaceIcon &icon); + + QPlaceContent::Collection content(QPlaceContent::Type type) const; + void setContent(QPlaceContent::Type type, const QPlaceContent::Collection &content); + void insertContent(QPlaceContent::Type type, const QPlaceContent::Collection &content); + + int totalContentCount(QPlaceContent::Type type) const; + void setTotalContentCount(QPlaceContent::Type type, int total); + + QString name() const; + void setName(const QString &name); + QString placeId() const; + void setPlaceId(const QString &identifier); + + QString primaryPhone() const; + QString primaryFax() const; + QString primaryEmail() const; + QUrl primaryWebsite() const; + + bool detailsFetched() const; + void setDetailsFetched(bool fetched); + + QStringList extendedAttributeTypes() const; + QPlaceAttribute extendedAttribute(const QString &attributeType) const; + void setExtendedAttribute(const QString &attributeType, const QPlaceAttribute &attribute); + void removeExtendedAttribute(const QString &attributeType); + + QStringList contactTypes() const; + QList contactDetails(const QString &contactType) const; + void setContactDetails(const QString &contactType, QList details); + void appendContactDetail(const QString &contactType, const QPlaceContactDetail &detail); + void removeContactDetails(const QString &contactType); + + QLocation::Visibility visibility() const; + void setVisibility(QLocation::Visibility visibility); + + bool isEmpty() const; + +private: + QSharedDataPointer d_ptr; + + inline QPlacePrivate *d_func(); + inline const QPlacePrivate *d_func() const; +}; + +Q_DECLARE_TYPEINFO(QPlace, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlace) + +#endif diff --git a/src/location/places/qplace_p.h b/src/location/places/qplace_p.h new file mode 100644 index 0000000..cb1b13c --- /dev/null +++ b/src/location/places/qplace_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACE_P_H +#define QPLACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include "qplace.h" +#include "qgeoaddress.h" +#include "qgeorectangle.h" +#include "qgeocoordinate.h" +#include "qplacesupplier.h" +#include + +QT_BEGIN_NAMESPACE + +class QPlacePrivate : public QSharedData +{ +public: + QPlacePrivate(); + QPlacePrivate(const QPlacePrivate &other); + ~QPlacePrivate(); + + QPlacePrivate &operator= (const QPlacePrivate &other); + + bool operator==(const QPlacePrivate &other) const; + + bool isEmpty() const; + + QList categories; + QGeoLocation location; + QPlaceRatings ratings; + QPlaceSupplier supplier; + QString name; + QString placeId; + QString attribution; + + QMap contentCollections; + QMap contentCounts; + + QMap extendedAttributes; + QMap > contacts; + + QLocation::Visibility visibility; + QPlaceIcon icon; + bool detailsFetched; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/location/places/qplaceattribute.cpp b/src/location/places/qplaceattribute.cpp new file mode 100644 index 0000000..e7812a7 --- /dev/null +++ b/src/location/places/qplaceattribute.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceattribute_p.h" +#include "qplaceattribute.h" + +QT_USE_NAMESPACE + +template<> QPlaceAttributePrivate *QSharedDataPointer::clone() +{ + return d->clone(); +} + +QPlaceAttributePrivate::QPlaceAttributePrivate(const QPlaceAttributePrivate &other) + : QSharedData(other), + label(other.label), + text(other.text) +{ +} + +bool QPlaceAttributePrivate::operator== (const QPlaceAttributePrivate &other) const +{ + return label == other.label + && text == other.text; +} + +bool QPlaceAttributePrivate::isEmpty() const +{ + return label.isEmpty() + && text.isEmpty(); +} + + +/*! + \class QPlaceAttribute + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceAttribute class represents generic attribute information about a place. + + A QPlaceAttribute instance stores an additional piece of information about a place that is not + otherwise exposed through the QPlace class. A QPlaceAttribute encapsulates a + localized label which describes the attribute and rich text string representing the attribute's value. + Generally, both are intended to be displayed to the end-user as is. + + Some plugins may not support attributes at all, others may only support a + certain set, others still may support a dynamically changing set of attributes + over time or even allow attributes to be arbitrarily defined by the client + application. The attributes could also vary on a place by place basis, + for example one place may have opening hours while another does not. + Consult the \l {Plugin References and Parameters}{plugin + references} for details. + + \section2 Attribute Types + The QPlaceAttribute class defines some constant strings which characterize standard \e {attribute types}. + \list + \li QPlaceAttribute::OpeningHours + \li QPlaceAttribute::Payment + \li QPlaceAttribute::Provider + \endlist + + There is a class of attribute types of the format x_id_ for example x_id_here. + This class of attributes is a set of alternative identifiers of the place, from the specified provider's + perspective. + + The above types are used to access and modify attributes in QPlace via: + \list + \li QPlace::extendedAttribute() + \li QPlace::setExtendedAttribute() + \li QPlace::removeExtendedAttribute() + \li QPlace::removeExtendedAttribute() + \endlist + + The \e {attribute type} is a string type so that providers are able to introduce + new attributes as necessary. Custom attribute types should always be prefixed + by a qualifier in order to avoid conflicts. + + \section3 User Readable and Non-User Readable Attributes + Some attributes may not be intended to be readable by end users, the label field + of such attributes are empty to indicate this fact. +*/ + +/*! + \variable QPlaceAttribute::OpeningHours + Specifies the opening hours. +*/ +const QString QPlaceAttribute::OpeningHours(QLatin1String("openingHours")); + +/*! + \variable QPlaceAttribute::Payment + The constant to specify an attribute that defines the methods of payment. +*/ +const QString QPlaceAttribute::Payment(QLatin1String("payment")); + +/*! + \variable QPlaceAttribute::Provider + The constant to specify an attribute that defines which + provider the place came from. +*/ +const QString QPlaceAttribute::Provider(QLatin1String("x_provider")); + +/*! + Constructs an attribute. +*/ +QPlaceAttribute::QPlaceAttribute() + : d_ptr(new QPlaceAttributePrivate) +{ +} + +/*! + Destroys the attribute. +*/ +QPlaceAttribute::~QPlaceAttribute() +{ +} + +/*! + Creates a copy of \a other. +*/ +QPlaceAttribute::QPlaceAttribute(const QPlaceAttribute &other) + :d_ptr(other.d_ptr) +{ +} + +/*! + Assigns \a other to this attribute and returns a reference to this + attribute. +*/ +QPlaceAttribute &QPlaceAttribute::operator=(const QPlaceAttribute &other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if \a other is equal to this attribute, otherwise + returns false. +*/ +bool QPlaceAttribute::operator== (const QPlaceAttribute &other) const +{ + if (d_ptr == other.d_ptr) + return true; + return ( *(d_ptr.constData()) == *(other.d_ptr.constData())); +} + +/*! + Returns true if \a other is not equal to this attribute, + otherwise returns false. +*/ +bool QPlaceAttribute::operator!= (const QPlaceAttribute &other) const +{ + return (!this->operator ==(other)); +} + +/*! + Returns a localized label describing the attribute. +*/ +QString QPlaceAttribute::label() const +{ + return d_ptr->label; +} + +/*! + Sets the \a label of the attribute. +*/ +void QPlaceAttribute::setLabel(const QString &label) +{ + d_ptr->label = label; +} + +/*! + Returns a piece of rich text representing the attribute value. +*/ +QString QPlaceAttribute::text() const +{ + return d_ptr->text; +} + +/*! + Sets the \a text of the attribute. +*/ +void QPlaceAttribute::setText(const QString &text) +{ + d_ptr->text = text; +} + +/*! + Returns a boolean indicating whether the all the fields of the place attribute are empty or not. +*/ +bool QPlaceAttribute::isEmpty() const +{ + return d_ptr->isEmpty(); +} diff --git a/src/location/places/qplaceattribute.h b/src/location/places/qplaceattribute.h new file mode 100644 index 0000000..91a171d --- /dev/null +++ b/src/location/places/qplaceattribute.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEATTRIBUTE_H +#define QPLACEATTRIBUTE_H + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceAttributePrivate; +class Q_LOCATION_EXPORT QPlaceAttribute +{ +public: + static const QString OpeningHours; + static const QString Payment; + static const QString Provider; + + QPlaceAttribute(); + QPlaceAttribute(const QPlaceAttribute &other); + virtual ~QPlaceAttribute(); + + QPlaceAttribute &operator=(const QPlaceAttribute &other); + + bool operator==(const QPlaceAttribute &other) const; + bool operator!=(const QPlaceAttribute &other) const; + + QString label() const; + void setLabel(const QString &label); + + QString text() const; + void setText(const QString &text); + + bool isEmpty() const; + +protected: + QSharedDataPointer d_ptr; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceAttribute) + +#endif diff --git a/src/location/places/qplaceattribute_p.h b/src/location/places/qplaceattribute_p.h new file mode 100644 index 0000000..1f7442e --- /dev/null +++ b/src/location/places/qplaceattribute_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEATTRIBUTE_P_H +#define QPLACEATTRIBUTE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceAttributePrivate : public QSharedData +{ +public: + QPlaceAttributePrivate(){} + QPlaceAttributePrivate(const QPlaceAttributePrivate &other); + virtual ~QPlaceAttributePrivate(){} + + + virtual bool operator== (const QPlaceAttributePrivate &other) const; + virtual QPlaceAttributePrivate *clone() const { return new QPlaceAttributePrivate(*this); } + + bool isEmpty() const; + + QString label; + QString text; +}; + +template<> QPlaceAttributePrivate *QSharedDataPointer::clone(); + +QT_END_NAMESPACE + +#endif + diff --git a/src/location/places/qplacecategory.cpp b/src/location/places/qplacecategory.cpp new file mode 100644 index 0000000..5629631 --- /dev/null +++ b/src/location/places/qplacecategory.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacecategory.h" +#include "qplacecategory_p.h" + +QT_BEGIN_NAMESPACE + +QPlaceCategoryPrivate::QPlaceCategoryPrivate() +: visibility(QLocation::UnspecifiedVisibility) +{ +} + +QPlaceCategoryPrivate::QPlaceCategoryPrivate(const QPlaceCategoryPrivate &other) +: QSharedData(other), categoryId(other.categoryId), name(other.name), visibility(other.visibility), + icon(other.icon) +{ +} + +QPlaceCategoryPrivate::~QPlaceCategoryPrivate() +{ +} + +QPlaceCategoryPrivate &QPlaceCategoryPrivate::operator=(const QPlaceCategoryPrivate &other) +{ + if (this == &other) + return *this; + + categoryId = other.categoryId; + name = other.name; + icon = other.icon; + return *this; +} + +bool QPlaceCategoryPrivate::isEmpty() const +{ + return categoryId.isEmpty() + && name.isEmpty() + && icon.isEmpty() + && QLocation::UnspecifiedVisibility == visibility; +} + +/*! + \class QPlaceCategory + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceCategory class represents a category that a \l QPlace can be associated with. + + Categories are used to search for places based on the categories they are associated with. The + list/tree of available categories can be obtained from \l QPlaceManager. The + \l QPlaceSearchRequest::setCategories() function can be used to limit the search results to + places with the specified categories. + + If the \l QGeoServiceProvider supports it, categories can be created and removed. This + functionality is available in the \l QPlaceManager class. +*/ + +/*! + \fn bool QPlaceCategory::operator!=(const QPlaceCategory &other) const + + Returns true if \a other is not equal to this category; otherwise returns false. +*/ + +/*! + Constructs a category. +*/ +QPlaceCategory::QPlaceCategory() + : d(new QPlaceCategoryPrivate) +{ +} + +/*! + Constructs a category which is a copy of \a other. +*/ +QPlaceCategory::QPlaceCategory(const QPlaceCategory &other) + :d(other.d) +{ +} + +/*! + Destroys the category. +*/ +QPlaceCategory::~QPlaceCategory() +{ +} + +/*! + Assigns \a other to this category and returns a reference to this category. +*/ +QPlaceCategory &QPlaceCategory::operator =(const QPlaceCategory &other) +{ + if (this == &other) + return *this; + + d = other.d; + return *this; +} + +/*! + Returns true if \a other is equal to this category; otherwise returns false. +*/ +bool QPlaceCategory::operator==(const QPlaceCategory &other) const +{ + return d->categoryId == other.d->categoryId && + d->name == other.d->name && + d->visibility == other.d->visibility && + d->icon == other.d->icon; +} + +/*! + Returns the identifier of the category. The category identifier is a string which uniquely identifies this category + within a particular \l QPlaceManager. The identifier is only meaningful to the QPlaceManager + that generated it and is not transferable between managers. +*/ +QString QPlaceCategory::categoryId() const +{ + return d->categoryId; +} + +/*! + Sets the \a identifier of the category. +*/ +void QPlaceCategory::setCategoryId(const QString &identifier) +{ + d->categoryId = identifier; +} + +/*! + Returns the name of category. +*/ +QString QPlaceCategory::name() const +{ + return d->name; +} + +/*! + Sets the \a name of the category. +*/ +void QPlaceCategory::setName(const QString &name) +{ + d->name = name; +} + +/*! + Sets the \a visibility of the category. +*/ +void QPlaceCategory::setVisibility(QLocation::Visibility visibility) +{ + d->visibility = visibility; +} + +/*! + Returns the visibility of the category. +*/ +QLocation::Visibility QPlaceCategory::visibility() const +{ + return d->visibility; +} + +/*! + Returns the icon associated with the category. +*/ +QPlaceIcon QPlaceCategory::icon() const +{ + return d->icon; +} + +/*! + Sets the \a icon of the category. +*/ +void QPlaceCategory::setIcon(const QPlaceIcon &icon) +{ + d->icon = icon; +} + +/*! + Returns a boolean indicating whether the all the fields of the place category are empty or not. +*/ +bool QPlaceCategory::isEmpty() const +{ + return d->isEmpty(); +} + +QT_END_NAMESPACE diff --git a/src/location/places/qplacecategory.h b/src/location/places/qplacecategory.h new file mode 100644 index 0000000..56a9854 --- /dev/null +++ b/src/location/places/qplacecategory.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECATEGORY_H +#define QPLACECATEGORY_H + +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceIcon; + +class QPlaceCategoryPrivate; +class Q_LOCATION_EXPORT QPlaceCategory +{ +public: + QPlaceCategory(); + QPlaceCategory(const QPlaceCategory &other); + + virtual ~QPlaceCategory(); + + QPlaceCategory &operator=(const QPlaceCategory &other); + + bool operator==(const QPlaceCategory &other) const; + bool operator!=(const QPlaceCategory &other) const { + return !(other == *this); + } + + QString categoryId() const; + void setCategoryId(const QString &identifier); + + QString name() const; + void setName(const QString &name); + + QLocation::Visibility visibility() const; + void setVisibility(QLocation::Visibility visibility); + + QPlaceIcon icon() const; + void setIcon(const QPlaceIcon &icon); + + bool isEmpty() const; + +private: + QSharedDataPointer d; +}; + +Q_DECLARE_TYPEINFO(QPlaceCategory, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceCategory) + +#endif // QPLACECATEGORY_H diff --git a/src/location/places/qplacecategory_p.h b/src/location/places/qplacecategory_p.h new file mode 100644 index 0000000..07fec3c --- /dev/null +++ b/src/location/places/qplacecategory_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECATEGORY_P_H +#define QPLACECATEGORY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include "qplaceicon.h" + +QT_BEGIN_NAMESPACE + +class QPlaceCategoryPrivate : public QSharedData +{ +public: + QPlaceCategoryPrivate(); + QPlaceCategoryPrivate(const QPlaceCategoryPrivate &other); + + ~QPlaceCategoryPrivate(); + QPlaceCategoryPrivate &operator= (const QPlaceCategoryPrivate &other); + bool operator==(const QPlaceCategoryPrivate &other) const; + bool isEmpty() const; + + QString categoryId; + QString name; + QLocation::Visibility visibility; + QPlaceIcon icon; +}; + +QT_END_NAMESPACE + +#endif // QPLACECATEGORY_P_H diff --git a/src/location/places/qplacecontactdetail.cpp b/src/location/places/qplacecontactdetail.cpp new file mode 100644 index 0000000..d19fafb --- /dev/null +++ b/src/location/places/qplacecontactdetail.cpp @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacecontactdetail_p.h" +#include "qplacecontactdetail.h" + +QT_USE_NAMESPACE + +QPlaceContactDetailPrivate::QPlaceContactDetailPrivate(const QPlaceContactDetailPrivate &other) + : QSharedData(other), + label(other.label), + value(other.value) +{ +} + +bool QPlaceContactDetailPrivate::operator== (const QPlaceContactDetailPrivate &other) const +{ + return label == other.label + && value == other.value; +} + +/*! +\class QPlaceContactDetail +\brief The QPlaceContactDetail class represents a contact detail such as a phone number or website url. +\inmodule QtLocation + +\ingroup QtLocation-places +\ingroup QtLocation-places-data + +The detail consists of a label and value. The label is a localized string that can be presented +to the end user that describes that detail value which is the actual phone number, email address and so on. + +\section2 Contact Types + +The QPlaceContactDetail class defines some constant strings which characterize standard \e {contact types}. +\list + \li QPlaceContactDetail::Phone + \li QPlaceContactDetail::Email + \li QPlaceContactDetail::Website + \li QPlaceContactDetail::Fax +\endlist + +These types are used to access and modify contact details in QPlace via: +\list + \li QPlace::contactDetails() + \li QPlace::setContactDetails() + \li QPlace::appendContactDetail() + \li QPlace::contactTypes() +\endlist + +The \e {contact type} is intended to be a string type so that providers are able to introduce new contact +types if necessary. +*/ + +/*! + \variable QPlaceContactDetail::Phone + The constant to specify phone contact details +*/ +const QString QPlaceContactDetail::Phone(QLatin1String("phone")); + +/*! + \variable QPlaceContactDetail::Email + The constant to specify email contact details. +*/ +const QString QPlaceContactDetail::Email(QLatin1String("email")); + +/*! + \variable QPlaceContactDetail::Website + The constant used to specify website contact details. +*/ +const QString QPlaceContactDetail::Website(QLatin1String("website")); + +/*! + \variable QPlaceContactDetail::Fax + The constant used to specify fax contact details. +*/ +const QString QPlaceContactDetail::Fax(QLatin1String("fax")); + +/*! + Constructs a contact detail. +*/ +QPlaceContactDetail::QPlaceContactDetail() + : d_ptr(new QPlaceContactDetailPrivate) +{ +} + +/*! + Destroys the contact detail. +*/ +QPlaceContactDetail::~QPlaceContactDetail() +{ +} + +/*! + Creates a copy of \a other. +*/ +QPlaceContactDetail::QPlaceContactDetail(const QPlaceContactDetail &other) + :d_ptr(other.d_ptr) +{ +} + +/*! + Assigns \a other to this contact detail and returns a reference to this + contact detail. +*/ +QPlaceContactDetail &QPlaceContactDetail::operator=(const QPlaceContactDetail &other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if \a other is equal to this contact detail, otherwise + returns false. +*/ +bool QPlaceContactDetail::operator== (const QPlaceContactDetail &other) const +{ + if (d_ptr == other.d_ptr) + return true; + return ( *(d_ptr.constData()) == *(other.d_ptr.constData())); +} + +/*! + Returns true if \a other is not equal to this contact detail, + otherwise returns false. +*/ +bool QPlaceContactDetail::operator!= (const QPlaceContactDetail &other) const +{ + return (!this->operator ==(other)); +} + +/*! + Returns a label describing the contact detail. + + The label can potentially be localized. The language is dependent on the entity that sets it, + typically this is the manager from which the places are sourced. + The QPlaceManager::locales() field defines what language is used. +*/ +QString QPlaceContactDetail::label() const +{ + return d_ptr->label; +} + +/*! + Sets the \a label of the contact detail. +*/ +void QPlaceContactDetail::setLabel(const QString &label) +{ + d_ptr->label = label; +} + +/*! + Returns the value of the contact detail. +*/ +QString QPlaceContactDetail::value() const +{ + return d_ptr->value; +} + +/*! + Sets the \a value of this contact detail. +*/ +void QPlaceContactDetail::setValue(const QString &value) +{ + d_ptr->value = value; +} + +/*! + Clears the contact detail. +*/ +void QPlaceContactDetail::clear() +{ + d_ptr->label.clear(); + d_ptr->value.clear(); +} diff --git a/src/location/places/qplacecontactdetail.h b/src/location/places/qplacecontactdetail.h new file mode 100644 index 0000000..5113d83 --- /dev/null +++ b/src/location/places/qplacecontactdetail.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECONTACTDETAIL_H +#define QPLACECONTACTDETAIL_H + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceContactDetailPrivate; +class Q_LOCATION_EXPORT QPlaceContactDetail +{ +public: + static const QString Phone; + static const QString Email; + static const QString Website; + static const QString Fax; + + QPlaceContactDetail(); + QPlaceContactDetail(const QPlaceContactDetail &other); + virtual ~QPlaceContactDetail(); + + QPlaceContactDetail &operator=(const QPlaceContactDetail &other); + + bool operator==(const QPlaceContactDetail &other) const; + bool operator!=(const QPlaceContactDetail &other) const; + + QString label() const; + void setLabel(const QString &label); + + QString value() const; + void setValue(const QString &value); + + void clear(); + +private: + QSharedDataPointer d_ptr; + +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceContactDetail) + +#endif diff --git a/src/location/places/qplacecontactdetail_p.h b/src/location/places/qplacecontactdetail_p.h new file mode 100644 index 0000000..5d4002e --- /dev/null +++ b/src/location/places/qplacecontactdetail_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECONTACTDETAIL_P_H +#define QPLACECONTACTDETAIL_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceContactDetailPrivate : public QSharedData +{ +public: + QPlaceContactDetailPrivate(){} + QPlaceContactDetailPrivate(const QPlaceContactDetailPrivate &other); + virtual ~QPlaceContactDetailPrivate(){} + + bool operator== (const QPlaceContactDetailPrivate &other) const; + + QString label; + QString value; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacecontent.cpp b/src/location/places/qplacecontent.cpp new file mode 100644 index 0000000..a3334c6 --- /dev/null +++ b/src/location/places/qplacecontent.cpp @@ -0,0 +1,265 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacecontent.h" +#include "qplacecontent_p.h" + +#include + +QT_USE_NAMESPACE + +template<> QPlaceContentPrivate *QSharedDataPointer::clone() +{ + return d->clone(); +} + +inline QPlaceContentPrivate *QPlaceContent::d_func() +{ + return static_cast(d_ptr.data()); +} + +inline const QPlaceContentPrivate *QPlaceContent::d_func() const +{ + return static_cast(d_ptr.constData()); +} + +bool QPlaceContentPrivate::compare(const QPlaceContentPrivate *other) const +{ + return supplier == other->supplier + && user == other->user + && attribution == other->attribution; +} + +/*! + \class QPlaceContent + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceContent class serves as the base class for rich content types. + + Rich content such as \l {QPlaceImage}{images}, \l {QPlaceReview}{reviews} + and \l {QPlaceEditorial}{editorials} inherit + from the QPlaceContent class which contains common properties such as + an attribution string and content contributor, which may take the form of a + \l {QPlaceUser}{user} and/or \l {QPlaceSupplier}{supplier}. It is possible that + a user from a supplier is contributing content, hence both fields could + be filled in simultaneously. + + \b {Note:} Some providers may \e {require} that the attribution string be displayed + to the user whenever a piece of content is viewed. + + Conversion between QPlaceContent and it's subclasses can be easily performed without + casting. Due to the way it has been implemented, object slicing is not an issue, + the following code is valid: + \snippet places/requesthandler.h Content conversion + + The rich content of a place is typically made available as paginated items. The ability + to convert between QPlaceContent and it's subclasses means that code which handles + the mechanics of paging can be easily shared for each of the sub types. + + At present the QPlaceContent class is not extensible by 3rd parties. + + Note: The Places API considers content objects to be 'retrieve-only' objects. + Submission of content to a provider is not a supported use case. + \sa QPlaceImage, QPlaceReview, QPlaceEditorial +*/ + +/*! + \typedef QPlaceContent::Collection + Synonym for QMap. The key of the map is an \c int representing the + index of the content. The value is the content object itself. + + The \c {Collection} is intended to be a container where content items, that have been retrieved + as pages, can be stored. This enables a developer to skip pages, for example indexes 0-9 may be + stored in the collection, if the user skips to indexes 80-99, these can be stored in the + collection as well. +*/ + +/*! + \enum QPlaceContent::Type + Defines the type of content. + \value NoType + The content object is default constructed, any other content type may be assigned + to this content object. + \value ImageType + The content object is an image. + \value ReviewType + The content object is a review. + \value EditorialType + The content object is an editorial +*/ + +/*! + Constructs an default content object which has no type. +*/ +QPlaceContent::QPlaceContent() + :d_ptr(0) +{ +} + +/*! + Constructs a new copy of \a other. +*/ +QPlaceContent::QPlaceContent(const QPlaceContent &other) + :d_ptr(other.d_ptr) +{ +} + +/*! + Assigns the \a other content object to this and returns a reference + to this content object. +*/ +QPlaceContent &QPlaceContent::operator=(const QPlaceContent &other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Destroys the content object. +*/ +QPlaceContent::~QPlaceContent() +{ +} + +/*! + Returns the content type. +*/ +QPlaceContent::Type QPlaceContent::type() const +{ + if (!d_ptr) + return NoType; + return d_ptr->type(); +} + +/*! + Returns true if this content object is equivalent to \a other, + otherwise returns false. +*/ +bool QPlaceContent::operator==(const QPlaceContent &other) const +{ + // An invalid content object is only equal to another invalid content object + if (!d_ptr) + return !other.d_ptr; + + if (type() != other.type()) + return false; + + return d_ptr->compare(other.d_ptr); +} + +/*! + Returns true if this content object is not equivalent to \a other, + otherwise returns false. +*/ +bool QPlaceContent::operator!=(const QPlaceContent &other) const +{ + return !(*this == other); +} + +/*! + Returns the supplier who contributed this content. +*/ +QPlaceSupplier QPlaceContent::supplier() const +{ + Q_D(const QPlaceContent); + + return d->supplier; +} + +/*! + Sets the \a supplier of the content. +*/ +void QPlaceContent::setSupplier(const QPlaceSupplier &supplier) +{ + Q_D(QPlaceContent); + + d->supplier = supplier; +} + +/*! + Returns the user who contributed this content. +*/ +QPlaceUser QPlaceContent::user() const +{ + Q_D(const QPlaceContent); + return d->user; +} + +/*! + Sets the \a user who contributed this content. +*/ +void QPlaceContent::setUser(const QPlaceUser &user) +{ + Q_D(QPlaceContent); + d->user = user; +} + +/*! + Returns a rich text attribution string. + + \b {Note}: Some providers may require that the attribution + of a particular content item always be displayed + when the content item is shown. +*/ +QString QPlaceContent::attribution() const +{ + Q_D(const QPlaceContent); + return d->attribution; +} + +/*! + Sets a rich text \a attribution string for this content item. +*/ +void QPlaceContent::setAttribution(const QString &attribution) +{ + Q_D(QPlaceContent); + d->attribution = attribution; +} + +/*! + \internal + Constructs a new content object from the given pointer \a d. +*/ +QPlaceContent::QPlaceContent(QPlaceContentPrivate *d) + :d_ptr(d) +{ +} diff --git a/src/location/places/qplacecontent.h b/src/location/places/qplacecontent.h new file mode 100644 index 0000000..87a293d --- /dev/null +++ b/src/location/places/qplacecontent.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QPLACECONTENT_H +#define QPLACECONTENT_H + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#define Q_DECLARE_CONTENT_D_FUNC(Class) \ + inline Class##Private *d_func(); \ + inline const Class##Private *d_func() const;\ + friend class Class##Private; + +#define Q_DECLARE_CONTENT_COPY_CTOR(Class) \ + Class(const QPlaceContent &other); + +class QPlaceUser; +class QPlaceSupplier; +class QPlaceContentPrivate; +class Q_LOCATION_EXPORT QPlaceContent +{ +public: + typedef QMap Collection; + + enum Type { + NoType = 0, + ImageType, + ReviewType, + EditorialType + }; + + QPlaceContent(); + QPlaceContent(const QPlaceContent &other); + virtual ~QPlaceContent(); + + QPlaceContent &operator=(const QPlaceContent &other); + + bool operator==(const QPlaceContent &other) const; + bool operator!=(const QPlaceContent &other) const; + + QPlaceContent::Type type() const; + + QPlaceSupplier supplier() const; + void setSupplier(const QPlaceSupplier &supplier); + + QPlaceUser user() const; + void setUser(const QPlaceUser &user); + + QString attribution() const; + void setAttribution(const QString &attribution); + +protected: + explicit QPlaceContent(QPlaceContentPrivate *d); + QSharedDataPointer d_ptr; + +private: + inline QPlaceContentPrivate *d_func(); + inline const QPlaceContentPrivate *d_func() const; + + friend class QPlaceContentPrivate; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceContent) +Q_DECLARE_METATYPE(QPlaceContent::Type) + +#endif + diff --git a/src/location/places/qplacecontent_p.h b/src/location/places/qplacecontent_p.h new file mode 100644 index 0000000..23b176b --- /dev/null +++ b/src/location/places/qplacecontent_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECONTENT_P_H +#define QPLACECONTENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplacecontent.h" +#include "qplacesupplier.h" +#include "qplaceuser.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + + +#define Q_IMPLEMENT_CONTENT_D_FUNC(Class) \ + Class##Private *Class::d_func() { return reinterpret_cast(d_ptr.data()); } \ + const Class##Private *Class::d_func() const { return reinterpret_cast(d_ptr.constData()); } \ + +#define Q_IMPLEMENT_CONTENT_COPY_CTOR(Class) \ + Class::Class(const QPlaceContent &other) : QPlaceContent() { Class##Private::copyIfPossible(d_ptr, other); } + +#define Q_DEFINE_CONTENT_PRIVATE_HELPER(Class, ContentType) \ + virtual QPlaceContentPrivate *clone() const { return new Class##Private(*this); } \ + virtual QPlaceContent::Type type() const {return ContentType;} \ + static void copyIfPossible(QSharedDataPointer &d_ptr, const QPlaceContent &other) \ + { \ + if (other.type() == ContentType) \ + d_ptr = extract_d(other); \ + else \ + d_ptr = new Class##Private; \ + } + +class QPlaceContentPrivate : public QSharedData +{ +public: + QPlaceContentPrivate(){} + virtual ~QPlaceContentPrivate(){} + + virtual bool compare(const QPlaceContentPrivate *other) const; + virtual QPlaceContentPrivate *clone() const = 0; + virtual QPlaceContent::Type type() const = 0; + + /* Helper functions for C++ protection rules */ + static const QSharedDataPointer &extract_d(const QPlaceContent &other) {return other.d_ptr;} + + QPlaceSupplier supplier; + QPlaceUser user; + QString attribution; +}; + +template<> QPlaceContentPrivate *QSharedDataPointer::clone(); + +QT_END_NAMESPACE + +#endif + diff --git a/src/location/places/qplacecontentreply.cpp b/src/location/places/qplacecontentreply.cpp new file mode 100644 index 0000000..f603019 --- /dev/null +++ b/src/location/places/qplacecontentreply.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacecontentreply.h" +#include "qplacereply_p.h" + +QT_BEGIN_NAMESPACE +class QPlaceContentReplyPrivate : public QPlaceReplyPrivate +{ +public: + QPlaceContentReplyPrivate() + : totalCount(0) + { } + + QPlaceContent::Collection contentCollection; + int totalCount; + QPlaceContentRequest contentRequest; + QPlaceContentRequest previousPageRequest; + QPlaceContentRequest nextPageRequest; +}; + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +/*! + \class QPlaceContentReply + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-replies + \since 5.6 + + \brief The QPlaceContentReply class manages a content retrieval operation started by an + instance of QPlaceManager. + + See \l {Fetching Rich Content} for an example on how to use a content reply. + \sa QPlaceContentRequest, QPlaceManager +*/ + +/*! + Constructs a content reply with a given \a parent. +*/ +QPlaceContentReply::QPlaceContentReply(QObject *parent) + : QPlaceReply(new QPlaceContentReplyPrivate, parent) +{ +} + +/*! + Destroys the reply. +*/ +QPlaceContentReply::~QPlaceContentReply() +{ +} + + /*! + Returns the collection of content retrieved. +*/ +QPlaceContent::Collection QPlaceContentReply::content() const +{ + Q_D(const QPlaceContentReply); + return d->contentCollection; +} + +/*! + Returns the type of reply. +*/ +QPlaceReply::Type QPlaceContentReply::type() const +{ + return QPlaceReply::ContentReply; +} + +/*! + Sets the \a content of the reply. +*/ +void QPlaceContentReply::setContent(const QPlaceContent::Collection &content) +{ + Q_D(QPlaceContentReply); + d->contentCollection = content; +} + +/*! + Returns the total number of content objects for a place. If the total number of + content objects cannot be counted, a value of -1 is returned. This count only + refers to the total count for a single content type, that is, the content type that + was specified when content was requested with the QPlaceManager. +*/ +int QPlaceContentReply::totalCount() const +{ + Q_D(const QPlaceContentReply); + return d->totalCount; +} + +/*! + Sets the \a total number of content objects for a place. +*/ +void QPlaceContentReply::setTotalCount(int total) +{ + Q_D(QPlaceContentReply); + d->totalCount = total; +} + +/*! + Returns the content request that was used to generate this reply. +*/ +QPlaceContentRequest QPlaceContentReply::request() const +{ + Q_D(const QPlaceContentReply); + return d->contentRequest; +} + +/*! + Returns a place content request that can be used to request the previous batch of place content + results. +*/ +QPlaceContentRequest QPlaceContentReply::previousPageRequest() const +{ + Q_D(const QPlaceContentReply); + return d->previousPageRequest; +} + +/*! + Returns a place content request that can be used to request the next batch of place content + results. +*/ +QPlaceContentRequest QPlaceContentReply::nextPageRequest() const +{ + Q_D(const QPlaceContentReply); + return d->nextPageRequest; +} + +/*! + Sets the content \a request used to generate this this reply. +*/ +void QPlaceContentReply::setRequest(const QPlaceContentRequest &request) +{ + Q_D(QPlaceContentReply); + d->contentRequest = request; +} + +/*! + Sets the place content request that can be used to request the previous batch of place content + results to \a previous. +*/ +void QPlaceContentReply::setPreviousPageRequest(const QPlaceContentRequest &previous) +{ + Q_D(QPlaceContentReply); + d->previousPageRequest = previous; +} + +/*! + Sets the place content request that can be used to request the next batch of place content + results to \a next. +*/ +void QPlaceContentReply::setNextPageRequest(const QPlaceContentRequest &next) +{ + Q_D(QPlaceContentReply); + d->nextPageRequest = next; +} diff --git a/src/location/places/qplacecontentreply.h b/src/location/places/qplacecontentreply.h new file mode 100644 index 0000000..fa96a0e --- /dev/null +++ b/src/location/places/qplacecontentreply.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECONTENTREPLY_H +#define QPLACECONTENTREPLY_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceContentReplyPrivate; +class Q_LOCATION_EXPORT QPlaceContentReply : public QPlaceReply +{ + Q_OBJECT + +public: + explicit QPlaceContentReply(QObject *parent = Q_NULLPTR); + virtual ~QPlaceContentReply(); + + QPlaceReply::Type type() const; + + QPlaceContent::Collection content() const; + + int totalCount() const; + + QPlaceContentRequest request() const; + + QPlaceContentRequest previousPageRequest() const; + QPlaceContentRequest nextPageRequest() const; + +protected: + void setContent(const QPlaceContent::Collection &content); + void setTotalCount(int total); + void setRequest(const QPlaceContentRequest &request); + void setPreviousPageRequest(const QPlaceContentRequest &previous); + void setNextPageRequest(const QPlaceContentRequest &next); + +private: + Q_DISABLE_COPY(QPlaceContentReply) + Q_DECLARE_PRIVATE(QPlaceContentReply) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacecontentrequest.cpp b/src/location/places/qplacecontentrequest.cpp new file mode 100644 index 0000000..5a211ae --- /dev/null +++ b/src/location/places/qplacecontentrequest.cpp @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacecontentrequest_p.h" +#include "qplacecontentrequest.h" +#include "qgeocoordinate.h" + +QT_BEGIN_NAMESPACE + +QPlaceContentRequestPrivate::QPlaceContentRequestPrivate() +: QSharedData(), contentType(QPlaceContent::NoType), limit(-1) +{ +} + +QPlaceContentRequestPrivate::QPlaceContentRequestPrivate(const QPlaceContentRequestPrivate &other) +: QSharedData(other), contentType(other.contentType), placeId(other.placeId), + contentContext(other.contentContext), limit(other.limit) +{ +} + +QPlaceContentRequestPrivate::~QPlaceContentRequestPrivate() +{ +} + +bool QPlaceContentRequestPrivate::operator==(const QPlaceContentRequestPrivate &other) const +{ + return contentType == other.contentType + && limit == other.limit; +} + +void QPlaceContentRequestPrivate::clear() +{ + contentType = QPlaceContent::NoType; + limit = -1; +} + +/*! + \class QPlaceContentRequest + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-requests + \since 5.6 + + \brief The QPlaceContentRequest class represents the parameters of a content request. + + The QPlaceContentRequest class is used in conjunction with a QPlaceManager to + retrieve rich content like images and reviews in a paginated fashion. + The following code would request a set of 5 images from the 10th index: + + \snippet places/requesthandler.h Content request + \dots + \dots + \snippet places/requesthandler.h Content handler + + \sa QPlaceContentReply +*/ + +/*! + Constructs a new request object. +*/ +QPlaceContentRequest::QPlaceContentRequest() + : d_ptr(new QPlaceContentRequestPrivate()) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QPlaceContentRequest::QPlaceContentRequest(const QPlaceContentRequest &other) + : d_ptr(other.d_ptr) +{ +} + +/*! + Destroys the request object +*/ +QPlaceContentRequest::~QPlaceContentRequest() +{ +} + +/*! + Assigns \a other to this content request and returns a reference + to this content request. +*/ +QPlaceContentRequest &QPlaceContentRequest::operator= (const QPlaceContentRequest & other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if \a other is equal to this content request, + otherwise returns false. +*/ +bool QPlaceContentRequest::operator== (const QPlaceContentRequest &other) const +{ + Q_D(const QPlaceContentRequest); + return *d == *other.d_func(); +} + +/*! + Returns true if \a other is not equal to this content request, + otherwise returns false. +*/ +bool QPlaceContentRequest::operator!= (const QPlaceContentRequest &other) const +{ + Q_D(const QPlaceContentRequest); + return !(*d == *other.d_func()); +} + +/*! + Returns the type of content to be requested, for example reviews or images +*/ +QPlaceContent::Type QPlaceContentRequest::contentType() const +{ + Q_D(const QPlaceContentRequest); + return d->contentType; +} + +/*! + Sets the \a type of content to be requested. +*/ +void QPlaceContentRequest::setContentType(QPlaceContent::Type type) +{ + Q_D(QPlaceContentRequest); + d->contentType = type; +} + +/*! + Returns the identifier of the place content is to be fetched for. +*/ +QString QPlaceContentRequest::placeId() const +{ + Q_D(const QPlaceContentRequest); + return d->placeId; +} + +/*! + Sets the identifier of the place to fetch content for to \a identifier. +*/ +void QPlaceContentRequest::setPlaceId(const QString &identifier) +{ + Q_D(QPlaceContentRequest); + d->placeId = identifier; +} + +/*! + Returns backend specific additional content context associated with this place content request. +*/ +QVariant QPlaceContentRequest::contentContext() const +{ + Q_D(const QPlaceContentRequest); + return d->contentContext; +} + +/*! + Sets the content context to \a context. + + \note This method is intended to be used by geo service plugins when returning place content + results. + + The content context is used by backends to store additional content context related to the + content request. Other relevant fields should also be filled in. For example, if the content + request is for image content the content type should also be set with \l setContentType(). The + content context allows additional context to be kept which is not directly accessible via the + Qt Location API. + + The content context can be of any type storable in a QVariant. The value of the content context + is not intended to be used directly by applications. +*/ +void QPlaceContentRequest::setContentContext(const QVariant &context) +{ + Q_D(QPlaceContentRequest); + d->contentContext = context; +} + +/*! + Returns the maximum number of content items to retrieve. + + A negative value for limit means that it is undefined. It is left up to the backend + provider to choose an appropriate number of items to return. + + The default limit is -1. +*/ +int QPlaceContentRequest::limit() const +{ + Q_D(const QPlaceContentRequest); + return d->limit; +} + +/*! + Set the maximum number of content items to retrieve to + \a limit. +*/ +void QPlaceContentRequest::setLimit(int limit) +{ + Q_D(QPlaceContentRequest); + d->limit = limit; +} + +/*! + Clears the content request. +*/ +void QPlaceContentRequest::clear() +{ + Q_D(QPlaceContentRequest); + d->clear(); +} + +inline QPlaceContentRequestPrivate *QPlaceContentRequest::d_func() +{ + return static_cast(d_ptr.data()); +} + +inline const QPlaceContentRequestPrivate *QPlaceContentRequest::d_func() const +{ + return static_cast(d_ptr.constData()); +} + +QT_END_NAMESPACE diff --git a/src/location/places/qplacecontentrequest.h b/src/location/places/qplacecontentrequest.h new file mode 100644 index 0000000..51b88f3 --- /dev/null +++ b/src/location/places/qplacecontentrequest.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECONTENTREQUEST_H +#define QPLACECONTENTREQUEST_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceContentRequestPrivate; + +class Q_LOCATION_EXPORT QPlaceContentRequest +{ +public: + QPlaceContentRequest(); + QPlaceContentRequest(const QPlaceContentRequest &other); + ~QPlaceContentRequest(); + + QPlaceContentRequest &operator=(const QPlaceContentRequest &other); + + bool operator==(const QPlaceContentRequest &other) const; + bool operator!=(const QPlaceContentRequest &other) const; + + QPlaceContent::Type contentType() const; + void setContentType(QPlaceContent::Type type); + + QString placeId() const; + void setPlaceId(const QString &identifier); + + QVariant contentContext() const; + void setContentContext(const QVariant &context); + + int limit() const; + void setLimit(int limit); + + void clear(); + +private: + QSharedDataPointer d_ptr; + inline QPlaceContentRequestPrivate *d_func(); + inline const QPlaceContentRequestPrivate *d_func() const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacecontentrequest_p.h b/src/location/places/qplacecontentrequest_p.h new file mode 100644 index 0000000..d9ba370 --- /dev/null +++ b/src/location/places/qplacecontentrequest_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECONTENTREQUEST_P_H +#define QPLACECONTENTREQUEST_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceContentRequestPrivate : public QSharedData +{ +public: + QPlaceContentRequestPrivate(); + QPlaceContentRequestPrivate(const QPlaceContentRequestPrivate &other); + ~QPlaceContentRequestPrivate(); + + QPlaceContentRequestPrivate &operator=(const QPlaceContentRequestPrivate &other); + bool operator==(const QPlaceContentRequestPrivate &other) const; + + void clear(); + + QPlaceContent::Type contentType; + QString placeId; + QVariant contentContext; + int limit; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacedetailsreply.cpp b/src/location/places/qplacedetailsreply.cpp new file mode 100644 index 0000000..84ea9f8 --- /dev/null +++ b/src/location/places/qplacedetailsreply.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacedetailsreply.h" +#include "qplacereply_p.h" + +QT_BEGIN_NAMESPACE +class QPlaceDetailsReplyPrivate : public QPlaceReplyPrivate +{ +public: + QPlaceDetailsReplyPrivate() {} + ~QPlaceDetailsReplyPrivate() {} + QPlace result; +}; + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +/*! + \class QPlaceDetailsReply + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-replies + \since 5.6 + + \brief The QPlaceDetailsReply class manages a place details fetch operation started by an + instance of QPlaceManager. + + See \l {QML Places API#Fetching Place Details}{Fetching Place Details} for an example on how to use a details reply. + \sa QPlaceManager +*/ + +/*! + Constructs a details reply with a given \a parent. +*/ +QPlaceDetailsReply::QPlaceDetailsReply(QObject *parent) + : QPlaceReply(new QPlaceDetailsReplyPrivate, parent) +{ +} + +/*! + Destroys the details reply. +*/ +QPlaceDetailsReply::~QPlaceDetailsReply() +{ +} + +/*! + Returns the type of reply. +*/ +QPlaceReply::Type QPlaceDetailsReply::type() const +{ + return QPlaceReply::DetailsReply; +} + + /*! + Returns the place that was fetched. +*/ +QPlace QPlaceDetailsReply::place() const +{ + Q_D(const QPlaceDetailsReply); + return d->result; +} + +/*! + Sets the fetched \a place of the reply. +*/ +void QPlaceDetailsReply::setPlace(const QPlace &place) +{ + Q_D(QPlaceDetailsReply); + d->result = place; +} diff --git a/src/location/places/qplacedetailsreply.h b/src/location/places/qplacedetailsreply.h new file mode 100644 index 0000000..09593a1 --- /dev/null +++ b/src/location/places/qplacedetailsreply.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEDETAILSREPLY_H +#define QPLACEDETAILSREPLY_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceDetailsReplyPrivate; +class Q_LOCATION_EXPORT QPlaceDetailsReply : public QPlaceReply +{ + Q_OBJECT +public: + explicit QPlaceDetailsReply(QObject *parent = Q_NULLPTR); + virtual ~QPlaceDetailsReply(); + + QPlaceReply::Type type() const; + + QPlace place() const; + +protected: + void setPlace(const QPlace &place); + +private: + Q_DISABLE_COPY(QPlaceDetailsReply) + Q_DECLARE_PRIVATE(QPlaceDetailsReply) +}; + +QT_END_NAMESPACE + +#endif // QPLACEDETAILSREPLY_H diff --git a/src/location/places/qplaceeditorial.cpp b/src/location/places/qplaceeditorial.cpp new file mode 100644 index 0000000..bd1cb64 --- /dev/null +++ b/src/location/places/qplaceeditorial.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceeditorial.h" +#include "qplaceeditorial_p.h" + +QT_USE_NAMESPACE + +QPlaceEditorialPrivate::QPlaceEditorialPrivate() +: QPlaceContentPrivate() +{ +} + +QPlaceEditorialPrivate::QPlaceEditorialPrivate(const QPlaceEditorialPrivate &other) +: QPlaceContentPrivate(other), text(other.text), contentTitle(other.contentTitle), + language(other.language) +{ +} + +QPlaceEditorialPrivate::~QPlaceEditorialPrivate() +{ +} + +bool QPlaceEditorialPrivate::compare(const QPlaceContentPrivate *other) const +{ + const QPlaceEditorialPrivate *od = static_cast(other); + return QPlaceContentPrivate::compare(other) + && text == od->text + && contentTitle == od->contentTitle + && language == od->language; +} + +/*! + \class QPlaceEditorial + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceEditorial class represents a publisher's article describing a place. + + Each QPlaceEditorial has a title, text and language; in addition to those properties + inherited from QPlaceContent. + + Note: The Places API only supports editorials as 'retrieve-only' objects. Submitting editorials + to a provider is not a supported use case. + + \sa QPlaceContent +*/ + +/*! + Constructs a new editorial object. +*/ +QPlaceEditorial::QPlaceEditorial() +: QPlaceContent(new QPlaceEditorialPrivate) +{ +} + +/*! + Destructor. +*/ +QPlaceEditorial::~QPlaceEditorial() +{ +} + +/*! + \fn QPlaceEditorial::QPlaceEditorial(const QPlaceContent &other) + Constructs a copy of \a other if possible, otherwise constructs a default editorial object. +*/ +Q_IMPLEMENT_CONTENT_COPY_CTOR(QPlaceEditorial) + +Q_IMPLEMENT_CONTENT_D_FUNC(QPlaceEditorial) + +/*! + Returns a textual description of the place. + + Depending upon the provider, the + editorial text could be either rich(HTML based) text or plain text. +*/ +QString QPlaceEditorial::text() const +{ + Q_D(const QPlaceEditorial); + return d->text; +} + +/*! + Sets the \a text of the editorial. +*/ +void QPlaceEditorial::setText(const QString &text) +{ + Q_D(QPlaceEditorial); + d->text = text; +} + +/*! + Returns the title of the editorial. +*/ +QString QPlaceEditorial::title() const +{ + Q_D(const QPlaceEditorial); + return d->contentTitle; +} + +/*! + Sets the \a title of the editorial. +*/ +void QPlaceEditorial::setTitle(const QString &title) +{ + Q_D(QPlaceEditorial); + d->contentTitle = title; +} + +/*! + Returns the language of the editorial. Typically this would be a language code + in the 2 letter ISO 639-1 format. +*/ +QString QPlaceEditorial::language() const +{ + Q_D(const QPlaceEditorial); + return d->language; +} + +/*! + Sets the \a language of the editorial. Typically this would be a language code + in the 2 letter ISO 639-1 format. +*/ +void QPlaceEditorial::setLanguage(const QString &language) +{ + Q_D(QPlaceEditorial); + d->language = language; +} diff --git a/src/location/places/qplaceeditorial.h b/src/location/places/qplaceeditorial.h new file mode 100644 index 0000000..ecfe8db --- /dev/null +++ b/src/location/places/qplaceeditorial.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEEDITORIAL_H +#define QPLACEEDITORIAL_H + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceEditorialPrivate; + +class Q_LOCATION_EXPORT QPlaceEditorial : public QPlaceContent +{ +public: + QPlaceEditorial(); +#ifdef Q_QDOC + QPlaceEditorial(const QPlaceContent &other); +#else + Q_DECLARE_CONTENT_COPY_CTOR(QPlaceEditorial) +#endif + + virtual ~QPlaceEditorial(); + + QString text() const; + void setText(const QString &text); + QString title() const; + void setTitle(const QString &data); + QString language() const; + void setLanguage(const QString &data); + +private: + Q_DECLARE_CONTENT_D_FUNC(QPlaceEditorial) +}; + +QT_END_NAMESPACE + +#endif // QPLACEEDITORIAL_H diff --git a/src/location/places/qplaceeditorial_p.h b/src/location/places/qplaceeditorial_p.h new file mode 100644 index 0000000..f502db7 --- /dev/null +++ b/src/location/places/qplaceeditorial_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEDESCRIPTION_P_H +#define QPLACEDESCRIPTION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include "qplacecontent_p.h" + +QT_BEGIN_NAMESPACE + +class QPlaceEditorialPrivate : public QPlaceContentPrivate +{ +public: + QPlaceEditorialPrivate(); + QPlaceEditorialPrivate(const QPlaceEditorialPrivate &other); + + ~QPlaceEditorialPrivate(); + + bool compare(const QPlaceContentPrivate *other) const; + + Q_DEFINE_CONTENT_PRIVATE_HELPER(QPlaceEditorial, QPlaceContent::EditorialType) + + QString text; + QString contentTitle; + QString language; +}; + +QT_END_NAMESPACE + +#endif // QPLACEDESCRIPTION_P_H diff --git a/src/location/places/qplaceicon.cpp b/src/location/places/qplaceicon.cpp new file mode 100644 index 0000000..c3a2b85 --- /dev/null +++ b/src/location/places/qplaceicon.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceicon.h" +#include "qplaceicon_p.h" +#include "qplacemanager.h" +#include "qplacemanagerengine.h" + +QT_USE_NAMESPACE + +QPlaceIconPrivate::QPlaceIconPrivate() + : QSharedData(), manager(0) +{ +} + +QPlaceIconPrivate::QPlaceIconPrivate(const QPlaceIconPrivate &other) + : QSharedData(other), + manager(other.manager), + parameters(other.parameters) +{ +} + +QPlaceIconPrivate::~QPlaceIconPrivate() +{ +} + +QPlaceIconPrivate &QPlaceIconPrivate::operator=(const QPlaceIconPrivate &other) +{ + if (this == &other) + return *this; + + manager = other.manager; + parameters = other.parameters; + + return *this; +} + +bool QPlaceIconPrivate::operator == (const QPlaceIconPrivate &other) const +{ + return manager == other.manager + && parameters == other.parameters; +} + +/*! + \class QPlaceIcon + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceIcon class represents an icon. + + The typical usage of an icon is to use the url() function to specify + a preferred icon size. + + \snippet places/requesthandler.h icon + + The icons are typically backend dependent, if a manager backend does not support a given size, the URL of the icon that most + closely matches those parameters is returned. + + The icon class also has a key-value set of parameters. The precise key one + needs to use depends on the \l {Qt Location#Plugin References and Parameters}{plugin} + being used. These parameters influence which icon URL is returned by + the manager and may also be used to specify icon URL locations when + saving icons. + + If there is only ever one image for an icon, then QPlaceIcon::SingleUrl can be used as a parameter + key with a QUrl as the associated value. If this key is set, then the url() function will always return the specified URL + and not defer to any manager. +*/ + +/*! + \variable QPlaceIcon::SingleUrl + \brief Parameter key for an icon that only has a single image URL. + + The parameter value to be used with this key is a QUrl. An icon with this parameter set will + always return the specified URL regardless of the requested size when url() is called. +*/ +const QString QPlaceIcon::SingleUrl(QLatin1String("singleUrl")); + +/*! + Constructs an icon. +*/ +QPlaceIcon::QPlaceIcon() + : d(new QPlaceIconPrivate) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QPlaceIcon::QPlaceIcon(const QPlaceIcon &other) + : d(other.d) +{ +} + +/*! + Destroys the icon. +*/ +QPlaceIcon::~QPlaceIcon() +{ +} + +/*! + Assigns \a other to this icon and returns a reference to this icon. +*/ +QPlaceIcon &QPlaceIcon::operator=(const QPlaceIcon &other) +{ + if (this == &other) + return *this; + + d = other.d; + return *this; +} + +/*! + Returns true if this icon is equal to \a other, otherwise returns false. +*/ +bool QPlaceIcon::operator==(const QPlaceIcon &other) const +{ + return *d == *(other.d); +} + +/*! + \fn QPlaceIcon::operator!=(const QPlaceIcon &other) const + + Returns true if \a other is not equal to this icon, otherwise returns false. +*/ + +/*! + Returns an icon URL according to the given \a size. + + If no manager has been assigned to the icon, and the parameters do not contain the QPlaceIcon::SingleUrl key, a default constructed QUrl + is returned. +*/ +QUrl QPlaceIcon::url(const QSize &size) const +{ + if (d->parameters.contains(QPlaceIcon::SingleUrl)) { + QVariant value = d->parameters.value(QPlaceIcon::SingleUrl); + if (value.type() == QVariant::Url) + return value.toUrl(); + else if (value.type() == QVariant::String) + return QUrl::fromUserInput(value.toString()); + + return QUrl(); + } + + if (!d->manager) + return QUrl(); + + return d->manager->d->constructIconUrl(*this, size); +} + +/*! + Returns a set of parameters for the icon that are manager/plugin specific. + These parameters are used by the manager to return the appropriate + URL when url() is called and to specify locations to save to + when saving icons. + + Consult the \l {Qt Location#Plugin References and Parameters}{plugin documentation} + for what parameters are supported and how they should be used. +*/ +QVariantMap QPlaceIcon::parameters() const +{ + return d->parameters; +} + +/*! + Sets the parameters of the icon to \a parameters. +*/ +void QPlaceIcon::setParameters(const QVariantMap ¶meters) +{ + d->parameters = parameters; +} + +/*! + Returns the manager that this icon is associated with. +*/ +QPlaceManager *QPlaceIcon::manager() const +{ + return d->manager; +} + +/*! + Sets the \a manager that this icon is associated with. The icon does not take + ownership of the pointer. +*/ +void QPlaceIcon::setManager(QPlaceManager *manager) +{ + d->manager = manager; +} + +/*! + Returns a boolean indicating whether the all the fields of the icon are empty or not. +*/ +bool QPlaceIcon::isEmpty() const +{ + return (d->manager == 0 + && d->parameters.isEmpty()); +} diff --git a/src/location/places/qplaceicon.h b/src/location/places/qplaceicon.h new file mode 100644 index 0000000..c603572 --- /dev/null +++ b/src/location/places/qplaceicon.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEICON_H +#define QPLACEICON_H + +#include + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceManager; + +class QPlaceIconPrivate; +class Q_LOCATION_EXPORT QPlaceIcon +{ +public: + static const QString SingleUrl; + + QPlaceIcon(); + QPlaceIcon(const QPlaceIcon &other); + + ~QPlaceIcon(); + + QPlaceIcon &operator=(const QPlaceIcon &other); + bool operator == (const QPlaceIcon &other) const; + bool operator != (const QPlaceIcon &other) const { + return !(*this == other); + } + + QUrl url(const QSize &size = QSize()) const; + + QPlaceManager *manager() const; + void setManager(QPlaceManager *manager); + + QVariantMap parameters() const; + void setParameters(const QVariantMap ¶meters); + + bool isEmpty() const; + +private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceIcon) + +#endif diff --git a/src/location/places/qplaceicon_p.h b/src/location/places/qplaceicon_p.h new file mode 100644 index 0000000..8f94102 --- /dev/null +++ b/src/location/places/qplaceicon_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEICON_P_H +#define QPLACEICON_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceManager; +class QPlaceIconPrivate: public QSharedData +{ +public: + QPlaceIconPrivate(); + QPlaceIconPrivate(const QPlaceIconPrivate &other); + ~QPlaceIconPrivate(); + + QPlaceIconPrivate &operator=(const QPlaceIconPrivate &other); + bool operator == (const QPlaceIconPrivate &other) const; + + QPlaceManager *manager; + QVariantMap parameters; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplaceidreply.cpp b/src/location/places/qplaceidreply.cpp new file mode 100644 index 0000000..7fb8bbe --- /dev/null +++ b/src/location/places/qplaceidreply.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceidreply.h" +#include "qplacereply_p.h" + +QT_BEGIN_NAMESPACE +class QPlaceIdReplyPrivate : public QPlaceReplyPrivate +{ +public: + QPlaceIdReplyPrivate(QPlaceIdReply::OperationType operationType) + : operationType(operationType) {} + ~QPlaceIdReplyPrivate() {} + QString id; + QPlaceIdReply::OperationType operationType; +}; + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +/*! + \class QPlaceIdReply + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-replies + \since 5.6 + + \brief The QPlaceIdReply class manages operations which return an identifier such as + saving and removal operations of places and categories. + + The QPlaceIdReply can be considered a multipurpose reply in that it can + be used to save places, save categories, remove places and remove categories. + In each case it returns an identifier of the place or category that was added, modified or removed. + + See \l {Saving a place cpp}{Saving a place} for an example of how to use an identifier reply. + \sa QPlaceManager +*/ + +/*! + \enum QPlaceIdReply::OperationType + Defines the type of operation that was used to generate this reply. + \value SavePlace The reply was created for a save place operation + \value RemovePlace The reply was created for a remove place operation. + \value SaveCategory The reply was created for a save category operation + \value RemoveCategory The reply was created for a remove category operation. +*/ + +/*! + Constructs a reply which contains the identifier of the object operated upon. The reply is for the given \a operationType and with \a parent. +*/ +QPlaceIdReply::QPlaceIdReply(QPlaceIdReply::OperationType operationType, QObject *parent) + : QPlaceReply(new QPlaceIdReplyPrivate(operationType), parent) {} + +/*! + Destroys the reply. +*/ +QPlaceIdReply::~QPlaceIdReply() +{ +} + +/*! + Returns the type of reply. +*/ +QPlaceReply::Type QPlaceIdReply::type() const +{ + return QPlaceReply::IdReply; +} + +/*! + Returns the operation type of the reply. This means whether this + identifier reply was for a save place operation, + remove category operation and so on. +*/ +QPlaceIdReply::OperationType QPlaceIdReply::operationType() const +{ + Q_D(const QPlaceIdReply); + return d->operationType; +} + +/*! + Returns the relevant identifier for the operation. For example for a save place operation, + the identifier is that of the saved place. For a category removal operation, + it is the identifier of the category that was removed. +*/ +QString QPlaceIdReply::id() const +{ + Q_D(const QPlaceIdReply); + return d->id; +} + +/*! + Sets the \a identifier of the reply. +*/ +void QPlaceIdReply::setId(const QString &identifier) +{ + Q_D(QPlaceIdReply); + d->id = identifier; +} diff --git a/src/location/places/qplaceidreply.h b/src/location/places/qplaceidreply.h new file mode 100644 index 0000000..ea44828 --- /dev/null +++ b/src/location/places/qplaceidreply.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEIDREPLY_H +#define QPLACEIDREPLY_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceIdReplyPrivate; +class Q_LOCATION_EXPORT QPlaceIdReply : public QPlaceReply +{ + Q_OBJECT +public: + enum OperationType + { + SavePlace, + SaveCategory, + RemovePlace, + RemoveCategory + }; + + explicit QPlaceIdReply(OperationType operationType, QObject *parent = Q_NULLPTR); + virtual ~QPlaceIdReply(); + + QPlaceReply::Type type() const; + OperationType operationType() const; + + QString id() const; + +protected: + void setId(const QString &identifier); +private: + Q_DISABLE_COPY(QPlaceIdReply) + Q_DECLARE_PRIVATE(QPlaceIdReply) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplaceimage.cpp b/src/location/places/qplaceimage.cpp new file mode 100644 index 0000000..f3dda15 --- /dev/null +++ b/src/location/places/qplaceimage.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceimage.h" +#include "qplaceimage_p.h" + +QT_USE_NAMESPACE + +QPlaceImagePrivate::QPlaceImagePrivate() : QPlaceContentPrivate() +{ +} + +QPlaceImagePrivate::QPlaceImagePrivate(const QPlaceImagePrivate &other) + : QPlaceContentPrivate(other) +{ + url = other.url; + id = other.id; + mimeType = other.mimeType; +} + +QPlaceImagePrivate::~QPlaceImagePrivate() +{ +} + +bool QPlaceImagePrivate::compare(const QPlaceContentPrivate *other) const +{ + const QPlaceImagePrivate *od = static_cast(other); + return QPlaceContentPrivate::compare(other) + && url == od->url && id == od->id && mimeType == od->mimeType; +} + +/*! + \class QPlaceImage + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceImage class represents a reference to an image. + + Each QPlaceImage represents a set of metadata about an image such as it's + url, identifier and MIME type. These are properties in addition to those provided + by QPlaceContent. + + Note: The Places API only supports images as 'retrieve-only' objects. Submitting + images to a provider is not a supported use case. + \sa QPlaceContent +*/ + +/*! + Constructs an new QPlaceImage. +*/ +QPlaceImage::QPlaceImage() + : QPlaceContent(new QPlaceImagePrivate) +{ +} + +/*! + Destructor. +*/ +QPlaceImage::~QPlaceImage() +{ +} + +/*! + \fn QPlaceImage::QPlaceImage(const QPlaceContent &other) + Constructs a copy of \a other if possible, otherwise constructs a default image. +*/ + +Q_IMPLEMENT_CONTENT_COPY_CTOR(QPlaceImage) + +Q_IMPLEMENT_CONTENT_D_FUNC(QPlaceImage) + +/*! + Returns the image's url. +*/ +QUrl QPlaceImage::url() const +{ + Q_D(const QPlaceImage); + return d->url; +} + +/*! + Sets the image's \a url. +*/ +void QPlaceImage::setUrl(const QUrl &url) +{ + Q_D(QPlaceImage); + d->url = url; +} + +/*! + Returns the image's identifier. +*/ +QString QPlaceImage::imageId() const +{ + Q_D(const QPlaceImage); + return d->id; +} + +/*! + Sets image's \a identifier. +*/ +void QPlaceImage::setImageId(const QString &identifier) +{ + Q_D(QPlaceImage); + d->id = identifier; +} + +/*! + Returns the image's MIME type. +*/ +QString QPlaceImage::mimeType() const +{ + Q_D(const QPlaceImage); + return d->mimeType; +} + +/*! + Sets image's MIME \a type. +*/ +void QPlaceImage::setMimeType(const QString &type) +{ + Q_D(QPlaceImage); + d->mimeType = type; +} diff --git a/src/location/places/qplaceimage.h b/src/location/places/qplaceimage.h new file mode 100644 index 0000000..732d3de --- /dev/null +++ b/src/location/places/qplaceimage.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEIMAGE_H +#define QPLACEIMAGE_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceImagePrivate; +class QUrl; + +class Q_LOCATION_EXPORT QPlaceImage : public QPlaceContent +{ +public: + QPlaceImage(); +#ifdef Q_QDOC + QPlaceImage(const QPlaceContent &other); +#else + Q_DECLARE_CONTENT_COPY_CTOR(QPlaceImage) +#endif + + virtual ~QPlaceImage(); + + QUrl url() const; + void setUrl(const QUrl &url); + + QString imageId() const; + void setImageId(const QString &identifier); + + QString mimeType() const; + void setMimeType(const QString &data); + +private: + Q_DECLARE_CONTENT_D_FUNC(QPlaceImage) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplaceimage_p.h b/src/location/places/qplaceimage_p.h new file mode 100644 index 0000000..4030b08 --- /dev/null +++ b/src/location/places/qplaceimage_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEIMAGE_P_H +#define QPLACEIMAGE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include "qplaceimage.h" +#include "qplacecontent_p.h" + +QT_BEGIN_NAMESPACE + +class QPlaceImagePrivate : public QPlaceContentPrivate +{ +public: + QPlaceImagePrivate(); + QPlaceImagePrivate(const QPlaceImagePrivate &other); + + ~QPlaceImagePrivate(); + + bool compare(const QPlaceContentPrivate *other) const; + + Q_DEFINE_CONTENT_PRIVATE_HELPER(QPlaceImage, QPlaceContent::ImageType) + + QUrl url; + QString id; + QString mimeType; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacemanager.cpp b/src/location/places/qplacemanager.cpp new file mode 100644 index 0000000..e78489f --- /dev/null +++ b/src/location/places/qplacemanager.cpp @@ -0,0 +1,489 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacemanager.h" +#include "qplacemanagerengine.h" +#include "qplacemanagerengine_p.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QPlaceManager + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-manager + \since 5.6 + + \brief The QPlaceManager class provides the interface which allows clients to access + places stored in a particular backend. + + The following table gives an overview of the functionality provided by the QPlaceManager + \table + \header + \li Functionality + \li Description + \row + \li Searching for places + \li Using set of parameters such as a search term and search area, relevant places + can be returned to the user. + \row + \li Categories + \li Places can be classified as belonging to different categories. The + manager supports access to these categories. + \row + \li Search term suggestions + \li Given a partially complete search term, a list of potential + search terms can be given. + \row + \li Recommendations + \li Given an existing place, a set of similar recommended places can + be suggested to the user. + \row + \li Rich Content + \li Rich content such as images, reviews etc can be retrieved in a paged + fashion. + \row + \li Place or Category management + \li Places and categories may be saved and removed. It is possible + for notifications to be given when this happens. + \row + \li Localization + \li Different locales may be specified to return place + data in different languages. + \endtable + + \section1 Obtaining a QPlaceManager Instance + Creation of a QPlaceManager is facilitated by the QGeoServiceProvider. + See \l {Initializing a manager} for an example on how to create a manager. + + + \section1 Asynchronous Interface + The QPlaceManager class provides an abstraction of the datastore which contains place information. + The functions provided by the QPlaceManager and primarily asynchronous and follow + a request-reply model. Typically a request is given to the manager, consisting + of a various set of parameters and a reply object is created. The reply object + has a signal to notify when the request is done, and once completed, the reply + contains the results of the request, along with any errors that occurred, if any. + + An asynchronous request is generally handled as follows: + \snippet places/requesthandler.h Simple search + \dots + \dots + \snippet places/requesthandler.h Simple search handler + + See \l {Common Operations} for a list of examples demonstrating how the QPlaceManger + is used. + + \section1 Category Initialization + Sometime during startup of an application, the initializeCategories() function should + be called to setup the categories. Initializing the categories enables the usage of the + following functions: + + \list + \li QPlaceManager::childCategories() + \li QPlaceManager::category() + \li QPlaceManager::parentCategoryId() + \li QPlaceManager::childCategoryIds(); + \endlist + + If the categories need to be refreshed or reloaded, the initializeCategories() function + may be called again. + +*/ + +/*! + Constructs a new manager with the specified \a parent and with the + implementation provided by \a engine. + + This constructor is used internally by QGeoServiceProviderFactory. Regular + users should acquire instances of QGeoRoutingManager with + QGeoServiceProvider::routingManager(); +*/ +QPlaceManager::QPlaceManager(QPlaceManagerEngine *engine, QObject *parent) + : QObject(parent), d(engine) +{ + if (d) { + d->setParent(this); + d->d_ptr->manager = this; + + qRegisterMetaType(); + + connect(d, SIGNAL(finished(QPlaceReply*)), this, SIGNAL(finished(QPlaceReply*))); + connect(d, SIGNAL(error(QPlaceReply*,QPlaceReply::Error)), + this, SIGNAL(error(QPlaceReply*,QPlaceReply::Error))); + + connect(d, SIGNAL(placeAdded(QString)), + this, SIGNAL(placeAdded(QString)), Qt::QueuedConnection); + connect(d, SIGNAL(placeUpdated(QString)), + this, SIGNAL(placeUpdated(QString)), Qt::QueuedConnection); + connect(d, SIGNAL(placeRemoved(QString)), + this, SIGNAL(placeRemoved(QString)), Qt::QueuedConnection); + + connect(d, SIGNAL(categoryAdded(QPlaceCategory,QString)), + this, SIGNAL(categoryAdded(QPlaceCategory,QString))); + connect(d, SIGNAL(categoryUpdated(QPlaceCategory,QString)), + this, SIGNAL(categoryUpdated(QPlaceCategory,QString))); + connect(d, SIGNAL(categoryRemoved(QString,QString)), + this, SIGNAL(categoryRemoved(QString,QString))); + connect(d, SIGNAL(dataChanged()), + this, SIGNAL(dataChanged()), Qt::QueuedConnection); + } else { + qFatal("The place manager engine that was set for this place manager was NULL."); + } +} + +/*! + Destroys the manager. This destructor is used internally by QGeoServiceProvider + and should never need to be called in application code. +*/ +QPlaceManager::~QPlaceManager() +{ + delete d; +} + +/*! + Returns the name of the manager +*/ +QString QPlaceManager::managerName() const +{ + return d->managerName(); +} + +/*! + Returns the manager version. +*/ +int QPlaceManager::managerVersion() const +{ + return d->managerVersion(); +} + +/*! + Retrieves a details of place corresponding to the given \a placeId. + + See \l {QML Places API#Fetching Place Details}{Fetching Place Details} for an example of usage. +*/ +QPlaceDetailsReply *QPlaceManager::getPlaceDetails(const QString &placeId) const +{ + return d->getPlaceDetails(placeId); +} + +/*! + Retrieves content for a place according to the parameters specified in \a request. + + See \l {Fetching Rich Content} for an example of usage. +*/ +QPlaceContentReply *QPlaceManager::getPlaceContent(const QPlaceContentRequest &request) const +{ + return d->getPlaceContent(request); +} + +/*! + Searches for places according to the parameters specified in \a request. + + See \l {Discovery/Search} for an example of usage. +*/ +QPlaceSearchReply *QPlaceManager::search(const QPlaceSearchRequest &request) const +{ + return d->search(request); +} + +/*! + Requests a set of search term suggestions according to the parameters specified in \a request. + The \a request can hold the incomplete search term, along with other data such + as a search area to narrow down relevant results. + + See \l {Search Suggestions} for an example of usage. +*/ +QPlaceSearchSuggestionReply *QPlaceManager::searchSuggestions(const QPlaceSearchRequest &request) const +{ + return d->searchSuggestions(request); +} + +/*! + Saves a specified \a place. + + See \l {Saving a place cpp} for an example of usage. +*/ +QPlaceIdReply *QPlaceManager::savePlace(const QPlace &place) +{ + return d->savePlace(place); +} + +/*! + Removes the place corresponding to \a placeId from the manager. + + See \l {Removing a place cpp} for an example of usage. +*/ +QPlaceIdReply *QPlaceManager::removePlace(const QString &placeId) +{ + return d->removePlace(placeId); +} + +/*! + Saves a \a category that is a child of the category specified by \a parentId. + An empty \a parentId means \a category is saved as a top level category. + + See \l {Saving a category} for an example of usage. +*/ +QPlaceIdReply *QPlaceManager::saveCategory(const QPlaceCategory &category, const QString &parentId) +{ + return d->saveCategory(category, parentId); +} + +/*! + Removes the category corresponding to \a categoryId from the manager. + + See \l {Removing a category} for an example of usage. +*/ +QPlaceIdReply *QPlaceManager::removeCategory(const QString &categoryId) +{ + return d->removeCategory(categoryId); +} + +/*! + Initializes the categories of the manager. + + See \l {Using Categories} for an example of usage. +*/ +QPlaceReply *QPlaceManager::initializeCategories() +{ + return d->initializeCategories(); +} + +/*! + Returns the parent category identifier of the category corresponding to \a categoryId. +*/ +QString QPlaceManager::parentCategoryId(const QString &categoryId) const +{ + return d->parentCategoryId(categoryId); +} + +/*! + Returns the child category identifiers of the category corresponding to \a parentId. + If \a parentId is empty then all top level category identifiers are returned. +*/ +QStringList QPlaceManager::childCategoryIds(const QString &parentId) const +{ + return d->childCategoryIds(parentId); +} + +/*! + Returns the category corresponding to the given \a categoryId. +*/ +QPlaceCategory QPlaceManager::category(const QString &categoryId) const +{ + return d->category(categoryId); +} + +/*! + Returns a list of categories that are children of the category corresponding to \a parentId. + If \a parentId is empty, all the top level categories are returned. +*/ +QList QPlaceManager::childCategories(const QString &parentId) const +{ + return d->childCategories(parentId); +} + +/*! + Returns a list of preferred locales. The locales are used as a hint to the manager for what language + place and category details should be returned in. + + If the first specified locale cannot be accommodated, the manager falls back to the next and so forth. + Some manager backends may not support a set of locales which are rigidly defined. An arbitrary + example is that some places in France could have French and English localizations, while + certain areas in America may only have the English localization available. In this example, + the set of supported locales is context dependent on the search location. + + If the manager cannot accommodate any of the preferred locales, the manager falls + back to using a supported language that is backend specific. + + Support for locales may vary from provider to provider. For those that do support it, + by default, the global default locale is set as the manager's only locale. + + For managers that do not support locales, the locale list is always empty. +*/ +QList QPlaceManager::locales() const +{ + return d->locales(); +} + +/*! + Convenience function which sets the manager's list of preferred locales + to a single \a locale. +*/ +void QPlaceManager::setLocale(const QLocale &locale) +{ + QList locales; + locales << locale; + d->setLocales(locales); +} + +/*! + Set the list of preferred \a locales. +*/ +void QPlaceManager::setLocales(const QList &locales) +{ + d->setLocales(locales); +} + +/*! + Returns a pruned or modified version of the \a original place + which is suitable to be saved into this manager. + + Only place details that are supported by this manager is + present in the modified version. Manager specific data such + as the place id, is not copied over from the \a original. +*/ +QPlace QPlaceManager::compatiblePlace(const QPlace &original) +{ + return d->compatiblePlace(original); +} + +/*! + Returns a reply which contains a list of places which correspond/match those + specified in the \a request. The places specified in the request come from a + different manager. +*/ +QPlaceMatchReply *QPlaceManager::matchingPlaces(const QPlaceMatchRequest &request) const +{ + return d->matchingPlaces(request); +} + +/*! + \fn void QPlaceManager::finished(QPlaceReply *reply) + + This signal is emitted when \a reply has finished processing. + + If reply->error() equals QPlaceReply::NoError then the processing + finished successfully. + + This signal and QPlaceReply::finished() will be emitted at the same time. + + \note Do not delete the \a reply object in the slot connected to this signal. + Use deleteLater() instead. +*/ + +/*! + \fn void QPlaceManager::error(QPlaceReply *reply, QPlaceReply::Error error, const QString &errorString) + + This signal is emitted when an error has been detected in the processing of + \a reply. The QPlaceManager::finished() signal will probably follow. + + The error will be described by the error code \a error. If \a errorString is + not empty it will contain a textual description of the error meant for developers + and not end users. + + This signal and QPlaceReply::error() will be emitted at the same time. + + \note Do not delete the \a reply object in the slot connected to this signal. + Use deleteLater() instead. +*/ + +/*! + \fn void QPlaceManager::placeAdded(const QString &placeId) + + This signal is emitted if a place has been added to the manager engine's datastore. + The particular added place is specified by \a placeId. + + This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManager::placeUpdated(const QString &placeId) + + This signal is emitted if a place has been modified in the manager's datastore. + The particular modified place is specified by \a placeId. + + This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManager::placeRemoved(const QString &placeId) + + This signal is emitted if a place has been removed from the manager's datastore. + The particular place that has been removed is specified by \a placeId. + + This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManager::categoryAdded(const QPlaceCategory &category, const QString &parentId) + + This signal is emitted if a \a category has been added to the manager's datastore. + The parent of the \a category is specified by \a parentId. + + This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManager::categoryUpdated(const QPlaceCategory &category, const QString &parentId) + + This signal is emitted if a \a category has been modified in the manager's datastore. + The parent of the modified category is specified by \a parentId. + + This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManager::categoryRemoved(const QString &categoryId, const QString &parentId) + + This signal is emitted when the category corresponding to \a categoryId has + been removed from the manager's datastore. The parent of the removed category + is specified by \a parentId. + + This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn QPlaceManager::dataChanged() + This signal is emitted by the manager if there are large scale changes to its + underlying datastore and the manager considers these changes radical enough + to require clients to reload all data. + + If the signal is emitted, no other signals will be emitted for the associated changes. + + This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature. +*/ + +QT_END_NAMESPACE diff --git a/src/location/places/qplacemanager.h b/src/location/places/qplacemanager.h new file mode 100644 index 0000000..bd4b167 --- /dev/null +++ b/src/location/places/qplacemanager.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEMANAGER_H +#define QPLACEMANAGER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceManagerEngine; +class QPlaceSearchRequest; +class QPlaceSearchReply; + +class Q_LOCATION_EXPORT QPlaceManager : public QObject +{ + Q_OBJECT +public: + ~QPlaceManager(); + + QString managerName() const; + int managerVersion() const; + + QPlaceDetailsReply *getPlaceDetails(const QString &placeId) const; + + QPlaceContentReply *getPlaceContent(const QPlaceContentRequest &request) const; + + QPlaceSearchReply *search(const QPlaceSearchRequest &query) const; + + QPlaceSearchSuggestionReply *searchSuggestions(const QPlaceSearchRequest &request) const; + + QPlaceIdReply *savePlace(const QPlace &place); + QPlaceIdReply *removePlace(const QString &placeId); + + QPlaceIdReply *saveCategory(const QPlaceCategory &category, const QString &parentId = QString()); + QPlaceIdReply *removeCategory(const QString &categoryId); + + QPlaceReply *initializeCategories(); + QString parentCategoryId(const QString &categoryId) const; + QStringList childCategoryIds(const QString &parentId = QString()) const; + + QPlaceCategory category(const QString &categoryId) const; + QList childCategories(const QString &parentId = QString()) const; + + QList locales() const; + void setLocale(const QLocale &locale); + void setLocales(const QList &locale); + + QPlace compatiblePlace(const QPlace &place); + + QPlaceMatchReply *matchingPlaces(const QPlaceMatchRequest &request) const; + +Q_SIGNALS: + void finished(QPlaceReply *reply); + void error(QPlaceReply *, QPlaceReply::Error error, const QString &errorString = QString()); + + void placeAdded(const QString &placeId); + void placeUpdated(const QString &placeId); + void placeRemoved(const QString &placeId); + + void categoryAdded(const QPlaceCategory &category, const QString &parentId); + void categoryUpdated(const QPlaceCategory &category, const QString &parentId); + void categoryRemoved(const QString &categoryId, const QString &parentId); + void dataChanged(); + +private: + explicit QPlaceManager(QPlaceManagerEngine *engine, QObject *parent = Q_NULLPTR); + Q_DISABLE_COPY(QPlaceManager) + + QPlaceManagerEngine *d; + + friend class QGeoServiceProvider; + friend class QGeoServiceProviderPrivate; + friend class QPlaceIcon; +}; + +QT_END_NAMESPACE + +#endif // QPLACEMANAGER_H diff --git a/src/location/places/qplacemanagerengine.cpp b/src/location/places/qplacemanagerengine.cpp new file mode 100644 index 0000000..c1b5f23 --- /dev/null +++ b/src/location/places/qplacemanagerengine.cpp @@ -0,0 +1,462 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacemanagerengine.h" +#include "qplacemanagerengine_p.h" +#include "unsupportedreplies_p.h" + +#include + +#include "qplaceicon.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QPlaceManagerEngine + \inmodule QtLocation + \ingroup QtLocation-impl + \ingroup QtLocation-places + \ingroup QtLocation-places-manager + \since 5.6 + + \brief The QPlaceManagerEngine class provides an interface for + implementers of QGeoServiceProvider plugins who want to provide access to place + functionality. + + Application developers need not concern themselves with the QPlaceManagerEngine. + Backend implementers however will need to derive from QPlaceManagerEngine and provide + implementations for the abstract virtual functions. + + For more information on writing a backend see the \l {Places Backend} documentation. + + \sa QPlaceManager +*/ + +/*! + Constructs a new engine with the specified \a parent, using \a parameters to pass any + implementation specific data to the engine. +*/ +QPlaceManagerEngine::QPlaceManagerEngine(const QVariantMap ¶meters, + QObject *parent) +: QObject(parent), d_ptr(new QPlaceManagerEnginePrivate) +{ + qRegisterMetaType(); + qRegisterMetaType(); + Q_UNUSED(parameters) +} + +/*! + Destroys this engine. +*/ +QPlaceManagerEngine::~QPlaceManagerEngine() +{ + delete d_ptr; +} + +/*! + \internal + Sets the name which this engine implementation uses to distinguish itself + from the implementations provided by other plugins to \a managerName. + + This function does not need to be called by engine implementers, + it is implicitly called by QGeoServiceProvider to set the manager + name to be the same as the provider's. +*/ +void QPlaceManagerEngine::setManagerName(const QString &managerName) +{ + d_ptr->managerName = managerName; +} + +/*! + Returns the name which this engine implementation uses to distinguish + itself from the implementations provided by other plugins. + + The manager name is automatically set to be the same + as the QGeoServiceProviderFactory::providerName(). +*/ +QString QPlaceManagerEngine::managerName() const +{ + return d_ptr->managerName; +} + +/*! + \internal + Sets the version of this engine implementation to \a managerVersion. + + The combination of managerName() and managerVersion() should be unique + amongst plugin implementations. +*/ +void QPlaceManagerEngine::setManagerVersion(int managerVersion) +{ + d_ptr->managerVersion = managerVersion; +} + +/*! + Returns the version of this engine implementation. + + The manager version is automatically set to be the same + as the QGeoServiceProviderFactory::providerVersion(). +*/ +int QPlaceManagerEngine::managerVersion() const +{ + return d_ptr->managerVersion; +} + +/*! + Retrieves details of place corresponding to the given \a placeId. +*/ +QPlaceDetailsReply *QPlaceManagerEngine::getPlaceDetails(const QString &placeId) +{ + Q_UNUSED(placeId) + + return new QPlaceDetailsReplyUnsupported(this); +} + +/*! + Retrieves content for a place according to the parameters specified in \a request. +*/ +QPlaceContentReply *QPlaceManagerEngine::getPlaceContent(const QPlaceContentRequest &request) +{ + Q_UNUSED(request) + + return new QPlaceContentReplyUnsupported(this); +} + +/*! + Searches for places according to the parameters specified in \a request. +*/ +QPlaceSearchReply *QPlaceManagerEngine::search(const QPlaceSearchRequest &request) +{ + Q_UNUSED(request) + + return new QPlaceSearchReplyUnsupported(QPlaceReply::UnsupportedError, + QStringLiteral("Place search is not supported."), this); +} + +/*! + Requests a set of search term suggestions according to the parameters specified in \a request. +*/ +QPlaceSearchSuggestionReply *QPlaceManagerEngine::searchSuggestions( + const QPlaceSearchRequest &request) +{ + Q_UNUSED(request) + + return new QPlaceSearchSuggestionReplyUnsupported(this); +} + +/*! + Saves a specified \a place to the manager engine's datastore. +*/ +QPlaceIdReply *QPlaceManagerEngine::savePlace(const QPlace &place) +{ + Q_UNUSED(place) + + return new QPlaceIdReplyUnsupported(QStringLiteral("Save place is not supported"), + QPlaceIdReply::SavePlace, this); +} + +/*! + Removes the place corresponding to \a placeId from the manager engine's datastore. +*/ +QPlaceIdReply *QPlaceManagerEngine::removePlace(const QString &placeId) +{ + Q_UNUSED(placeId) + + return new QPlaceIdReplyUnsupported(QStringLiteral("Remove place is not supported"), + QPlaceIdReply::RemovePlace, this); +} + +/*! + Saves a \a category that is a child of the category specified by \a parentId. An empty + \a parentId means \a category is saved as a top level category. +*/ +QPlaceIdReply *QPlaceManagerEngine::saveCategory(const QPlaceCategory &category, + const QString &parentId) +{ + Q_UNUSED(category) + Q_UNUSED(parentId) + + return new QPlaceIdReplyUnsupported(QStringLiteral("Save category is not supported"), + QPlaceIdReply::SaveCategory, this); +} + +/*! + Removes the category corresponding to \a categoryId from the manager engine's datastore. +*/ + +QPlaceIdReply *QPlaceManagerEngine::removeCategory(const QString &categoryId) +{ + Q_UNUSED(categoryId) + + return new QPlaceIdReplyUnsupported(QStringLiteral("Remove category is not supported"), + QPlaceIdReply::RemoveCategory, this); +} + +/*! + Initializes the categories of the manager engine. +*/ +QPlaceReply *QPlaceManagerEngine::initializeCategories() +{ + return new QPlaceReplyUnsupported(QStringLiteral("Categories are not supported."), this); +} + +/*! + Returns the parent category identifier of the category corresponding to \a categoryId. +*/ +QString QPlaceManagerEngine::parentCategoryId(const QString &categoryId) const +{ + Q_UNUSED(categoryId) + + return QString(); +} + +/*! + Returns the child category identifiers of the category corresponding to \a categoryId. If + \a categoryId is empty then all top level category identifiers are returned. +*/ +QStringList QPlaceManagerEngine::childCategoryIds(const QString &categoryId) const +{ + Q_UNUSED(categoryId) + + return QStringList(); +} + +/*! + Returns the category corresponding to the given \a categoryId. +*/ +QPlaceCategory QPlaceManagerEngine::category(const QString &categoryId) const +{ + Q_UNUSED(categoryId) + + return QPlaceCategory(); +} + +/*! + Returns a list of categories that are children of the category corresponding to \a parentId. + If \a parentId is empty, all the top level categories are returned. +*/ +QList QPlaceManagerEngine::childCategories(const QString &parentId) const +{ + Q_UNUSED(parentId) + + return QList(); +} + +/*! + Returns a list of preferred locales. The locales are used as a hint to the manager engine for + what language place and category details should be returned in. + + If the first specified locale cannot be accommodated, the manager engine falls back to the next + and so forth. + + Support for locales may vary from provider to provider. For those that do support it, by + default, the \l {QLocale::setDefault()}{global default locale} will be used. If the manager + engine has no locales assigned to it, it implicitly uses the global default locale. For + engines that do not support locales, the locale list is always empty. +*/ +QList QPlaceManagerEngine::locales() const +{ + return QList(); +} + +/*! + Set the list of preferred \a locales. +*/ +void QPlaceManagerEngine::setLocales(const QList &locales) +{ + Q_UNUSED(locales) +} + +/*! + Returns the manager instance used to create this engine. +*/ +QPlaceManager *QPlaceManagerEngine::manager() const +{ + return d_ptr->manager; +} + +/*! + Returns a pruned or modified version of the \a original place + which is suitable to be saved by the manager engine. + + Only place details that are supported by this manager is + present in the modified version. Manager specific data such + as the place id, is not copied over from the \a original. +*/ +QPlace QPlaceManagerEngine::compatiblePlace(const QPlace &original) const +{ + Q_UNUSED(original); + return QPlace(); +} + +/*! + Returns a reply which contains a list of places which correspond/match those + specified in \a request. +*/ +QPlaceMatchReply * QPlaceManagerEngine::matchingPlaces(const QPlaceMatchRequest &request) +{ + Q_UNUSED(request) + + return new QPlaceMatchReplyUnsupported(this); +} + +/*! + QUrl QPlaceManagerEngine::constructIconUrl(const QPlaceIcon &icon, const QSize &size) + + Constructs an icon url from a given \a icon, \a size. The URL of the icon + image that most closely matches the given parameters is returned. +*/ +QUrl QPlaceManagerEngine::constructIconUrl(const QPlaceIcon &icon, const QSize &size) const +{ + Q_UNUSED(icon); + Q_UNUSED(size); + + return QUrl(); +} + +QPlaceManagerEnginePrivate::QPlaceManagerEnginePrivate() + : managerVersion(-1), manager(0) +{ +} + +QPlaceManagerEnginePrivate::~QPlaceManagerEnginePrivate() +{ +} + +/*! + \fn void QPlaceManagerEngine::finished(QPlaceReply *reply) + + This signal is emitted when \a reply has finished processing. + + If reply->error() equals QPlaceReply::NoError then the processing + finished successfully. + + This signal and QPlaceReply::finished() will be emitted at the same time. + + \note Do not delete the \a reply object in the slot connected to this signal. + Use deleteLater() instead. +*/ + +/*! + \fn void QPlaceManagerEngine::error(QPlaceReply * reply, QPlaceReply::Error error, const QString &errorString = QString()); + + This signal is emitted when an error has been detected in the processing of + \a reply. The QPlaceManager::finished() signal will probably follow. + + The error will be described by the error code \a error. If \a errorString is + not empty it will contain a textual description of the error meant for developers + and not end users. + + This signal and QPlaceReply::error() will be emitted at the same time. + + \note Do not delete the \a reply object in the slot connected to this signal. + Use deleteLater() instead. +*/ + +/*! + \fn void QPlaceManagerEngine::placeAdded(const QString &placeId) + + This signal is emitted if a place has been added to the manager engine's datastore. + The particular added place is specified by \a placeId. + + This signal is only emitted by manager engines that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManagerEngine::placeUpdated(const QString &placeId) + + This signal is emitted if a place has been modified in the manager engine's datastore. + The particular modified place is specified by \a placeId. + + This signal is only emitted by manager engines that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManagerEngine::placeRemoved(const QString &placeId) + + This signal is emitted if a place has been removed from the manager engine's datastore. + The particular place that has been removed is specified by \a placeId. + + This signal is only emitted by manager engines that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManagerEngine::categoryAdded(const QPlaceCategory &category, const QString &parentId) + + This signal is emitted if a \a category has been added to the manager engine's datastore. + The parent of the \a category is specified by \a parentId. + + This signal is only emitted by manager engines that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManagerEngine::categoryUpdated(const QPlaceCategory &category, const QString &parentId) + + This signal is emitted if a \a category has been modified in the manager engine's datastore. + The parent of the modified category is specified by \a parentId. + + This signal is only emitted by manager engines that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + \fn void QPlaceManagerEngine::categoryRemoved(const QString &categoryId, const QString &parentId) + + This signal is emitted when the category corresponding to \a categoryId has + been removed from the manager engine's datastore. The parent of the removed category + is specified by \a parentId. + + This signal is only emitted by manager engines that support the QPlaceManager::NotificationsFeature. + \sa dataChanged() +*/ + +/*! + * \fn QPlaceManagerEngine::dataChanged() + + This signal is emitted by the engine if there are large scale changes to its + underlying datastore and the engine considers these changes radical enough + to require clients to reload all data. + + If the signal is emitted, no other signals will be emitted for the associated changes. +*/ + +QT_END_NAMESPACE + +#include "moc_qplacemanagerengine.cpp" diff --git a/src/location/places/qplacemanagerengine.h b/src/location/places/qplacemanagerengine.h new file mode 100644 index 0000000..0c11278 --- /dev/null +++ b/src/location/places/qplacemanagerengine.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEMANAGERENGINE_H +#define QPLACEMANAGERENGINE_H + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceManagerEnginePrivate; +class QPlaceMatchReply; +class QPlaceMatchRequest; +class QPlaceSearchReply; +class QPlaceSearchRequest; +class QPlaceSearchSuggestionReply; + +class Q_LOCATION_EXPORT QPlaceManagerEngine : public QObject +{ + Q_OBJECT + +public: + explicit QPlaceManagerEngine(const QVariantMap ¶meters, QObject *parent = Q_NULLPTR); + virtual ~QPlaceManagerEngine(); + + QString managerName() const; + int managerVersion() const; + + virtual QPlaceDetailsReply *getPlaceDetails(const QString &placeId); + + virtual QPlaceContentReply *getPlaceContent(const QPlaceContentRequest &request); + + virtual QPlaceSearchReply *search(const QPlaceSearchRequest &request); + + virtual QPlaceSearchSuggestionReply *searchSuggestions(const QPlaceSearchRequest &request); + + virtual QPlaceIdReply *savePlace(const QPlace &place); + virtual QPlaceIdReply *removePlace(const QString &placeId); + + virtual QPlaceIdReply *saveCategory(const QPlaceCategory &category, const QString &parentId); + virtual QPlaceIdReply *removeCategory(const QString &categoryId); + + virtual QPlaceReply *initializeCategories(); + virtual QString parentCategoryId(const QString &categoryId) const; + virtual QStringList childCategoryIds(const QString &categoryId) const; + virtual QPlaceCategory category(const QString &categoryId) const; + + virtual QList childCategories(const QString &parentId) const; + + virtual QList locales() const; + virtual void setLocales(const QList &locales); + + virtual QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size) const; + + virtual QPlace compatiblePlace(const QPlace &original) const; + + virtual QPlaceMatchReply *matchingPlaces(const QPlaceMatchRequest &request); + +Q_SIGNALS: + void finished(QPlaceReply *reply); + void error(QPlaceReply *, QPlaceReply::Error error, const QString &errorString = QString()); + + void placeAdded(const QString &placeId); + void placeUpdated(const QString &placeId); + void placeRemoved(const QString &placeId); + + void categoryAdded(const QPlaceCategory &category, const QString &parentCategoryId); + void categoryUpdated(const QPlaceCategory &category, const QString &parentCategoryId); + void categoryRemoved(const QString &categoryId, const QString &parentCategoryId); + void dataChanged(); + +protected: + QPlaceManager *manager() const; + +private: + void setManagerName(const QString &managerName); + void setManagerVersion(int managerVersion); + + QPlaceManagerEnginePrivate *d_ptr; + Q_DISABLE_COPY(QPlaceManagerEngine) + + friend class QGeoServiceProviderPrivate; + friend class QPlaceManager; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacemanagerengine_p.h b/src/location/places/qplacemanagerengine_p.h new file mode 100644 index 0000000..1a1359a --- /dev/null +++ b/src/location/places/qplacemanagerengine_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEMANAGERENGINE_P_H +#define QPLACEMANAGERENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceManagerEnginePrivate +{ +public: + QPlaceManagerEnginePrivate(); + ~QPlaceManagerEnginePrivate(); + + QString managerName; + int managerVersion; + QPlaceManager *manager; + +private: + Q_DISABLE_COPY(QPlaceManagerEnginePrivate) +}; + +QT_END_NAMESPACE + +#endif // QPLACEMANAGERENGINE_P_H diff --git a/src/location/places/qplacematchreply.cpp b/src/location/places/qplacematchreply.cpp new file mode 100644 index 0000000..9794b3f --- /dev/null +++ b/src/location/places/qplacematchreply.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacematchreply.h" +#include "qplacereply_p.h" + + +QT_BEGIN_NAMESPACE +class QPlaceMatchReplyPrivate : public QPlaceReplyPrivate +{ +public: + QPlaceMatchReplyPrivate(){} + QList places; + QPlaceMatchRequest request; +}; + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +/*! + \class QPlaceMatchReply + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-replies + \since 5.6 + + \brief The QPlaceMatchReply class manages a place matching operation started by an + instance of QPlaceManager. + + If the operation is successful, the number of places in the reply matches those + in the request. If a particular place in the request is not found, a default + constructed place is used as a place holder in the reply. In this way, there + is always a one is to one relationship between input places in the request, + and output places in the reply. + + If the operation is not successful the number of places is always zero. + + See \l {Matching places between managers} for an example on how to use + a match reply. + + \sa QPlaceMatchRequest, QPlaceManager +*/ + +/*! + Constructs a match reply with a given \a parent. +*/ +QPlaceMatchReply::QPlaceMatchReply(QObject *parent) + : QPlaceReply(new QPlaceMatchReplyPrivate, parent) +{ +} + +/*! + Destroys the match reply. +*/ +QPlaceMatchReply::~QPlaceMatchReply() +{ +} + +/*! + Returns the type of reply. +*/ +QPlaceReply::Type QPlaceMatchReply::type() const +{ + return QPlaceReply::MatchReply; +} + + /*! + Returns a list of matching places; +*/ +QList QPlaceMatchReply::places() const +{ + Q_D(const QPlaceMatchReply); + return d->places; +} + +/*! + Sets the list of matching \a places. +*/ +void QPlaceMatchReply::setPlaces(const QList &places) +{ + Q_D(QPlaceMatchReply); + d->places = places; +} + +/*! + Returns the match request that was used to generate this reply. +*/ +QPlaceMatchRequest QPlaceMatchReply::request() const +{ + Q_D(const QPlaceMatchReply); + return d->request; +} + +/*! + Sets the match \a request used to generate this reply. +*/ +void QPlaceMatchReply::setRequest(const QPlaceMatchRequest &request) +{ + Q_D(QPlaceMatchReply); + d->request = request; +} diff --git a/src/location/places/qplacematchreply.h b/src/location/places/qplacematchreply.h new file mode 100644 index 0000000..df4b3fd --- /dev/null +++ b/src/location/places/qplacematchreply.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEMATCHREPLY_H +#define QPLACEMATCHREPLY_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceMatchReplyPrivate; +class Q_LOCATION_EXPORT QPlaceMatchReply : public QPlaceReply +{ + Q_OBJECT +public: + explicit QPlaceMatchReply(QObject *parent = Q_NULLPTR); + ~QPlaceMatchReply(); + + QPlaceReply::Type type() const; + + QList places() const; + QPlaceMatchRequest request() const; + +protected: + void setPlaces(const QList &results); + void setRequest(const QPlaceMatchRequest &request); +private: + Q_DISABLE_COPY(QPlaceMatchReply) + Q_DECLARE_PRIVATE(QPlaceMatchReply) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacematchrequest.cpp b/src/location/places/qplacematchrequest.cpp new file mode 100644 index 0000000..89343dc --- /dev/null +++ b/src/location/places/qplacematchrequest.cpp @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacematchrequest.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceMatchRequestPrivate : public QSharedData +{ +public: + QPlaceMatchRequestPrivate(); + QPlaceMatchRequestPrivate(const QPlaceMatchRequestPrivate &other); + ~QPlaceMatchRequestPrivate(); + + QPlaceMatchRequestPrivate &operator=(const QPlaceMatchRequestPrivate &other); + bool operator==(const QPlaceMatchRequestPrivate &other) const; + + void clear(); + + QList places; + QVariantMap parameters; +}; + +QPlaceMatchRequestPrivate::QPlaceMatchRequestPrivate() + : QSharedData() +{ +} + +QPlaceMatchRequestPrivate::QPlaceMatchRequestPrivate(const QPlaceMatchRequestPrivate &other) + : QSharedData(other), + places(other.places), + parameters(other.parameters) +{ +} + +QPlaceMatchRequestPrivate::~QPlaceMatchRequestPrivate() +{ +} + +QPlaceMatchRequestPrivate &QPlaceMatchRequestPrivate::operator=(const QPlaceMatchRequestPrivate &other) +{ + if (this != &other) { + places = other.places; + parameters = other.parameters; + } + + return *this; +} + +bool QPlaceMatchRequestPrivate::operator==(const QPlaceMatchRequestPrivate &other) const +{ + return (places == other.places + && parameters == other.parameters); +} + +void QPlaceMatchRequestPrivate::clear() +{ + places.clear(); + parameters.clear(); +} + +/*! + \class QPlaceMatchRequest + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-requests + \since 5.6 + + \brief The QPlaceMatchRequest class is used to find places from one manager that match those from another. It represents + a set of request parameters. + + Places from another manager that may have corresponding/matching places in the current manager are assigned using setPlaces() or setResults(). + A set of further parameters are specified which determines the criteria for matching. + + The typical key for matching is the QPlaceMatchRequest::AlternativeId, the value is an alternative identifier attribute type of the format + x_id_ for example x_id_here. The provider name is name supplied to the QGeoServiceProvider instance. + + See \l {Matching places between managers} for an example on how to use a match request. + + \sa QPlaceMatchReply, QPlaceManager +*/ + +/*! + \variable QPlaceMatchRequest::AlternativeId + The key to specify that matching is to be accomplished via an alternative place identifier. +*/ +const QString QPlaceMatchRequest::AlternativeId(QLatin1String("alternativeId")); + +/*! + Default constructor. Constructs a new request object. +*/ +QPlaceMatchRequest::QPlaceMatchRequest() + : d_ptr(new QPlaceMatchRequestPrivate()) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QPlaceMatchRequest::QPlaceMatchRequest(const QPlaceMatchRequest &other) + : d_ptr(other.d_ptr) +{ +} + +/*! + Destroys the request object. +*/ +QPlaceMatchRequest::~QPlaceMatchRequest() +{ +} + +/*! + Assigns \a other to this search request and returns a reference + to this match request. +*/ +QPlaceMatchRequest &QPlaceMatchRequest::operator= (const QPlaceMatchRequest & other) +{ + if (this == &other) + return *this; + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if \a other is equal to this match request, + otherwise returns false. +*/ +bool QPlaceMatchRequest::operator== (const QPlaceMatchRequest &other) const +{ + Q_D(const QPlaceMatchRequest); + return *d == *other.d_func(); +} + +/*! + Returns true if \a other is not equal to this match request, + otherwise returns false. +*/ +bool QPlaceMatchRequest::operator!= (const QPlaceMatchRequest &other) const +{ + Q_D(const QPlaceMatchRequest); + return !(*d == *other.d_func()); +} + + +/*! + Returns a list of places which are to be matched. +*/ +QList QPlaceMatchRequest::places() const +{ + Q_D(const QPlaceMatchRequest); + return d->places; +} + +/*! + Sets a list of \a places which are to be matched. + + \sa setResults() +*/ +void QPlaceMatchRequest::setPlaces(const QList places) +{ + Q_D(QPlaceMatchRequest); + d->places = places; +} + +/*! + Convenience function which uses a set of search \a results to set + the places which should be matched. + + \sa setPlaces() +*/ +void QPlaceMatchRequest::setResults(const QList &results) +{ + Q_D(QPlaceMatchRequest); + QList places; + foreach (const QPlaceSearchResult &result, results) { + if (result.type() == QPlaceSearchResult::PlaceResult) { + QPlaceResult placeResult = result; + places.append(placeResult.place()); + } + } + + d->places = places; +} + +/*! + Returns the parameters for matching places. +*/ +QVariantMap QPlaceMatchRequest::parameters() const +{ + Q_D(const QPlaceMatchRequest); + return d->parameters; +} + +/*! + Sets the \a parameters for matching places. +*/ +void QPlaceMatchRequest::setParameters(const QVariantMap ¶meters) +{ + Q_D(QPlaceMatchRequest); + d->parameters = parameters; +} + +/*! + Clears the match request. +*/ +void QPlaceMatchRequest::clear() +{ + Q_D(QPlaceMatchRequest); + d->clear(); +} + +inline QPlaceMatchRequestPrivate *QPlaceMatchRequest::d_func() +{ + return static_cast(d_ptr.data()); +} + +inline const QPlaceMatchRequestPrivate *QPlaceMatchRequest::d_func() const +{ + return static_cast(d_ptr.constData()); +} + +QT_END_NAMESPACE diff --git a/src/location/places/qplacematchrequest.h b/src/location/places/qplacematchrequest.h new file mode 100644 index 0000000..24f9d9f --- /dev/null +++ b/src/location/places/qplacematchrequest.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEMATCHREQUEST_H +#define QPLACEMATCHREQUEST_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceMatchRequestPrivate; + +class Q_LOCATION_EXPORT QPlaceMatchRequest +{ +public: + static const QString AlternativeId; + + QPlaceMatchRequest(); + QPlaceMatchRequest(const QPlaceMatchRequest &other); + + + QPlaceMatchRequest &operator=(const QPlaceMatchRequest &other); + + bool operator==(const QPlaceMatchRequest &other) const; + bool operator!=(const QPlaceMatchRequest &other) const; + + ~QPlaceMatchRequest(); + + QList places() const; + void setPlaces(const QList places); + + void setResults(const QList &results); + + QVariantMap parameters() const; + void setParameters(const QVariantMap ¶meters); + + void clear(); + +private: + QSharedDataPointer d_ptr; + inline QPlaceMatchRequestPrivate *d_func(); + inline const QPlaceMatchRequestPrivate *d_func() const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplaceproposedsearchresult.cpp b/src/location/places/qplaceproposedsearchresult.cpp new file mode 100644 index 0000000..20a6be9 --- /dev/null +++ b/src/location/places/qplaceproposedsearchresult.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Aaron McCarthy +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceproposedsearchresult.h" +#include "qplaceproposedsearchresult_p.h" + +QT_BEGIN_NAMESPACE + +QPlaceProposedSearchResultPrivate::QPlaceProposedSearchResultPrivate() +{ +} + +QPlaceProposedSearchResultPrivate::QPlaceProposedSearchResultPrivate(const QPlaceProposedSearchResultPrivate &other) +: QPlaceSearchResultPrivate(other), searchRequest(other.searchRequest) +{ +} + +QPlaceProposedSearchResultPrivate::~QPlaceProposedSearchResultPrivate() +{ +} + +bool QPlaceProposedSearchResultPrivate::compare(const QPlaceSearchResultPrivate *other) const +{ + const QPlaceProposedSearchResultPrivate *od = static_cast(other); + return QPlaceSearchResultPrivate::compare(other) && searchRequest == od->searchRequest; +} + +/*! + \class QPlaceProposedSearchResult + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since Qt Location 5.2 + + \brief The QPlaceProposedSearchResult class represents a search result containing a proposed search. + + \sa QPlaceSearchResult +*/ + +/*! + Constructs a new proposed search result. +*/ +QPlaceProposedSearchResult::QPlaceProposedSearchResult() +: QPlaceSearchResult(new QPlaceProposedSearchResultPrivate) +{ +} + +/*! + \fn QPlaceProposedSearchResult::QPlaceProposedSearchResult(const QPlaceSearchRequest &other) + + Contructs a copy of \a other if possible, otherwise constructs a default proposed search + result. +*/ +Q_IMPLEMENT_SEARCHRESULT_COPY_CTOR(QPlaceProposedSearchResult) + +Q_IMPLEMENT_SEARCHRESULT_D_FUNC(QPlaceProposedSearchResult) + +/*! + Destroys the proposed search result. +*/ +QPlaceProposedSearchResult::~QPlaceProposedSearchResult() +{ +} + +/*! + Returns a place search request that can be used to perform an additional proposed search. +*/ +QPlaceSearchRequest QPlaceProposedSearchResult::searchRequest() const +{ + Q_D(const QPlaceProposedSearchResult); + return d->searchRequest; +} + +/*! + Sets the proposed search request to \a request. +*/ +void QPlaceProposedSearchResult::setSearchRequest(const QPlaceSearchRequest &request) +{ + Q_D(QPlaceProposedSearchResult); + d->searchRequest = request; +} + +QT_END_NAMESPACE diff --git a/src/location/places/qplaceproposedsearchresult.h b/src/location/places/qplaceproposedsearchresult.h new file mode 100644 index 0000000..d949717 --- /dev/null +++ b/src/location/places/qplaceproposedsearchresult.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Aaron McCarthy +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPROPOSEDSEARCHRESULT_H +#define QPROPOSEDSEARCHRESULT_H + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceProposedSearchResultPrivate; + +class Q_LOCATION_EXPORT QPlaceProposedSearchResult : public QPlaceSearchResult +{ +public: + QPlaceProposedSearchResult(); + +#ifdef Q_QDOC + QPlaceProposedSearchResult(const QPlaceSearchRequest &other); +#else + Q_DECLARE_SEARCHRESULT_COPY_CTOR(QPlaceProposedSearchResult) +#endif + + ~QPlaceProposedSearchResult(); + + QPlaceSearchRequest searchRequest() const; + void setSearchRequest(const QPlaceSearchRequest &request); + +private: + Q_DECLARE_SEARCHRESULT_D_FUNC(QPlaceProposedSearchResult) +}; + +Q_DECLARE_TYPEINFO(QPlaceProposedSearchResult, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +#endif // QPROPOSEDSEARCHRESULT_H diff --git a/src/location/places/qplaceproposedsearchresult_p.h b/src/location/places/qplaceproposedsearchresult_p.h new file mode 100644 index 0000000..46f9510 --- /dev/null +++ b/src/location/places/qplaceproposedsearchresult_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Aaron McCarthy +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPROPOSEDSEARCHRESULT_P_H +#define QPROPOSEDSEARCHRESULT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplacesearchresult_p.h" + +QT_BEGIN_NAMESPACE + +class QPlaceProposedSearchResultPrivate : public QPlaceSearchResultPrivate +{ +public: + QPlaceProposedSearchResultPrivate(); + QPlaceProposedSearchResultPrivate(const QPlaceProposedSearchResultPrivate &other); + + ~QPlaceProposedSearchResultPrivate(); + + bool compare(const QPlaceSearchResultPrivate *other) const Q_DECL_OVERRIDE; + + Q_DEFINE_SEARCHRESULT_PRIVATE_HELPER(QPlaceProposedSearchResult, QPlaceSearchResult::ProposedSearchResult) + + QPlaceSearchRequest searchRequest; +}; + +QT_END_NAMESPACE + +#endif // QPROPOSEDSEARCHRESULT_P_H diff --git a/src/location/places/qplaceratings.cpp b/src/location/places/qplaceratings.cpp new file mode 100644 index 0000000..391db37 --- /dev/null +++ b/src/location/places/qplaceratings.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceratings.h" +#include "qplaceratings_p.h" + +QT_USE_NAMESPACE + +QPlaceRatingsPrivate::QPlaceRatingsPrivate() + : QSharedData(), average(0), maximum(0), count(0) +{ +} + +QPlaceRatingsPrivate::QPlaceRatingsPrivate(const QPlaceRatingsPrivate &other) +: QSharedData(), average(0), maximum(other.maximum), count(other.count) +{ +} + +QPlaceRatingsPrivate::~QPlaceRatingsPrivate() +{ +} + +bool QPlaceRatingsPrivate::operator==(const QPlaceRatingsPrivate &other) const +{ + return average == other.average && maximum == other.maximum && count == other.count; +} + +bool QPlaceRatingsPrivate::isEmpty() const +{ + return count == 0 && average == 0 && maximum == 0; +} + +/*! + \class QPlaceRatings + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceRatings class holds rating information about a place. + + Rating information is used to describe how good a place is conceived to be. + Typically this information is visualized as a number of stars. + The average() function returns an aggregated ratings value out of a possible + maximum as given by the maximum() function. + + \snippet places/requesthandler.h Ratings +*/ + +/*! + Constructs a new ratings object. +*/ +QPlaceRatings::QPlaceRatings() + : d(new QPlaceRatingsPrivate) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QPlaceRatings::QPlaceRatings(const QPlaceRatings &other) + :d(other.d) +{ +} + +/*! + Destroys the ratings object. +*/ +QPlaceRatings::~QPlaceRatings() +{ +} + +/*! + Assigns \a other to this ratings object and returns + a reference to this ratings object. +*/ +QPlaceRatings &QPlaceRatings::operator=(const QPlaceRatings &other) +{ + if (this == &other) + return *this; + + d = other.d; + return *this; +} + +/*! + Returns true if \a other is equal to this ratings object, + otherwise returns false. +*/ +bool QPlaceRatings::operator==(const QPlaceRatings &other) const +{ + return (*(d.constData()) == *(other.d.constData())); +} + +/*! + \fn bool QPlaceRatings::operator!=(const QPlaceRatings &other) const + + Returns true if \a other is not equal to this ratings object, + otherwise returns false. +*/ + +/*! + Returns the average value of individual ratings. +*/ +qreal QPlaceRatings::average() const +{ + return d->average; +} + +/*! + Sets the \a average value of the ratings. +*/ +void QPlaceRatings::setAverage(qreal average) +{ + d->average = average; +} + +/*! + Returns the maximum possible rating value. +*/ +qreal QPlaceRatings::maximum() const +{ + return d->maximum; +} + +/*! + Sets the maximum possible rating value to \a max. +*/ +void QPlaceRatings::setMaximum(qreal max) +{ + d->maximum = max; +} + +/*! + Returns the total number of individual ratings. +*/ +int QPlaceRatings::count() const +{ + return d->count; +} + +/*! + Sets the total number of individual ratings to \a count. +*/ +void QPlaceRatings::setCount(int count) +{ + d->count = count; +} + +/*! + Returns true if all fields of the place ratings are 0; otherwise returns false. +*/ +bool QPlaceRatings::isEmpty() const +{ + return d->isEmpty(); +} diff --git a/src/location/places/qplaceratings.h b/src/location/places/qplaceratings.h new file mode 100644 index 0000000..3cda5be --- /dev/null +++ b/src/location/places/qplaceratings.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACERATINGS_H +#define QPLACERATINGS_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceRatingsPrivate; + +class Q_LOCATION_EXPORT QPlaceRatings +{ +public: + QPlaceRatings(); + QPlaceRatings(const QPlaceRatings &other); + + ~QPlaceRatings(); + + QPlaceRatings &operator=(const QPlaceRatings &other); + + bool operator==(const QPlaceRatings &other) const; + bool operator!=(const QPlaceRatings &other) const { + return !(other == *this); + } + + qreal average() const; + void setAverage(qreal average); + + int count() const; + void setCount(int count); + + qreal maximum() const; + void setMaximum(qreal max); + + bool isEmpty() const; + +private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceRatings) + +#endif diff --git a/src/location/places/qplaceratings_p.h b/src/location/places/qplaceratings_p.h new file mode 100644 index 0000000..21d441a --- /dev/null +++ b/src/location/places/qplaceratings_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACERATINGS_P_H +#define QPLACERATINGS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceRatingsPrivate : public QSharedData +{ +public: + QPlaceRatingsPrivate(); + QPlaceRatingsPrivate(const QPlaceRatingsPrivate &other); + + ~QPlaceRatingsPrivate(); + + bool operator==(const QPlaceRatingsPrivate &other) const; + + bool isEmpty() const; + + qreal average; + qreal maximum; + int count; +}; + +QT_END_NAMESPACE + +#endif // QPLACERATING_P_H diff --git a/src/location/places/qplacereply.cpp b/src/location/places/qplacereply.cpp new file mode 100644 index 0000000..0590871 --- /dev/null +++ b/src/location/places/qplacereply.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacereply.h" +#include "qplacereply_p.h" + +QT_USE_NAMESPACE + +/*! + \class QPlaceReply + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-replies + \since 5.6 + + \brief The QPlaceReply class manages an operation started by an instance of QPlaceManager and + serves as a base class for more specialized replies. + + The QPlaceReply and each of its specialized subclasses manage the + state and results of their corresponding operations. The QPlaceReply itself is used + for operations that have no results, that is, it only necessary to know if the operation + succeeded or failed. + + The finished() signal can be used to monitor the progress of an operation. + Once an operation is complete, the error() and errorString() methods provide information + on whether the operation completed successfully. If successful, the reply + will contain the results for that operation, that is, each subclass will have appropriate + functions to retrieve the results of an operation. + + \sa QPlaceManager +*/ + +/*! + \enum QPlaceReply::Error + + Describes an error which occurred during an operation. + \value NoError + No error has occurred + \value PlaceDoesNotExistError + A specified place could not be found + \value CategoryDoesNotExistError + A specified category could not be found + \value CommunicationError + An error occurred communicating with the service provider. + \value ParseError + The response from the service provider or an import file was in an unrecognizable format + \value PermissionsError + The operation failed because of insufficient permissions. + \value UnsupportedError + The operation was not supported by the service provider. + \value BadArgumentError. + A parameter that was provided was invalid. + \value CancelError + The operation was canceled. + \value UnknownError + An error occurred which does not fit into any of the other categories. +*/ + +/*! + \enum QPlaceReply::Type + + Describes the reply's type. + \value Reply + This is a generic reply. + \value DetailsReply + This is a reply for the retrieval of place details + \value SearchReply + This is a reply for the place search operation. + \value SearchSuggestionReply + This is a reply for a search suggestion operation. + \value ContentReply + This is a reply for content associated with a place. + \value IdReply + This is a reply that returns an identifier of a place or category. + Typically used for place or category save and remove operations. + \value MatchReply + This is a reply that returns places that match + those from another provider. +*/ + +/*! + Constructs a reply object with a given \a parent. +*/ +QPlaceReply::QPlaceReply(QObject *parent) + : QObject(parent),d_ptr(new QPlaceReplyPrivate) +{ +} + +/*! + \internal +*/ +QPlaceReply::QPlaceReply(QPlaceReplyPrivate *dd, QObject *parent) + : QObject(parent),d_ptr(dd) +{ +} + +/*! + Destroys the reply object. +*/ +QPlaceReply::~QPlaceReply() +{ + if (!isFinished()) { + abort(); + } + delete d_ptr; +} + +/*! + Return true if the reply has completed. +*/ +bool QPlaceReply::isFinished() const +{ + return d_ptr->isFinished; +} + +/*! + Returns the type of the reply. +*/ +QPlaceReply::Type QPlaceReply::type() const +{ + return QPlaceReply::Reply; +} + +/*! + Sets the status of whether the reply is \a finished + or not. This function does not cause the finished() signal + to be emitted. +*/ +void QPlaceReply::setFinished(bool finished) +{ + d_ptr->isFinished = finished; +} + +/*! + Sets the \a error and \a errorString of the reply. + This function does not cause the QPlaceReply::error(QPlaceReply::Error, const QString &errorString) + signal to be emitted. +*/ +void QPlaceReply::setError(QPlaceReply::Error error, const QString &errorString) +{ + d_ptr->error = error; + d_ptr->errorString = errorString; +} + +/*! + Returns the error string of the reply. The error string is intended to be + used by developers only and is not fit to be displayed to an end user. + + If no error has occurred, the string is empty. +*/ +QString QPlaceReply::errorString() const +{ + return d_ptr->errorString; +} + +/*! + Returns the error code. +*/ +QPlaceReply::Error QPlaceReply::error() const +{ + return d_ptr->error; +} + +/*! + Aborts the operation. +*/ +void QPlaceReply::abort() +{ +} + +/*! + \fn void QPlaceReply::finished() + + This signal is emitted when this reply has finished processing. + + If error() equals QPlaceReply::NoError then the processing + finished successfully. + + This signal and QPlaceManager::finished() will be + emitted at the same time. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ + +/*! + \fn void QPlaceReply::error(QPlaceReply::Error error, const QString &errorString) + + This signal is emitted when an error has been detected in the processing of + this reply. The finished() signal will probably follow. + + The error will be described by the error code \a error. If \a errorString is + not empty it will contain a textual description of the error meant for + developers and not end users. + + This signal and QPlaceManager::error() will be emitted at the same time. + + \note Do not delete this reply object in the slot connected to this + signal. Use deleteLater() instead. +*/ diff --git a/src/location/places/qplacereply.h b/src/location/places/qplacereply.h new file mode 100644 index 0000000..374c68b --- /dev/null +++ b/src/location/places/qplacereply.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEREPLY_H +#define QPLACEREPLY_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceReplyPrivate; +class Q_LOCATION_EXPORT QPlaceReply : public QObject +{ + Q_OBJECT +public: + enum Error { + NoError, + PlaceDoesNotExistError, + CategoryDoesNotExistError, + CommunicationError, + ParseError, + PermissionsError, + UnsupportedError, + BadArgumentError, + CancelError, + UnknownError + }; + + enum Type { + Reply, + DetailsReply, + SearchReply, + SearchSuggestionReply, + ContentReply, + IdReply, + MatchReply + }; + + explicit QPlaceReply(QObject *parent = Q_NULLPTR); + ~QPlaceReply(); + + bool isFinished() const; + + virtual Type type() const; + + QString errorString() const; + QPlaceReply::Error error() const; + +public Q_SLOTS: + virtual void abort(); + +Q_SIGNALS: + void finished(); + void error(QPlaceReply::Error error, const QString &errorString = QString()); + +protected: + explicit QPlaceReply(QPlaceReplyPrivate *, QObject *parent = Q_NULLPTR); + void setFinished(bool finished); + void setError(QPlaceReply::Error error, const QString &errorString); + QPlaceReplyPrivate *d_ptr; + +private: + Q_DISABLE_COPY(QPlaceReply) +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceReply::Error) +Q_DECLARE_METATYPE(QPlaceReply *) + +#endif // QPLACEREPLY_H diff --git a/src/location/places/qplacereply_p.h b/src/location/places/qplacereply_p.h new file mode 100644 index 0000000..9e6c096 --- /dev/null +++ b/src/location/places/qplacereply_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEREPLY_P_H +#define QPLACEREPLY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplacereply.h" + +QT_BEGIN_NAMESPACE + +class QPlaceReplyPrivate +{ +public: + QPlaceReplyPrivate() : + isFinished(false), + error(QPlaceReply::NoError), + errorString(QString()){} + virtual ~QPlaceReplyPrivate(){} + bool isFinished; + QPlaceReply::Error error; + QString errorString; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplaceresult.cpp b/src/location/places/qplaceresult.cpp new file mode 100644 index 0000000..fe89eff --- /dev/null +++ b/src/location/places/qplaceresult.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceresult.h" +#include "qplaceresult_p.h" +#include + +QT_USE_NAMESPACE + +QPlaceResultPrivate::QPlaceResultPrivate() + : QPlaceSearchResultPrivate(), distance(qQNaN()), sponsored(false) +{ +} + +QPlaceResultPrivate::QPlaceResultPrivate(const QPlaceResultPrivate &other) +: QPlaceSearchResultPrivate(other), distance(other.distance), place(other.place), + sponsored(other.sponsored) +{ +} + +QPlaceResultPrivate::~QPlaceResultPrivate() +{ +} + +bool QPlaceResultPrivate::compare(const QPlaceSearchResultPrivate *other) const +{ + const QPlaceResultPrivate *od = static_cast(other); + return QPlaceSearchResultPrivate::compare(other) + && ((qIsNaN(distance) && qIsNaN(od->distance)) + || qFuzzyCompare(distance, od->distance)) + && place == od->place + && sponsored == od->sponsored; +} + +/*! + \class QPlaceResult + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceResult class represents a search result containing a place. + + The PlaceResult holds the distance to the place from the center of the search request, + an instance of the place and an indication of whether the result is + sponsored or \l {http://en.wikipedia.org/wiki/Organic_search}{organic}. + + The intended usage is that a QPlaceSearchResult can be converted into a QPlaceResult + like so: + + \snippet places/requesthandler.h Convert search result + + The implementation is handled in such a way that object slicing is not an issue. + + \sa QPlaceSearchResult +*/ + +/*! + Constructs a new place result object. +*/ +QPlaceResult::QPlaceResult() +: QPlaceSearchResult(new QPlaceResultPrivate) +{ +} + +/*! + Destructor. +*/ +QPlaceResult::~QPlaceResult() +{ +} + +/*! + \fn QPlaceResult::QPlaceResult(const QPlaceSearchResult &other) + Constructs a copy of \a other if possible, otherwise constructs a default place result. +*/ +Q_IMPLEMENT_SEARCHRESULT_COPY_CTOR(QPlaceResult) + +Q_IMPLEMENT_SEARCHRESULT_D_FUNC(QPlaceResult) + +/*! + Returns the distance of the place to the search center. This + field is only relevant provided the search request contained + a search area with a search center. Otherwise, + the distance is NaN indicating an undefined distance. The default value + for distance is NaN. +*/ +qreal QPlaceResult::distance() const +{ + Q_D(const QPlaceResult); + return d->distance; +} + +/*! + Set the \a distance of the search result's place from a search center. +*/ +void QPlaceResult::setDistance(qreal distance) +{ + Q_D(QPlaceResult); + d->distance = distance; +} + +/*! + Returns the place of the search result. +*/ +QPlace QPlaceResult::place() const +{ + Q_D(const QPlaceResult); + return d->place; +} + +/*! + Sets the \a place that this result refers to. +*/ +void QPlaceResult::setPlace(const QPlace &place) +{ + Q_D(QPlaceResult); + d->place = place; +} + +/*! + Returns true if the result is a sponsored result. + + \sa setSponsored() +*/ +bool QPlaceResult::isSponsored() const +{ + Q_D(const QPlaceResult); + return d->sponsored; +} + +/*! + Sets whether the result is a \a sponsored result or not. + + \sa isSponsored() +*/ +void QPlaceResult::setSponsored(bool sponsored) +{ + Q_D(QPlaceResult); + d->sponsored = sponsored; +} diff --git a/src/location/places/qplaceresult.h b/src/location/places/qplaceresult.h new file mode 100644 index 0000000..9d11724 --- /dev/null +++ b/src/location/places/qplaceresult.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACERESULT_H +#define QPLACERESULT_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceResultPrivate; + +class Q_LOCATION_EXPORT QPlaceResult : public QPlaceSearchResult +{ +public: + QPlaceResult(); + +#ifdef Q_QDOC + QPlaceResult::QPlaceResult(const QPlaceSearchResult &other); +#else + Q_DECLARE_SEARCHRESULT_COPY_CTOR(QPlaceResult) +#endif + + virtual ~QPlaceResult(); + + qreal distance() const; + void setDistance(qreal distance); + + QPlace place() const; + void setPlace(const QPlace &place); + + bool isSponsored() const; + void setSponsored(bool sponsored); + +private: + Q_DECLARE_SEARCHRESULT_D_FUNC(QPlaceResult) +}; + +Q_DECLARE_TYPEINFO(QPlaceResult, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplaceresult_p.h b/src/location/places/qplaceresult_p.h new file mode 100644 index 0000000..0e0bf8c --- /dev/null +++ b/src/location/places/qplaceresult_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACERESULT_P_H +#define QPLACERESULT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplacesearchresult_p.h" + +QT_BEGIN_NAMESPACE + +class QPlaceResultPrivate : public QPlaceSearchResultPrivate +{ +public: + QPlaceResultPrivate(); + QPlaceResultPrivate(const QPlaceResultPrivate &other); + + ~QPlaceResultPrivate(); + + bool compare(const QPlaceSearchResultPrivate *other) const Q_DECL_OVERRIDE; + + Q_DEFINE_SEARCHRESULT_PRIVATE_HELPER(QPlaceResult, QPlaceSearchResult::PlaceResult) + + qreal distance; + QPlace place; + bool sponsored; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacereview.cpp b/src/location/places/qplacereview.cpp new file mode 100644 index 0000000..ca79b07 --- /dev/null +++ b/src/location/places/qplacereview.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacereview.h" +#include "qplacereview_p.h" + +QT_BEGIN_NAMESPACE + +QPlaceReviewPrivate::QPlaceReviewPrivate() +: QPlaceContentPrivate(), rating(0) +{ +} + +QPlaceReviewPrivate::QPlaceReviewPrivate(const QPlaceReviewPrivate &other) + : QPlaceContentPrivate(other) +{ + dateTime = other.dateTime; + text = other.text; + language = other.language; + rating = other.rating; + reviewId = other.reviewId; + title = other.title; +} + +QPlaceReviewPrivate::~QPlaceReviewPrivate() +{ +} + +bool QPlaceReviewPrivate::compare(const QPlaceContentPrivate *other) const +{ + const QPlaceReviewPrivate *od = static_cast(other); + return QPlaceContentPrivate::compare(other) && + dateTime == od->dateTime && + text == od->text && + language == od->language && + rating == od->rating && + reviewId == od->reviewId && + title == od->title; +} + +/*! + \class QPlaceReview + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceReview class represents a review of a place. + + Each QPlaceReview has a number of properties such as + a title, text, date of submission and rating; in addition to those properties + inherited from QPlaceContent. + + Note: The Places API only supports reviews as 'retrieve-only' objects. Submitting reviews + to a provider is not a supported use case. + + \sa QPlaceContent, QPlaceEditorial +*/ + +/*! + Constructs a new review object. +*/ +QPlaceReview::QPlaceReview() + : QPlaceContent(new QPlaceReviewPrivate) +{ +} + +/*! + \fn QPlaceReview::QPlaceReview(const QPlaceContent &other) + Constructs a copy of \a other, otherwise constructs a default review object. +*/ +Q_IMPLEMENT_CONTENT_COPY_CTOR(QPlaceReview) + + +/*! + Destroys the review. +*/ +QPlaceReview::~QPlaceReview() +{ +} + +Q_IMPLEMENT_CONTENT_D_FUNC(QPlaceReview) + +/*! + Returns the date and time that the review was submitted. +*/ +QDateTime QPlaceReview::dateTime() const +{ + Q_D(const QPlaceReview); + return d->dateTime; +} + +/*! + Sets the date and time that the review was submitted to \a dateTime. +*/ +void QPlaceReview::setDateTime(const QDateTime &dateTime) +{ + Q_D(QPlaceReview); + d->dateTime = dateTime; +} + +/*! + Returns a textual description of the place. + + Depending on the provider the text could be rich (HTML based) or plain text. +*/ +QString QPlaceReview::text() const +{ + Q_D(const QPlaceReview); + return d->text; +} + +/*! + Sets \a text of the review. +*/ +void QPlaceReview::setText(const QString &text) +{ + Q_D(QPlaceReview); + d->text = text; +} + +/*! + Returns the language of the review. Typically this would be a language code + in the 2 letter ISO 639-1 format. +*/ +QString QPlaceReview::language() const +{ + Q_D(const QPlaceReview); + return d->language; +} + +/*! + Sets the \a language of the review. Typically this would be a language code + in the 2 letter ISO 639-1 format. +*/ +void QPlaceReview::setLanguage(const QString &language) +{ + Q_D(QPlaceReview); + d->language = language; +} + +/*! + Returns this review's rating of the place. +*/ +qreal QPlaceReview::rating() const +{ + Q_D(const QPlaceReview); + return d->rating; +} + +/*! + Sets the review's \a rating of the place. +*/ +void QPlaceReview::setRating(qreal rating) +{ + Q_D(QPlaceReview); + d->rating = rating; +} + +/*! + Returns the review's identifier. +*/ +QString QPlaceReview::reviewId() const +{ + Q_D(const QPlaceReview); + return d->reviewId; +} + +/*! + Sets the \a identifier of the review. +*/ +void QPlaceReview::setReviewId(const QString &identifier) +{ + Q_D(QPlaceReview); + d->reviewId = identifier; +} + +/*! + Returns the title of the review. +*/ +QString QPlaceReview::title() const +{ + Q_D(const QPlaceReview); + return d->title; +} + +/*! + Sets the \a title of the review. +*/ +void QPlaceReview::setTitle(const QString &title) +{ + Q_D(QPlaceReview); + d->title = title; +} + +QT_END_NAMESPACE diff --git a/src/location/places/qplacereview.h b/src/location/places/qplacereview.h new file mode 100644 index 0000000..2c9791c --- /dev/null +++ b/src/location/places/qplacereview.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEREVIEW_H +#define QPLACEREVIEW_H + +#include + +QT_BEGIN_NAMESPACE + +class QDateTime; +class QPlaceReviewPrivate; + +class Q_LOCATION_EXPORT QPlaceReview : public QPlaceContent +{ +public: + QPlaceReview(); +#ifdef Q_QDOC + QPlaceReview(const QPlaceContent &other); +#else + Q_DECLARE_CONTENT_COPY_CTOR(QPlaceReview) +#endif + virtual ~QPlaceReview(); + + QDateTime dateTime() const; + void setDateTime(const QDateTime &dt); + QString text() const; + void setText(const QString &text); + QString language() const; + void setLanguage(const QString &data); + + qreal rating() const; + void setRating(qreal data); + QString reviewId() const; + void setReviewId(const QString &identifier); + QString title() const; + void setTitle(const QString &data); + +private: + Q_DECLARE_CONTENT_D_FUNC(QPlaceReview) +}; + +QT_END_NAMESPACE + +#endif // QPLACEREVIEW_H diff --git a/src/location/places/qplacereview_p.h b/src/location/places/qplacereview_p.h new file mode 100644 index 0000000..345aa19 --- /dev/null +++ b/src/location/places/qplacereview_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEREVIEW_P_H +#define QPLACEREVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include "qplacecontent_p.h" + +QT_BEGIN_NAMESPACE + +class QPlaceReviewPrivate : public QPlaceContentPrivate +{ +public: + QPlaceReviewPrivate(); + QPlaceReviewPrivate(const QPlaceReviewPrivate &other); + + ~QPlaceReviewPrivate(); + + bool compare(const QPlaceContentPrivate *other) const; + + Q_DEFINE_CONTENT_PRIVATE_HELPER(QPlaceReview, QPlaceContent::ReviewType); + + QDateTime dateTime; + QString text; + QString language; + qreal rating; + QString reviewId; + QString title; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacesearchreply.cpp b/src/location/places/qplacesearchreply.cpp new file mode 100644 index 0000000..06eef4e --- /dev/null +++ b/src/location/places/qplacesearchreply.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceSearchReplyPrivate : public QPlaceReplyPrivate +{ +public: + QPlaceSearchReplyPrivate(){} + QList results; + QPlaceSearchRequest searchRequest; + QPlaceSearchRequest previousPageRequest; + QPlaceSearchRequest nextPageRequest; +}; + +/*! + \class QPlaceSearchReply + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-replies + \since 5.6 + + \brief The QPlaceSearchReply class manages a place search operation started by an + instance of QPlaceManager. + + See \l {Discovery/Search} for an example on how to use a search reply. + \sa QPlaceSearchRequest, QPlaceManager +*/ + +/*! + Constructs a search reply with a given \a parent. +*/ +QPlaceSearchReply::QPlaceSearchReply(QObject *parent) + : QPlaceReply(new QPlaceSearchReplyPrivate, parent) +{ +} + +/*! + Destroys the search reply. +*/ +QPlaceSearchReply::~QPlaceSearchReply() +{ +} + +/*! + Returns the type of reply. +*/ +QPlaceReply::Type QPlaceSearchReply::type() const +{ + return QPlaceReply::SearchReply; +} + + /*! + Returns a list of search results; +*/ +QList QPlaceSearchReply::results() const +{ + Q_D(const QPlaceSearchReply); + return d->results; +} + +/*! + Sets the list of search \a results. +*/ +void QPlaceSearchReply::setResults(const QList &results) +{ + Q_D(QPlaceSearchReply); + d->results = results; +} + +/*! + Returns the search request that was used to generate this reply. +*/ +QPlaceSearchRequest QPlaceSearchReply::request() const +{ + Q_D(const QPlaceSearchReply); + return d->searchRequest; +} + +/*! + Returns a place search request which can be used to request the previous page of search + results. An empty place search request is returned if there is no previous page of results. + + \sa nextPageRequest(), setPreviousPageRequest() +*/ +QPlaceSearchRequest QPlaceSearchReply::previousPageRequest() const +{ + Q_D(const QPlaceSearchReply); + return d->previousPageRequest; +} + +/*! + Returns a place search request which can be used to request the next page of search results. An + empty place search request is returned if there is no next page of results. + + \sa previousPageRequest(), setNextPageRequest() +*/ +QPlaceSearchRequest QPlaceSearchReply::nextPageRequest() const +{ + Q_D(const QPlaceSearchReply); + return d->nextPageRequest; +} + +/*! + Sets the search \a request used to generate this reply. +*/ +void QPlaceSearchReply::setRequest(const QPlaceSearchRequest &request) +{ + Q_D(QPlaceSearchReply); + d->searchRequest = request; +} + +/*! + Sets the previous page of search results request to \a previous. + + \sa previousPageRequest() +*/ +void QPlaceSearchReply::setPreviousPageRequest(const QPlaceSearchRequest &previous) +{ + Q_D(QPlaceSearchReply); + d->previousPageRequest = previous; +} + +/*! + Sets the next page of search results request to \a next. + + \sa nextPageRequest() +*/ +void QPlaceSearchReply::setNextPageRequest(const QPlaceSearchRequest &next) +{ + Q_D(QPlaceSearchReply); + d->nextPageRequest = next; +} + +QT_END_NAMESPACE diff --git a/src/location/places/qplacesearchreply.h b/src/location/places/qplacesearchreply.h new file mode 100644 index 0000000..52c8889 --- /dev/null +++ b/src/location/places/qplacesearchreply.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESEARCHREPLY_H +#define QPLACESEARCHREPLY_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceSearchResult; +class QPlaceSearchReplyPrivate; + +class Q_LOCATION_EXPORT QPlaceSearchReply : public QPlaceReply +{ + Q_OBJECT +public: + explicit QPlaceSearchReply(QObject *parent = Q_NULLPTR); + ~QPlaceSearchReply(); + + QPlaceReply::Type type() const; + + QList results() const; + QPlaceSearchRequest request() const; + + QPlaceSearchRequest previousPageRequest() const; + QPlaceSearchRequest nextPageRequest() const; + +protected: + void setResults(const QList &results); + void setRequest(const QPlaceSearchRequest &request); + void setPreviousPageRequest(const QPlaceSearchRequest &previous); + void setNextPageRequest(const QPlaceSearchRequest &next); + +private: + Q_DISABLE_COPY(QPlaceSearchReply) + Q_DECLARE_PRIVATE(QPlaceSearchReply) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacesearchrequest.cpp b/src/location/places/qplacesearchrequest.cpp new file mode 100644 index 0000000..c2d993e --- /dev/null +++ b/src/location/places/qplacesearchrequest.cpp @@ -0,0 +1,440 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacesearchrequest.h" +#include "qgeocoordinate.h" +#include "qgeoshape.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceSearchRequestPrivate : public QSharedData +{ +public: + QPlaceSearchRequestPrivate(); + QPlaceSearchRequestPrivate(const QPlaceSearchRequestPrivate &other); + ~QPlaceSearchRequestPrivate(); + + QPlaceSearchRequestPrivate &operator=(const QPlaceSearchRequestPrivate &other); + bool operator==(const QPlaceSearchRequestPrivate &other) const; + + void clear(); + + QString searchTerm; + QList categories; + QGeoShape searchArea; + QString recommendationId; + QLocation::VisibilityScope visibilityScope; + QPlaceSearchRequest::RelevanceHint relevanceHint; + int limit; + QVariant searchContext; +}; + +QPlaceSearchRequestPrivate::QPlaceSearchRequestPrivate() +: QSharedData(), + visibilityScope(QLocation::UnspecifiedVisibility), + relevanceHint(QPlaceSearchRequest::UnspecifiedHint), + limit(-1) +{ +} + +QPlaceSearchRequestPrivate::QPlaceSearchRequestPrivate(const QPlaceSearchRequestPrivate &other) + : QSharedData(other), + searchTerm(other.searchTerm), + categories(other.categories), + searchArea(other.searchArea), + recommendationId(other.recommendationId), + visibilityScope(other.visibilityScope), + relevanceHint(other.relevanceHint), + limit(other.limit), + searchContext(other.searchContext) +{ +} + +QPlaceSearchRequestPrivate::~QPlaceSearchRequestPrivate() +{ +} + +QPlaceSearchRequestPrivate &QPlaceSearchRequestPrivate::operator=(const QPlaceSearchRequestPrivate &other) +{ + if (this != &other) { + searchTerm = other.searchTerm; + categories = other.categories; + searchArea = other.searchArea; + recommendationId = other.recommendationId; + visibilityScope = other.visibilityScope; + relevanceHint = other.relevanceHint; + limit = other.limit; + searchContext = other.searchContext; + } + + return *this; +} + +bool QPlaceSearchRequestPrivate::operator==(const QPlaceSearchRequestPrivate &other) const +{ + return searchTerm == other.searchTerm && + categories == other.categories && + searchArea == other.searchArea && + recommendationId == other.recommendationId && + visibilityScope == other.visibilityScope && + relevanceHint == other.relevanceHint && + limit == other.limit && + searchContext == other.searchContext; +} + +void QPlaceSearchRequestPrivate::clear() +{ + limit = -1; + searchTerm.clear(); + categories.clear(); + searchArea = QGeoShape(); + recommendationId.clear(); + visibilityScope = QLocation::UnspecifiedVisibility; + relevanceHint = QPlaceSearchRequest::UnspecifiedHint; + searchContext.clear(); +} + +/*! + \class QPlaceSearchRequest + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-requests + \since 5.6 + + \brief The QPlaceSearchRequest class represents the set of parameters for a search request. + + A typical search request may look like the following: + \snippet places/requesthandler.h Search request + + Note that specifying a search center can be done by setting a circular search area that has + a center but no radius. The default radius is set to -1, which indicates an undefined radius. The provider will + interpret this as being free to choose its own default radius. + + The QPlaceSearchRequest is primarily used with the QPlaceManager to + \l {QPlaceManager::search()} {search for places}, however it is also + used to provide parameters for \l {QPlaceManager::searchSuggestions()}{generating search term suggestions}. + Note that in this context only some of the parameters may be relevant. For example, the search area + is useful in narrowing down relevant search suggestions, while other parameters such as relevance hint + are not so applicable. + + Also be aware that providers may vary by which parameters they support for example some providers may not support + paging while others do, some providers may honor relevance hints while others may completely ignore them, + see the \l {Qt Location#Plugin References and Parameters}{plugin documentation} for more + details. +*/ + +/*! + \enum QPlaceSearchRequest::RelevanceHint + + Defines hints to help rank place results. + \value UnspecifiedHint + No explicit hint has been specified. + \value DistanceHint + Distance to a search center is relevant for the user. Closer places + are more highly weighted. This hint is only useful + if a circular search area is used in the query. + \value LexicalPlaceNameHint + Alphabetic ordering of places according to name is relevant to the user. +*/ + +/*! + Default constructor. Constructs an new request object. +*/ +QPlaceSearchRequest::QPlaceSearchRequest() + : d_ptr(new QPlaceSearchRequestPrivate()) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QPlaceSearchRequest::QPlaceSearchRequest(const QPlaceSearchRequest &other) + : d_ptr(other.d_ptr) +{ +} + +/*! + Destroys the request object. +*/ +QPlaceSearchRequest::~QPlaceSearchRequest() +{ +} + +/*! + Assigns \a other to this search request and returns a reference + to this search request. +*/ +QPlaceSearchRequest &QPlaceSearchRequest::operator= (const QPlaceSearchRequest & other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if \a other is equal to this search request, + otherwise returns false. +*/ +bool QPlaceSearchRequest::operator== (const QPlaceSearchRequest &other) const +{ + Q_D(const QPlaceSearchRequest); + return *d == *other.d_func(); +} + +/*! + Returns true if \a other is not equal to this search request, + otherwise returns false. +*/ +bool QPlaceSearchRequest::operator!= (const QPlaceSearchRequest &other) const +{ + Q_D(const QPlaceSearchRequest); + return !(*d == *other.d_func()); +} + +/*! + Returns the search term. +*/ +QString QPlaceSearchRequest::searchTerm() const +{ + Q_D(const QPlaceSearchRequest); + return d->searchTerm; +} + +/*! + Sets the search \a term. +*/ +void QPlaceSearchRequest::setSearchTerm(const QString &term) +{ + Q_D(QPlaceSearchRequest); + d->searchTerm = term; +} + +/*! + Return the categories to be used in the search request. + Places need only to belong to one of the categories + to be considered a match by the request. +*/ +QList QPlaceSearchRequest::categories() const +{ + Q_D(const QPlaceSearchRequest); + return d->categories; +} + +/*! + Sets the search request to search by a single \a category + + \sa setCategories() +*/ +void QPlaceSearchRequest::setCategory(const QPlaceCategory &category) +{ + Q_D(QPlaceSearchRequest); + d->categories.clear(); + + if (!category.categoryId().isEmpty()) + d->categories.append(category); +} + +/*! + Sets the search request to search from the list of given \a categories. + Any places returned during the search will match at least one of the \a + categories. + + \sa setCategory() +*/ +void QPlaceSearchRequest::setCategories(const QList &categories) +{ + Q_D(QPlaceSearchRequest); + d->categories = categories; +} + +/*! + Returns the search area which will be used to limit search results. The default search area is + an invalid QGeoShape, indicating that no specific search area is defined. +*/ +QGeoShape QPlaceSearchRequest::searchArea() const +{ + Q_D(const QPlaceSearchRequest); + return d->searchArea; +} + +/*! + Sets the search request to search within the given \a area. +*/ +void QPlaceSearchRequest::setSearchArea(const QGeoShape &area) +{ + Q_D(QPlaceSearchRequest); + d->searchArea = area; +} + +/*! + Returns the place id which will be used to search for recommendations + for similar places. +*/ +QString QPlaceSearchRequest::recommendationId() const +{ + Q_D(const QPlaceSearchRequest); + return d->recommendationId; +} + +/*! + Sets the \a placeId which will be used to search for recommendations. +*/ +void QPlaceSearchRequest::setRecommendationId(const QString &placeId) +{ + Q_D(QPlaceSearchRequest); + d->recommendationId = placeId; +} + +/*! + Returns backend specific additional search context associated with this place search request. + The search context is typically set as part of a + \l {QPlaceSearchResult::ProposedSearchResult}{proposed search results}. +*/ +QVariant QPlaceSearchRequest::searchContext() const +{ + Q_D(const QPlaceSearchRequest); + return d->searchContext; +} + +/*! + Sets the search context to \a context. + + \note This method is intended to be used by geo service plugins when returning search results + of type \l QPlaceSearchResult::ProposedSearchResult. + + The search context is used by backends to store additional search context related to the search + request. Other relevant fields should also be filled in. For example, if the search context + encodes a text search the search term should also be set with \l setSearchTerm(). The search + context allows additional search context to be kept which is not directly accessible via the + Qt Location API. + + The search context can be of any type storable in a QVariant. The value of the search context + is not intended to be use directly by applications. +*/ +void QPlaceSearchRequest::setSearchContext(const QVariant &context) +{ + Q_D(QPlaceSearchRequest); + d->searchContext = context; +} + +/*! + Returns the visibility scope used when searching for places. The default value is + QLocation::UnspecifiedVisibility meaning that no explicit scope has been assigned. + Places of any scope may be returned during the search. +*/ +QLocation::VisibilityScope QPlaceSearchRequest::visibilityScope() const +{ + Q_D(const QPlaceSearchRequest); + return d->visibilityScope; +} + +/*! + Sets the visibility \a scope used when searching for places. +*/ +void QPlaceSearchRequest::setVisibilityScope(QLocation::VisibilityScope scope) +{ + Q_D(QPlaceSearchRequest); + d->visibilityScope = scope; +} + +/*! + Returns the relevance hint of the request. The hint is given to the provider + to help but not dictate the ranking of results. For example providing a distance hint + may give closer places a higher ranking but it doesn't necessarily mean + that he results will be ordered strictly according to distance. +*/ +QPlaceSearchRequest::RelevanceHint QPlaceSearchRequest::relevanceHint() const +{ + Q_D(const QPlaceSearchRequest); + return d->relevanceHint; +} + +/*! + Sets the relevance \a hint to be used when searching for a place. +*/ +void QPlaceSearchRequest::setRelevanceHint(QPlaceSearchRequest::RelevanceHint hint) +{ + Q_D(QPlaceSearchRequest); + d->relevanceHint = hint; +} + +/*! + Returns the maximum number of search results to retrieve. + + A negative value for limit means that it is undefined. It is left up to the backend + provider to choose an appropriate number of results to return. The default limit is -1. +*/ +int QPlaceSearchRequest::limit() const +{ + Q_D(const QPlaceSearchRequest); + return d->limit; +} + +/*! + Set the maximum number of search results to retrieve to \a limit. +*/ +void QPlaceSearchRequest::setLimit(int limit) +{ + Q_D(QPlaceSearchRequest); + d->limit = limit; +} + +/*! + Clears the search request. +*/ +void QPlaceSearchRequest::clear() +{ + Q_D(QPlaceSearchRequest); + d->clear(); +} + +inline QPlaceSearchRequestPrivate *QPlaceSearchRequest::d_func() +{ + return static_cast(d_ptr.data()); +} + +inline const QPlaceSearchRequestPrivate *QPlaceSearchRequest::d_func() const +{ + return static_cast(d_ptr.constData()); +} + +QT_END_NAMESPACE diff --git a/src/location/places/qplacesearchrequest.h b/src/location/places/qplacesearchrequest.h new file mode 100644 index 0000000..0965450 --- /dev/null +++ b/src/location/places/qplacesearchrequest.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESEARCHREQUEST_H +#define QPLACESEARCHREQUEST_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoShape; +class QPlaceSearchRequestPrivate; + +class Q_LOCATION_EXPORT QPlaceSearchRequest +{ +public: + enum RelevanceHint { + UnspecifiedHint, + DistanceHint, + LexicalPlaceNameHint + }; + + QPlaceSearchRequest(); + QPlaceSearchRequest(const QPlaceSearchRequest &other); + + + QPlaceSearchRequest &operator=(const QPlaceSearchRequest &other); + + bool operator==(const QPlaceSearchRequest &other) const; + bool operator!=(const QPlaceSearchRequest &other) const; + + ~QPlaceSearchRequest(); + + QString searchTerm() const; + void setSearchTerm(const QString &term); + + QList categories() const; + void setCategory(const QPlaceCategory &category); + void setCategories(const QList &categories); + + QGeoShape searchArea() const; + void setSearchArea(const QGeoShape &area); + + QString recommendationId() const; + void setRecommendationId(const QString &recommendationId); + + QVariant searchContext() const; + void setSearchContext(const QVariant &context); + + QLocation::VisibilityScope visibilityScope() const; + void setVisibilityScope(QLocation::VisibilityScope visibilityScopes); + + RelevanceHint relevanceHint() const; + void setRelevanceHint(RelevanceHint hint); + + int limit() const; + void setLimit(int limit); + + void clear(); + +private: + QSharedDataPointer d_ptr; + inline QPlaceSearchRequestPrivate *d_func(); + inline const QPlaceSearchRequestPrivate *d_func() const; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceSearchRequest::RelevanceHint) + +#endif // QPLACESEARCHQUERY_H diff --git a/src/location/places/qplacesearchresult.cpp b/src/location/places/qplacesearchresult.cpp new file mode 100644 index 0000000..d8ddc50 --- /dev/null +++ b/src/location/places/qplacesearchresult.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacesearchresult.h" +#include "qplacesearchresult_p.h" +#include "qplaceresult.h" +#include + +QT_USE_NAMESPACE + +template<> QPlaceSearchResultPrivate *QSharedDataPointer::clone() +{ + return d->clone(); +} + +inline QPlaceSearchResultPrivate *QPlaceSearchResult::d_func() +{ + return static_cast(d_ptr.data()); +} + +inline const QPlaceSearchResultPrivate *QPlaceSearchResult::d_func() const +{ + return static_cast(d_ptr.constData()); +} + +bool QPlaceSearchResultPrivate::compare(const QPlaceSearchResultPrivate *other) const +{ + return title == other->title + && icon == other->icon; +} + +/*! + \class QPlaceSearchResult + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceSearchResult class is the base class for search results. + + A list of search results can be retrieved from the QPlaceSearchReply after it has + successfully completed the request. Common to all search results are the + \l {QPlaceSearchResult::title()} {title} and \l {QPlaceSearchResult::icon()}{icon}, + which can be used to present the search result to the user. + + The intended usage is that depending on the \l {QPlaceSearchResult::type()} {type}, + the search result can be converted to a more detailed subclass like so: + + \snippet places/requesthandler.h Convert search result + + The implementation is handled in such a way that object slicing is not an issue. + It is not expected that client applications or backend plugins instantiate + a QPlaceSearchResult directly, but rather client applications simply convert + to search result subclasses and backend plugins only instantiate subclasses. + + \sa QPlaceResult +*/ + +/*! + \enum QPlaceSearchResult::SearchResultType + + Defines the type of search result + + \value UnknownSearchResult The contents of the search result are unknown. + \value PlaceResult The search result contains a place. + \value ProposedSearchResult The search result contains a proposed search which may be relevant. +*/ + +/*! + Constructs a new search result. +*/ +QPlaceSearchResult::QPlaceSearchResult() + : d_ptr(new QPlaceSearchResultPrivate) +{ +} + +/*! + Constructs a copy of \a other +*/ +QPlaceSearchResult::QPlaceSearchResult(const QPlaceSearchResult &other) + :d_ptr(other.d_ptr) +{ +} + +/*! + Destroys the search result. +*/ +QPlaceSearchResult::~QPlaceSearchResult() +{ +} + +/*! + Assigns \a other to this search result and returns a reference to this + search result. +*/ +QPlaceSearchResult &QPlaceSearchResult::operator =(const QPlaceSearchResult &other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if \a other is equal to this search result, otherwise + returns false. +*/ +bool QPlaceSearchResult::operator==(const QPlaceSearchResult &other) const +{ + // An unknown object is only equal to another unknown search result + if (!d_ptr) + return !other.d_ptr; + + if (type() != other.type()) + return false; + + return d_ptr->compare(other.d_ptr); +} + +/*! + \fn bool QPlaceSearchResult::operator!=(const QPlaceSearchResult &other) const + Returns true if \a other not equal to this search result, otherwise + returns false. +*/ + +/*! + Returns the result type. +*/ +QPlaceSearchResult::SearchResultType QPlaceSearchResult::type() const +{ + if (!d_ptr) + return UnknownSearchResult; + return d_ptr->type(); +} + +/*! + Returns the title of the search result. This string can be used to display the search result + to the user. +*/ +QString QPlaceSearchResult::title() const +{ + Q_D(const QPlaceSearchResult); + return d->title; +} + +/*! + Sets the title of the search result to \a title. +*/ +void QPlaceSearchResult::setTitle(const QString &title) +{ + Q_D(QPlaceSearchResult); + d->title = title; +} + +/*! + Returns an icon that can be used to represent the search result. +*/ +QPlaceIcon QPlaceSearchResult::icon() const +{ + Q_D(const QPlaceSearchResult); + return d->icon; +} + +/*! + Sets the icon of the search result to \a icon. +*/ +void QPlaceSearchResult::setIcon(const QPlaceIcon &icon) +{ + Q_D(QPlaceSearchResult); + d->icon = icon; +} + +/*! + \internal + Constructs a new search result from the given pointer \a d. +*/ +QPlaceSearchResult::QPlaceSearchResult(QPlaceSearchResultPrivate *d) + :d_ptr(d) +{ +} diff --git a/src/location/places/qplacesearchresult.h b/src/location/places/qplacesearchresult.h new file mode 100644 index 0000000..436060d --- /dev/null +++ b/src/location/places/qplacesearchresult.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESEARCHRESULT_H +#define QPLACESEARCHRESULT_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#define Q_DECLARE_SEARCHRESULT_D_FUNC(Class) \ + inline Class##Private *d_func(); \ + inline const Class##Private *d_func() const;\ + friend class Class##Private; + +#define Q_DECLARE_SEARCHRESULT_COPY_CTOR(Class) \ + Class(const QPlaceSearchResult &other); + +class QPlaceSearchRequest; +class QPlaceSearchResultPrivate; +class QPlaceIcon; + +class Q_LOCATION_EXPORT QPlaceSearchResult +{ +public: + QPlaceSearchResult(); + QPlaceSearchResult(const QPlaceSearchResult &other); + + virtual ~QPlaceSearchResult(); + + QPlaceSearchResult &operator=(const QPlaceSearchResult &other); + + bool operator==(const QPlaceSearchResult &other) const; + bool operator!=(const QPlaceSearchResult &other) const { + return !(other == *this); + } + + enum SearchResultType { + UnknownSearchResult = 0, + PlaceResult, + ProposedSearchResult + }; + + SearchResultType type() const; + + QString title() const; + void setTitle(const QString &title); + + QPlaceIcon icon() const; + void setIcon(const QPlaceIcon &icon); + +protected: + explicit QPlaceSearchResult(QPlaceSearchResultPrivate *d); + QSharedDataPointer d_ptr; + +private: + inline QPlaceSearchResultPrivate *d_func(); + inline const QPlaceSearchResultPrivate *d_func() const; + + friend class QPlaceSearchResultPrivate; +}; + +Q_DECLARE_TYPEINFO(QPlaceSearchResult, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceSearchResult) +Q_DECLARE_METATYPE(QPlaceSearchResult::SearchResultType) + +#endif // QPLACESEARCHRESULT_H diff --git a/src/location/places/qplacesearchresult_p.h b/src/location/places/qplacesearchresult_p.h new file mode 100644 index 0000000..e7c1aaf --- /dev/null +++ b/src/location/places/qplacesearchresult_p.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESEARCHRESULT_P_H +#define QPLACESEARCHRESULT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplacesearchresult.h" +#include "qplacesearchrequest.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// defines must be in sync with class below +#define Q_IMPLEMENT_SEARCHRESULT_D_FUNC(Class) \ + Class##Private *Class::d_func() { return reinterpret_cast(d_ptr.data()); } \ + const Class##Private *Class::d_func() const { return reinterpret_cast(d_ptr.constData()); } \ + +#define Q_IMPLEMENT_SEARCHRESULT_COPY_CTOR(Class) \ + Class::Class(const QPlaceSearchResult &other) : QPlaceSearchResult() { Class##Private::copyIfPossible(d_ptr, other); } + +#define Q_DEFINE_SEARCHRESULT_PRIVATE_HELPER(Class, ResultType) \ + virtual QPlaceSearchResultPrivate *clone() const Q_DECL_OVERRIDE { return new Class##Private(*this); } \ + virtual QPlaceSearchResult::SearchResultType type() const Q_DECL_OVERRIDE {return ResultType;} \ + static void copyIfPossible(QSharedDataPointer &d_ptr, const QPlaceSearchResult &other) \ + { \ + if (other.type() == ResultType) \ + d_ptr = extract_d(other); \ + else \ + d_ptr = new Class##Private; \ + } + +class QPlaceSearchResultPrivate : public QSharedData +{ +public: + QPlaceSearchResultPrivate() {} + virtual ~QPlaceSearchResultPrivate() {} + + virtual bool compare(const QPlaceSearchResultPrivate *other) const; + + static const QSharedDataPointer + &extract_d(const QPlaceSearchResult &other) { return other.d_ptr; } + + virtual QPlaceSearchResultPrivate *clone() const { return new QPlaceSearchResultPrivate(*this); } + virtual QPlaceSearchResult::SearchResultType type() const { return QPlaceSearchResult::UnknownSearchResult; } + static void copyIfPossible(QSharedDataPointer &d_ptr, const QPlaceSearchResult &other) + { + if (other.type() == QPlaceSearchResult::UnknownSearchResult) + d_ptr = extract_d(other); + else + d_ptr = new QPlaceSearchResultPrivate; + } + + QString title; + QPlaceIcon icon; +}; + +template<> QPlaceSearchResultPrivate *QSharedDataPointer::clone(); + +QT_END_NAMESPACE + +#endif // QPLACESEARCHRESULT_P_H diff --git a/src/location/places/qplacesearchsuggestionreply.cpp b/src/location/places/qplacesearchsuggestionreply.cpp new file mode 100644 index 0000000..9bfc5f0 --- /dev/null +++ b/src/location/places/qplacesearchsuggestionreply.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacesearchsuggestionreply.h" +#include "qplacereply_p.h" + +QT_BEGIN_NAMESPACE + +class QPlaceSearchSuggestionReplyPrivate : public QPlaceReplyPrivate +{ +public: + QPlaceSearchSuggestionReplyPrivate(){} + QStringList suggestions; +}; + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +/*! + \class QPlaceSearchSuggestionReply + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-replies + \since 5.6 + + \brief The QPlaceSearchSuggestionReply class manages a search suggestion operation started by an + instance of QPlaceManager. + + On successful completion of the operation, the reply will contain a list of search term + suggestions. + See \l {Search Suggestions} for an example on how to use a search suggestion reply. + + \sa QPlaceManager +*/ + +/*! + Constructs a search suggestion reply with a given \a parent. +*/ +QPlaceSearchSuggestionReply::QPlaceSearchSuggestionReply(QObject *parent) + : QPlaceReply(new QPlaceSearchSuggestionReplyPrivate, parent) +{ +} + +/*! + Destroys the reply. +*/ +QPlaceSearchSuggestionReply::~QPlaceSearchSuggestionReply() +{ +} + +/*! + Returns the search term suggestions. +*/ +QStringList QPlaceSearchSuggestionReply::suggestions() const +{ + Q_D(const QPlaceSearchSuggestionReply); + return d->suggestions; +} + +/*! + Returns type of reply. +*/ +QPlaceReply::Type QPlaceSearchSuggestionReply::type() const +{ + return QPlaceReply::SearchSuggestionReply; +} + +/*! + Sets the search term \a suggestions. +*/ +void QPlaceSearchSuggestionReply::setSuggestions(const QStringList &suggestions) +{ + Q_D(QPlaceSearchSuggestionReply); + d->suggestions = suggestions; +} diff --git a/src/location/places/qplacesearchsuggestionreply.h b/src/location/places/qplacesearchsuggestionreply.h new file mode 100644 index 0000000..3909b14 --- /dev/null +++ b/src/location/places/qplacesearchsuggestionreply.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESEARCHSUGGESTIONREPLY_H +#define QPLACESEARCHSUGGESTIONREPLY_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceSearchSuggestionReplyPrivate; + +class Q_LOCATION_EXPORT QPlaceSearchSuggestionReply : public QPlaceReply +{ + Q_OBJECT +public: + explicit QPlaceSearchSuggestionReply(QObject *parent = Q_NULLPTR); + ~QPlaceSearchSuggestionReply(); + + QStringList suggestions() const; + Type type() const; + +protected: + void setSuggestions(const QStringList &suggestions); + +private: + Q_DISABLE_COPY(QPlaceSearchSuggestionReply) + Q_DECLARE_PRIVATE(QPlaceSearchSuggestionReply) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/qplacesupplier.cpp b/src/location/places/qplacesupplier.cpp new file mode 100644 index 0000000..aa9e122 --- /dev/null +++ b/src/location/places/qplacesupplier.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacesupplier.h" +#include "qplacesupplier_p.h" + +QT_USE_NAMESPACE + +QPlaceSupplierPrivate::QPlaceSupplierPrivate() : QSharedData() +{ +} + +QPlaceSupplierPrivate::QPlaceSupplierPrivate(const QPlaceSupplierPrivate &other) + : QSharedData() +{ + this->name = other.name; + this->supplierId = other.supplierId; + this->url = other.url; + this->icon = other.icon; +} + +QPlaceSupplierPrivate::~QPlaceSupplierPrivate() +{ +} + +bool QPlaceSupplierPrivate::operator==(const QPlaceSupplierPrivate &other) const +{ + return ( + this->name == other.name + && this->supplierId == other.supplierId + && this->url == other.url + && this->icon == other.icon + ); +} + +bool QPlaceSupplierPrivate::isEmpty() const +{ + return (name.isEmpty() + && supplierId.isEmpty() + && url.isEmpty() + && icon.isEmpty() + ); +} + +/*! + \class QPlaceSupplier + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceSupplier class represents a supplier of a place or content associated + with a place. + + Each instance represents a set of data about a supplier, which can include + supplier's name, url and icon. The supplier is typically a business or organization. + + Note: The Places API only supports suppliers as 'retrieve-only' objects. Submitting + suppliers to a provider is not a supported use case. +*/ + +/*! + Constructs a new supplier object. +*/ +QPlaceSupplier::QPlaceSupplier() + : d(new QPlaceSupplierPrivate) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QPlaceSupplier::QPlaceSupplier(const QPlaceSupplier &other) + :d(other.d) +{ +} + +/*! + Destroys the supplier object. +*/ +QPlaceSupplier::~QPlaceSupplier() +{ +} + +/*! + Assigns \a other to this supplier and returns a reference to this + supplier. +*/ +QPlaceSupplier &QPlaceSupplier::operator=(const QPlaceSupplier &other) +{ + if (this == &other) + return *this; + + d = other.d; + return *this; +} + +/*! + Returns true if this supplier is equal to \a other, + otherwise returns false. +*/ +bool QPlaceSupplier::operator==(const QPlaceSupplier &other) const +{ + return (*(d.constData()) == *(other.d.constData())); +} + +/*! + \fn QPlaceSupplier::operator!=(const QPlaceSupplier &other) const + + Returns true if this supplier is not equal to \a other, + otherwise returns false. +*/ + +/*! + Returns the name of the supplier which can be displayed to the user. + + The name can potentially be localized. The language is dependent on the + entity that sets it, typically this is the QPlaceManager. + The QPlaceManager::locales() field defines what language is used. +*/ +QString QPlaceSupplier::name() const +{ + return d->name; +} + +/*! + Sets the \a name of the supplier. +*/ +void QPlaceSupplier::setName(const QString &name) +{ + d->name = name; +} + +/*! + Returns the identifier of the supplier. The identifier is unique + to the manager backend which provided the supplier and is generally + not suitable for displaying to the user. +*/ +QString QPlaceSupplier::supplierId() const +{ + return d->supplierId; +} + +/*! + Sets the \a identifier of the supplier. +*/ +void QPlaceSupplier::setSupplierId(const QString &identifier) +{ + d->supplierId = identifier; +} + +/*! + Returns the URL of the supplier's website. +*/ +QUrl QPlaceSupplier::url() const +{ + return d->url; +} + +/*! + Sets the \a url of the supplier's website. +*/ +void QPlaceSupplier::setUrl(const QUrl &url) +{ + d->url = url; +} + +/*! + Returns the icon of the supplier. +*/ +QPlaceIcon QPlaceSupplier::icon() const +{ + return d->icon; +} + +/*! + Sets the \a icon of the supplier. +*/ +void QPlaceSupplier::setIcon(const QPlaceIcon &icon) +{ + d->icon = icon; +} + +/*! + Returns true if all fields of the place supplier are 0; otherwise returns false. +*/ +bool QPlaceSupplier::isEmpty() const +{ + return d->isEmpty(); +} diff --git a/src/location/places/qplacesupplier.h b/src/location/places/qplacesupplier.h new file mode 100644 index 0000000..21fcf57 --- /dev/null +++ b/src/location/places/qplacesupplier.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESUPPLIER_H +#define QPLACESUPPLIER_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QUrl; +class QPlaceSupplierPrivate; + +class Q_LOCATION_EXPORT QPlaceSupplier +{ +public: + QPlaceSupplier(); + QPlaceSupplier(const QPlaceSupplier &other); + ~QPlaceSupplier(); + + QPlaceSupplier &operator=(const QPlaceSupplier &other); + + bool operator==(const QPlaceSupplier &other) const; + bool operator!=(const QPlaceSupplier &other) const { + return !(other == *this); + } + + QString name() const; + void setName(const QString &data); + + QString supplierId() const; + void setSupplierId(const QString &identifier); + + QUrl url() const; + void setUrl(const QUrl &data); + + QPlaceIcon icon() const; + void setIcon(const QPlaceIcon &icon); + + bool isEmpty() const; + +private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceSupplier) + +#endif // QPLACESUPPLIER_H diff --git a/src/location/places/qplacesupplier_p.h b/src/location/places/qplacesupplier_p.h new file mode 100644 index 0000000..ab09349 --- /dev/null +++ b/src/location/places/qplacesupplier_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESUPPLIER_P_H +#define QPLACESUPPLIER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include "qplaceicon.h" + +QT_BEGIN_NAMESPACE + +class QPlaceSupplierPrivate : public QSharedData +{ +public: + QPlaceSupplierPrivate(); + QPlaceSupplierPrivate(const QPlaceSupplierPrivate &other); + + ~QPlaceSupplierPrivate(); + + bool operator==(const QPlaceSupplierPrivate &other) const; + + bool isEmpty() const; + + QString name; + QString supplierId; + QUrl url; + QPlaceIcon icon; +}; + +QT_END_NAMESPACE + +#endif // QPLACESUPPLIER_P_H diff --git a/src/location/places/qplaceuser.cpp b/src/location/places/qplaceuser.cpp new file mode 100644 index 0000000..fbfba62 --- /dev/null +++ b/src/location/places/qplaceuser.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceuser.h" +#include "qplaceuser_p.h" + +QT_USE_NAMESPACE + +QPlaceUserPrivate::QPlaceUserPrivate() + : QSharedData() +{ +} + +QPlaceUserPrivate::QPlaceUserPrivate(const QPlaceUserPrivate &other) + : QSharedData(), userId(other.userId), name(other.name) +{ +} + +QPlaceUserPrivate::~QPlaceUserPrivate() +{ +} + +bool QPlaceUserPrivate::operator==(const QPlaceUserPrivate &other) const +{ + return userId == other.userId && name == other.name; +} + +/*! + \class QPlaceUser + \inmodule QtLocation + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.6 + + \brief The QPlaceUser class represents an individual user. +*/ + +/*! + Constructs a new user object. +*/ +QPlaceUser::QPlaceUser() + : d(new QPlaceUserPrivate) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QPlaceUser::QPlaceUser(const QPlaceUser &other) + :d(other.d) +{ +} + +/*! + Destroys the user object. +*/ +QPlaceUser::~QPlaceUser() +{ +} + +/*! + Assigns \a other to this user and returns a reference to this user. +*/ +QPlaceUser &QPlaceUser::operator=(const QPlaceUser &other) +{ + if (this == &other) + return *this; + + d = other.d; + return *this; +} + +/*! + \fn bool QPlaceUser::operator!=(const QPlaceUser &other) const + + Returns true if \a other is not equal to this user, + otherwise returns false. +*/ + +/*! + Returns true if this user is equal to \a other. + Otherwise returns false. +*/ +bool QPlaceUser::operator==(const QPlaceUser &other) const +{ + return (*d) == *(other.d); +} + +/*! + Returns the identifier of the user. +*/ +QString QPlaceUser::userId() const +{ + return d->userId; +} + +/*! + Sets the \a identifier of the user. +*/ +void QPlaceUser::setUserId(const QString &identifier) +{ + d->userId = identifier; +} + +/*! + Returns the name of the user. +*/ +QString QPlaceUser::name() const +{ + return d->name; +} + +/*! + Sets the \a name of the user. +*/ + +void QPlaceUser::setName(const QString &name) +{ + d->name = name; +} diff --git a/src/location/places/qplaceuser.h b/src/location/places/qplaceuser.h new file mode 100644 index 0000000..1709783 --- /dev/null +++ b/src/location/places/qplaceuser.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEUSER_H +#define QPLACEUSER_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceUserPrivate; + +class Q_LOCATION_EXPORT QPlaceUser +{ +public: + QPlaceUser(); + QPlaceUser(const QPlaceUser &other); + ~QPlaceUser(); + + QPlaceUser &operator=(const QPlaceUser &other); + + bool operator==(const QPlaceUser &other) const; + bool operator!=(const QPlaceUser &other) const { + return !(other == *this); + } + + QString userId() const; + void setUserId(const QString &identifier); + + QString name() const; + void setName(const QString &name); + +private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPlaceUser) + +#endif diff --git a/src/location/places/qplaceuser_p.h b/src/location/places/qplaceuser_p.h new file mode 100644 index 0000000..f49110b --- /dev/null +++ b/src/location/places/qplaceuser_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEUSER_P_H +#define QPLACEUSER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceUserPrivate : public QSharedData +{ +public: + QPlaceUserPrivate(); + QPlaceUserPrivate(const QPlaceUserPrivate &other); + + ~QPlaceUserPrivate(); + + bool operator==(const QPlaceUserPrivate &other) const; + + QString userId; + QString name; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/location/places/unsupportedreplies_p.h b/src/location/places/unsupportedreplies_p.h new file mode 100644 index 0000000..b23a3b3 --- /dev/null +++ b/src/location/places/unsupportedreplies_p.h @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef UNSUPPORTEDREPLIES_P_H +#define UNSUPPORTEDREPLIES_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplacedetailsreply.h" +#include "qplacecontentreply.h" +#include "qplacesearchreply.h" +#include "qplacesearchsuggestionreply.h" +#include "qplaceidreply.h" + +#include "qplacematchreply.h" +#include "qplacemanagerengine.h" + +class Q_LOCATION_EXPORT QPlaceDetailsReplyUnsupported : public QPlaceDetailsReply +{ + Q_OBJECT + +public: + QPlaceDetailsReplyUnsupported(QPlaceManagerEngine *parent) + : QPlaceDetailsReply(parent) + { + setError(QPlaceReply::UnsupportedError, + QStringLiteral("Getting place details is not supported.")); + setFinished(true); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(parent, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this), + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + QMetaObject::invokeMethod(parent, "finished", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this)); + } +}; + +class Q_LOCATION_EXPORT QPlaceContentReplyUnsupported : public QPlaceContentReply +{ + Q_OBJECT + +public: + QPlaceContentReplyUnsupported(QPlaceManagerEngine *parent) + : QPlaceContentReply(parent) + { + setError(QPlaceReply::UnsupportedError, + QStringLiteral("Place content is not supported.")); + setFinished(true); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(parent, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this), + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + QMetaObject::invokeMethod(parent, "finished", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this)); + } +}; + +class Q_LOCATION_EXPORT QPlaceSearchReplyUnsupported : public QPlaceSearchReply +{ + Q_OBJECT + +public: + QPlaceSearchReplyUnsupported(QPlaceReply::Error errorCode, const QString &message, + QPlaceManagerEngine *parent) + : QPlaceSearchReply(parent) + { + setError(errorCode, message); + setFinished(true); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(parent, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this), + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + QMetaObject::invokeMethod(parent, "finished", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this)); + } +}; + +class Q_LOCATION_EXPORT QPlaceSearchSuggestionReplyUnsupported : public QPlaceSearchSuggestionReply +{ + Q_OBJECT + +public: + QPlaceSearchSuggestionReplyUnsupported(QPlaceManagerEngine *parent) + : QPlaceSearchSuggestionReply(parent) + { + setError(QPlaceReply::UnsupportedError, + QStringLiteral("Place search suggestions are not supported.")); + setFinished(true); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(parent, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this), + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + QMetaObject::invokeMethod(parent, "finished", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this)); + } +}; + +class Q_LOCATION_EXPORT QPlaceIdReplyUnsupported : public QPlaceIdReply +{ + Q_OBJECT + +public: + QPlaceIdReplyUnsupported(const QString &message, QPlaceIdReply::OperationType type, + QPlaceManagerEngine *parent) + : QPlaceIdReply(type, parent) + { + setError(QPlaceReply::UnsupportedError, message); + setFinished(true); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(parent, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this), + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + QMetaObject::invokeMethod(parent, "finished", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this)); + } +}; + +class Q_LOCATION_EXPORT QPlaceReplyUnsupported : public QPlaceReply +{ + Q_OBJECT + +public: + QPlaceReplyUnsupported(const QString &message, QPlaceManagerEngine *parent) + : QPlaceReply(parent) + { + setError(QPlaceReply::UnsupportedError, message); + setFinished(true); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(parent, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this), + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + QMetaObject::invokeMethod(parent, "finished", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this)); + } +}; + +class Q_LOCATION_EXPORT QPlaceMatchReplyUnsupported : public QPlaceMatchReply +{ + Q_OBJECT + +public: + QPlaceMatchReplyUnsupported(QPlaceManagerEngine *parent) + : QPlaceMatchReply(parent) + { + setError(QPlaceReply::UnsupportedError, + QStringLiteral("Place matching is not supported.")); + setFinished(true); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(parent, "error", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this), + Q_ARG(QPlaceReply::Error, error()), + Q_ARG(QString, errorString())); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + QMetaObject::invokeMethod(parent, "finished", Qt::QueuedConnection, + Q_ARG(QPlaceReply *, this)); + } +}; + +#endif diff --git a/src/location/qlocation.cpp b/src/location/qlocation.cpp new file mode 100644 index 0000000..2afed10 --- /dev/null +++ b/src/location/qlocation.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +QT_BEGIN_NAMESPACE + +namespace QLocation { + +/*! + \namespace QLocation + \inmodule QtLocation + \keyword QLocation Namespace + + \brief The QLocation namespace contains miscellaneous identifiers used throughout the + QtLocation module. +*/ + +/*! + \enum QLocation::Visibility + + Defines the visibility of a QPlace or QPlaceCategory. + + \value UnspecifiedVisibility No explicit visibility has been defined. + \value DeviceVisibility Places and categories with DeviceVisibility are only stored on + the local device. + \value PrivateVisibility Places and categories with PrivateVisibility are only visible + to the current user. The data may be stored either locally or + on a remote service or both. + \value PublicVisibility Places and categories with PublicVisibility are visible to + everyone. + + A particular manager may support one or more visibility scopes. For example a manager from one provider may only provide places + that are public to everyone, whilst another may provide both public and private places. + + \note The meaning of unspecified visibility depends on the context it is used. + + When \e saving a place or category, the + default visibility is unspecified meaning that the manager chooses an appropriate visibility scope for the item. + + When \e searching for places, unspecified means that places of any scope is returned. +*/ +} + +QT_END_NAMESPACE diff --git a/src/location/qlocation.h b/src/location/qlocation.h new file mode 100644 index 0000000..d30a3a3 --- /dev/null +++ b/src/location/qlocation.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOCATION_H +#define QLOCATION_H + +#if 0 +#pragma qt_class(QLocation) +#endif + +#include + +QT_BEGIN_NAMESPACE + +namespace QLocation { + +enum Visibility { + UnspecifiedVisibility = 0x00, + DeviceVisibility = 0x01, + PrivateVisibility = 0x02, + PublicVisibility = 0x04 +}; + +Q_DECLARE_FLAGS(VisibilityScope, Visibility) + +} + +Q_DECLARE_OPERATORS_FOR_FLAGS(QLocation::VisibilityScope) + +QT_END_NAMESPACE + +#endif // QLOCATION_H diff --git a/src/location/qlocationglobal.h b/src/location/qlocationglobal.h new file mode 100644 index 0000000..7992c09 --- /dev/null +++ b/src/location/qlocationglobal.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QLOCATIONGLOBAL_H +#define QLOCATIONGLOBAL_H + +#include + +QT_BEGIN_NAMESPACE + +#ifndef QT_STATIC +# if defined(QT_BUILD_LOCATION_LIB) +# define Q_LOCATION_EXPORT Q_DECL_EXPORT +# else +# define Q_LOCATION_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_LOCATION_EXPORT +#endif + +QT_END_NAMESPACE + +#endif // QLOCATIONGLOBAL_H + diff --git a/src/plugins/geoservices/geoservices.pro b/src/plugins/geoservices/geoservices.pro new file mode 100644 index 0000000..3d0971f --- /dev/null +++ b/src/plugins/geoservices/geoservices.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS = nokia osm mapbox diff --git a/src/plugins/geoservices/mapbox/mapbox.pro b/src/plugins/geoservices/mapbox/mapbox.pro new file mode 100644 index 0000000..d4797e3 --- /dev/null +++ b/src/plugins/geoservices/mapbox/mapbox.pro @@ -0,0 +1,22 @@ +TARGET = qtgeoservices_mapbox + +QT += location-private positioning-private network + +HEADERS += \ + qgeoserviceproviderpluginmapbox.h \ + qgeotiledmappingmanagerenginemapbox.h \ + qgeotilefetchermapbox.h \ + qgeomapreplymapbox.h + +SOURCES += \ + qgeoserviceproviderpluginmapbox.cpp \ + qgeotiledmappingmanagerenginemapbox.cpp \ + qgeotilefetchermapbox.cpp \ + qgeomapreplymapbox.cpp + +OTHER_FILES += \ + mapbox_plugin.json + +PLUGIN_TYPE = geoservices +PLUGIN_CLASS_NAME = QGeoServiceProviderFactoryMapbox +load(qt_plugin) diff --git a/src/plugins/geoservices/mapbox/mapbox_plugin.json b/src/plugins/geoservices/mapbox/mapbox_plugin.json new file mode 100644 index 0000000..0b8d08a --- /dev/null +++ b/src/plugins/geoservices/mapbox/mapbox_plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["mapbox"], + "Provider": "mapbox", + "Version": 100, + "Experimental": false, + "Features": [ + "OnlineMappingFeature" + ] +} diff --git a/src/plugins/geoservices/mapbox/qgeomapreplymapbox.cpp b/src/plugins/geoservices/mapbox/qgeomapreplymapbox.cpp new file mode 100644 index 0000000..5fe9caa --- /dev/null +++ b/src/plugins/geoservices/mapbox/qgeomapreplymapbox.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Canonical Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomapreplymapbox.h" + +#include + +QGeoMapReplyMapbox::QGeoMapReplyMapbox(QNetworkReply *reply, const QGeoTileSpec &spec, const QString &format, QObject *parent) +: QGeoTiledMapReply(spec, parent), m_reply(reply), m_format (format) +{ + connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkReplyError(QNetworkReply::NetworkError))); +} + +QGeoMapReplyMapbox::~QGeoMapReplyMapbox() +{ + if (m_reply) { + m_reply->deleteLater(); + m_reply = 0; + } +} + +void QGeoMapReplyMapbox::abort() +{ + if (!m_reply) + return; + + m_reply->abort(); +} + +QNetworkReply *QGeoMapReplyMapbox::networkReply() const +{ + return m_reply; +} + +void QGeoMapReplyMapbox::networkReplyFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() != QNetworkReply::NoError) + return; + + setMapImageData(m_reply->readAll()); + setMapImageFormat(m_format); + setFinished(true); + + m_reply->deleteLater(); + m_reply = 0; +} + +void QGeoMapReplyMapbox::networkReplyError(QNetworkReply::NetworkError error) +{ + if (!m_reply) + return; + + if (error != QNetworkReply::OperationCanceledError) + setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); + + setFinished(true); + m_reply->deleteLater(); + m_reply = 0; +} diff --git a/src/plugins/geoservices/mapbox/qgeomapreplymapbox.h b/src/plugins/geoservices/mapbox/qgeomapreplymapbox.h new file mode 100644 index 0000000..67ad61a --- /dev/null +++ b/src/plugins/geoservices/mapbox/qgeomapreplymapbox.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Canonical Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPREPLYMAPBOX_H +#define QGEOMAPREPLYMAPBOX_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMapReplyMapbox : public QGeoTiledMapReply +{ + Q_OBJECT + +public: + explicit QGeoMapReplyMapbox(QNetworkReply *reply, const QGeoTileSpec &spec, const QString &format, QObject *parent = 0); + ~QGeoMapReplyMapbox(); + + void abort(); + + QNetworkReply *networkReply() const; + +private Q_SLOTS: + void networkReplyFinished(); + void networkReplyError(QNetworkReply::NetworkError error); + +private: + QPointer m_reply; + QString m_format; +}; + +QT_END_NAMESPACE + +#endif // QGEOMAPREPLYMAPBOX_H diff --git a/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.cpp b/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.cpp new file mode 100644 index 0000000..ec40716 --- /dev/null +++ b/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Canonical Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoserviceproviderpluginmapbox.h" +#include "qgeotiledmappingmanagerenginemapbox.h" + +#include + +QT_BEGIN_NAMESPACE + +QGeoCodingManagerEngine *QGeoServiceProviderFactoryMapbox::createGeocodingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + Q_UNUSED(parameters) + Q_UNUSED(error) + Q_UNUSED(errorString) + + return 0; +} + +QGeoMappingManagerEngine *QGeoServiceProviderFactoryMapbox::createMappingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + const QString mapId = parameters.value(QStringLiteral("mapbox.map_id")).toString(); + const QString accessToken = parameters.value(QStringLiteral("mapbox.access_token")).toString(); + + if (!mapId.isEmpty() && !accessToken.isEmpty()) { + return new QGeoTiledMappingManagerEngineMapbox(parameters, error, errorString); + } else { + *error = QGeoServiceProvider::MissingRequiredParameterError; + *errorString = tr("Mapbox plugin requires 'mapbox.map_id' and 'mapbox.access_token' parameters.\n" + "Please visit https://www.mapbox.com"); + return 0; + } +} + +QGeoRoutingManagerEngine *QGeoServiceProviderFactoryMapbox::createRoutingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + Q_UNUSED(parameters) + Q_UNUSED(error) + Q_UNUSED(errorString) + + return 0; +} + +QPlaceManagerEngine *QGeoServiceProviderFactoryMapbox::createPlaceManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + Q_UNUSED(parameters) + Q_UNUSED(error) + Q_UNUSED(errorString) + + return 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.h b/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.h new file mode 100644 index 0000000..30b4c6e --- /dev/null +++ b/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Canonical Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDER_MAPBOX_H +#define QGEOSERVICEPROVIDER_MAPBOX_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoServiceProviderFactoryMapbox: public QObject, public QGeoServiceProviderFactory +{ + Q_OBJECT + Q_INTERFACES(QGeoServiceProviderFactory) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0" + FILE "mapbox_plugin.json") + +public: + QGeoCodingManagerEngine *createGeocodingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + QGeoMappingManagerEngine *createMappingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + QGeoRoutingManagerEngine *createRoutingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp new file mode 100644 index 0000000..4be5ac2 --- /dev/null +++ b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Canonical Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotiledmappingmanagerenginemapbox.h" +#include "qgeotilefetchermapbox.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoTiledMappingManagerEngineMapbox::QGeoTiledMappingManagerEngineMapbox(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) +: QGeoTiledMappingManagerEngine() +{ + QGeoCameraCapabilities cameraCaps; + cameraCaps.setMinimumZoomLevel(0.0); + cameraCaps.setMaximumZoomLevel(19.0); + setCameraCapabilities(cameraCaps); + + setTileSize(QSize(256, 256)); + + QList mapTypes; + mapTypes << QGeoMapType(QGeoMapType::CustomMap, tr("Custom"), tr("Mapbox custom map"), false, false, 0); + setSupportedMapTypes(mapTypes); + + QGeoTileFetcherMapbox *tileFetcher = new QGeoTileFetcherMapbox(this); + if (parameters.contains(QStringLiteral("useragent"))) { + const QByteArray ua = parameters.value(QStringLiteral("useragent")).toString().toLatin1(); + tileFetcher->setUserAgent(ua); + } + if (parameters.contains(QStringLiteral("mapbox.map_id"))) { + const QString id = parameters.value(QStringLiteral("mapbox.map_id")).toString(); + tileFetcher->setMapId(id); + } + if (parameters.contains(QStringLiteral("mapbox.format"))) { + const QString format = parameters.value(QStringLiteral("mapbox.format")).toString(); + tileFetcher->setFormat(format); + } + if (parameters.contains(QStringLiteral("mapbox.access_token"))) { + const QString token = parameters.value(QStringLiteral("mapbox.access_token")).toString(); + tileFetcher->setAccessToken(token); + } + + setTileFetcher(tileFetcher); + + *error = QGeoServiceProvider::NoError; + errorString->clear(); +} + +QGeoTiledMappingManagerEngineMapbox::~QGeoTiledMappingManagerEngineMapbox() +{ +} + +QGeoMap *QGeoTiledMappingManagerEngineMapbox::createMap() +{ + return new QGeoTiledMap(this, 0); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.h b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.h new file mode 100644 index 0000000..379ca6b --- /dev/null +++ b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Canonical Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEDMAPPINGMANAGERENGINEMAPBOX_H +#define QGEOTILEDMAPPINGMANAGERENGINEMAPBOX_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoTiledMappingManagerEngineMapbox : public QGeoTiledMappingManagerEngine +{ + Q_OBJECT + +public: + QGeoTiledMappingManagerEngineMapbox(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString); + ~QGeoTiledMappingManagerEngineMapbox(); + + QGeoMap *createMap(); +}; + +QT_END_NAMESPACE + +#endif // QGEOTILEDMAPPINGMANAGERENGINEMAPBOX_H diff --git a/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.cpp b/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.cpp new file mode 100644 index 0000000..69a832d --- /dev/null +++ b/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Canonical Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotilefetchermapbox.h" +#include "qgeomapreplymapbox.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoTileFetcherMapbox::QGeoTileFetcherMapbox(QObject *parent) +: QGeoTileFetcher(parent), m_networkManager(new QNetworkAccessManager(this)), + m_userAgent("Qt Location based application"), + m_mapId(""), + m_format("png"), + m_replyFormat("png"), + m_accessToken("") +{ +} + +void QGeoTileFetcherMapbox::setUserAgent(const QByteArray &userAgent) +{ + m_userAgent = userAgent; +} + +void QGeoTileFetcherMapbox::setMapId(const QString &mapId) +{ + m_mapId = mapId; +} + +void QGeoTileFetcherMapbox::setFormat(const QString &format) +{ + m_format = format; + + if (m_format == "png" || m_format == "png32" || m_format == "png64" || m_format == "png128" || m_format == "png256") + m_replyFormat = "png"; + else if (m_format == "jpg70" || m_format == "jpg80" || m_format == "jpg90") + m_replyFormat = "jpg"; + else + qWarning() << "Unknown map format " << m_format; +} + +void QGeoTileFetcherMapbox::setAccessToken(const QString &accessToken) +{ + m_accessToken = accessToken; +} + +QGeoTiledMapReply *QGeoTileFetcherMapbox::getTileImage(const QGeoTileSpec &spec) +{ + QNetworkRequest request; + request.setRawHeader("User-Agent", m_userAgent); + + request.setUrl(QUrl(QStringLiteral("http://api.tiles.mapbox.com/v4/") + + m_mapId + QLatin1Char('/') + + QString::number(spec.zoom()) + QLatin1Char('/') + + QString::number(spec.x()) + QLatin1Char('/') + + QString::number(spec.y()) + QLatin1Char('.') + + m_format + QLatin1Char('?') + + QStringLiteral("access_token=") + m_accessToken)); + + QNetworkReply *reply = m_networkManager->get(request); + + return new QGeoMapReplyMapbox(reply, spec, m_replyFormat); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.h b/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.h new file mode 100644 index 0000000..ddec289 --- /dev/null +++ b/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Canonical Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEFETCHERMAPBOX_H +#define QGEOTILEFETCHERMAPBOX_H + +#include + +QT_BEGIN_NAMESPACE + +class QGeoTiledMappingManagerEngine; +class QNetworkAccessManager; + +class QGeoTileFetcherMapbox : public QGeoTileFetcher +{ + Q_OBJECT + +public: + QGeoTileFetcherMapbox(QObject *parent = 0); + + void setUserAgent(const QByteArray &userAgent); + void setMapId(const QString &mapId); + void setFormat(const QString &format); + void setAccessToken(const QString &accessToken); + +private: + QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec); + + QNetworkAccessManager *m_networkManager; + QByteArray m_userAgent; + QString m_mapId; + QString m_format; + QString m_replyFormat; + QString m_accessToken; +}; + +QT_END_NAMESPACE + +#endif // QGEOTILEFETCHERMAPBOX_H diff --git a/src/plugins/geoservices/nokia/logo.png b/src/plugins/geoservices/nokia/logo.png new file mode 100644 index 0000000..ba42191 Binary files /dev/null and b/src/plugins/geoservices/nokia/logo.png differ diff --git a/src/plugins/geoservices/nokia/marclanguagecodes.h b/src/plugins/geoservices/nokia/marclanguagecodes.h new file mode 100644 index 0000000..69e309f --- /dev/null +++ b/src/plugins/geoservices/nokia/marclanguagecodes.h @@ -0,0 +1,312 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MARCLANGUAGECODES_H_ +#define MARCLANGUAGECODES_H_ + +// MARC language codes for GeoCoding service language/locale support +// http://www.loc.gov/marc/languages/language_code.html +// Order matches QLocale::Language + +QT_BEGIN_NAMESPACE + +static const unsigned char marc_language_code_list[] = + "\0\0\0" // Unused + "\0\0\0" // C + "abk" // Abkhazian + "\0\0\0" // Oromo + "aar" // Afar + "afr" // Afrikaans + "alb" // Albanian + "amh" // Amharic + "ara" // Arabic + "arm" // Armenian + "asm" // Assamese + "aym" // Aymara + "aze" // Azerbaijani + "bak" // Bashkir + "baq" // Basque + "ben" // Bengali + "\0\0\0" // Dzongkha + "bih" // Bihari + "bis" // Bislama + "bre" // Breton + "bul" // Bulgarian + "bur" // Burmese + "bel" // Belarusian + "khm" // Khmer + "cat" // Catalan + "chi" // Chinese + "cos" // Corsican + "hrv" // Croatian + "cze" // Czech + "dan" // Danish + "dut" // Dutch + "eng" // English + "epo" // Esperanto + "est" // Estonian + "fao" // Faroese + "fij" // Fijian + "fin" // Finnish + "fre" // French + "fry" // WesternFrisian + "gla" // Gaelic + "glg" // Galician + "geo" // Georgian + "ger" // German + "gre" // Greek + "\0\0\0" // Greenlandic + "grn" // Guarani + "guj" // Gujarati + "hau" // Hausa + "heb" // Hebrew + "hin" // Hindi + "hun" // Hungarian + "ice" // Icelandic + "ind" // Indonesian + "ina" // Interlingua + "ile" // Interlingue + "iku" // Inuktitut + "ipk" // Inupiak + "gle" // Irish + "ita" // Italian + "jpn" // Japanese + "jav" // Javanese + "kan" // Kannada + "kas" // Kashmiri + "kaz" // Kazakh + "kin" // Kinyarwanda + "kir" // Kirghiz + "kor" // Korean + "kur" // Kurdish + "\0\0\0" // Rundi + "lao" // Lao + "lat" // Latin + "lav" // Latvian + "lin" // Lingala + "lit" // Lithuanian + "mac" // Macedonian + "mlg" // Malagasy + "may" // Malay + "mal" // Malayalam + "mlt" // Maltese + "mao" // Maori + "mar" // Marathi + "mah" // Marshallese + "mon" // Mongolian + "nau" // NauruLanguage + "nep" // Nepali + "nor" // NorwegianBokmal + "oci" // Occitan + "ori" // Oriya + "\0\0\0" // Pashto + "per" // Persian + "pol" // Polish + "por" // Portuguese + "pan" // Punjabi + "que" // Quechua + "roh" // Romansh + "rum" // Romanian + "rus" // Russian + "smo" // Samoan + "sag" // Sango + "san" // Sanskrit + "srp" // Serbian + "oss" // Ossetic + "\0\0\0" // SouthernSotho + "\0\0\0" // Tswana + "sna" // Shona + "snd" // Sindhi + "\0\0\0" // Sinhala + "\0\0\0" // Swati + "slo" // Slovak + "slv" // Slovenian + "som" // Somali + "spa" // Spanish + "sun" // Sundanese + "swa" // Swahili + "swe" // Swedish + "srd" // Sardinian + "tgk" // Tajik + "tam" // Tamil + "tat" // Tatar + "tel" // Telugu + "tha" // Thai + "tib" // Tibetan + "tir" // Tigrinya + "tog" // Tongan + "tso" // Tsonga + "tur" // Turkish + "tuk" // Turkmen + "tah" // Tahitian + "uig" // Uigur + "ukr" // Ukrainian + "urd" // Urdu + "uzb" // Uzbek + "vie" // Vietnamese + "vol" // Volapuk + "wel" // Welsh + "wol" // Wolof + "xho" // Xhosa + "yid" // Yiddish + "yor" // Yoruba + "zha" // Zhuang + "zul" // Zulu + "nno" // NorwegianNynorsk + "bos" // Bosnian + "div" // Divehi + "glv" // Manx + "cor" // Cornish + "aka" // Akan + "kok" // Konkani + "gaa" // Ga + "ibo" // Igbo + "kam" // Kamba + "syc" // Syriac + "\0\0\0" // Blin + "\0\0\0" // Geez + "\0\0\0" // Koro + "sid" // Sidamo + "\0\0\0" // Atsam + "tig" // Tigre + "\0\0\0" // Jju + "fur" // Friulian + "ven" // Venda + "ewe" // Ewe + "\0\0\0" // Walamo + "haw" // Hawaiian + "\0\0\0" // Tyap + "\0\0\0" // Nyanja + "fil" // Filipino + "gsw" // SwissGerman + "iii" // SichuanYi + "kpe" // Kpelle + "nds" // LowGerman + "nbl" // SouthNdebele + "nso" // NorthernSotho + "sme" // NorthernSami + "\0\0\0" // Taroko + "\0\0\0" // Gusii + "\0\0\0" // Taita + "ful" // Fulah + "kik" // Kikuyu + "\0\0\0" // Samburu + "\0\0\0" // Sena + "nde" // NorthNdebele + "\0\0\0" // Rombo + "\0\0\0" // Tachelhit + "kab" // Kabyle + "nyn" // Nyankole + "\0\0\0" // Bena + "\0\0\0" // Vunjo + "bam" // Bambara + "\0\0\0" // Embu + "chr" // Cherokee + "\0\0\0" // Morisyen + "\0\0\0" // Makonde + "\0\0\0" // Langi + "lug" // Ganda + "bem" // Bemba + "\0\0\0" // Kabuverdianu + "\0\0\0" // Meru + "\0\0\0" // Kalenjin + "\0\0\0" // Nama + "\0\0\0" // Machame + "\0\0\0" // Colognian + "mas" // Masai + "\0\0\0" // Soga + "\0\0\0" // Luyia + "\0\0\0" // Asu + "\0\0\0" // Teso + "\0\0\0" // Saho + "\0\0\0" // KoyraChiini + "\0\0\0" // Rwa + "luo" // Luo + "\0\0\0" // Chiga + "\0\0\0" // CentralMoroccoTamazight + "\0\0\0" // KoyraboroSenni + "\0\0\0" // Shambala + "\0\0\0" // Bodo + "ava" // Avaric + "cha" // Chamorro + "che" // Chechen + "chu" // Church + "chv" // Chuvash + "cre" // Cree + "hat" // Haitian + "her" // Herero + "hmo" // HiriMotu + "kau" // Kanuri + "kom" // Komi + "kon" // Kongo + "\0\0\0" // Kwanyama + "lim" // Limburgish + "lub" // LubaKatanga + "ltz" // Luxembourgish + "\0\0\0" // Navaho + "ndo" // Ndonga + "oji" // Ojibwa + "pli" // Pali + "wln" // Walloon + "\0\0\0" // Aghem + "bas" // Basaa + "\0\0\0" // Zarma + "dua" // Duala + "\0\0\0" // JolaFonyi + "ewo" // Ewondo + "\0\0\0" // Bafia + "\0\0\0" // MakhuwaMeetto + "\0\0\0" // Mundang + "\0\0\0" // Kwasio + "\0\0\0" // Nuer + "\0\0\0" // Sakha + "\0\0\0" // Sangu + "\0\0\0" // CongoSwahili + "\0\0\0" // Tasawaq + "vai" // Vai + "\0\0\0" // Walser + "\0\0\0" // Yangben + "ave" // Avestan + "\0\0\0" // Asturian + "\0\0\0" // Ngomba + "\0\0\0" // Kako + "\0\0\0" // Meta + "\0\0\0" // Ngiemboon + ; + +QT_END_NAMESPACE + +#endif /* MARCLANGUAGECODES_H_ */ diff --git a/src/plugins/geoservices/nokia/nokia.pro b/src/plugins/geoservices/nokia/nokia.pro new file mode 100644 index 0000000..cd340f5 --- /dev/null +++ b/src/plugins/geoservices/nokia/nokia.pro @@ -0,0 +1,61 @@ +TARGET = qtgeoservices_nokia + +QT += location-private positioning-private network + +contains(QT_CONFIG, location-china-support) { + # China support + DEFINES += USE_CHINA_NETWORK_REGISTRATION + QT += systeminfo +} + +HEADERS += \ + qgeocodereply_nokia.h \ + qgeocodexmlparser.h \ + qgeocodingmanagerengine_nokia.h \ + qgeotiledmappingmanagerengine_nokia.h \ + qgeotilefetcher_nokia.h \ + qgeomapreply_nokia.h \ + qgeoroutereply_nokia.h \ + qgeoroutexmlparser.h \ + qgeoroutingmanagerengine_nokia.h \ + qgeoserviceproviderplugin_nokia.h \ + marclanguagecodes.h \ + qgeonetworkaccessmanager.h \ + qgeointrinsicnetworkaccessmanager.h \ + qgeouriprovider.h \ + uri_constants.h \ + qgeoerror_messages.h \ + qgeomapversion.h \ + qgeotiledmap_nokia.h + + +SOURCES += \ + qgeocodereply_nokia.cpp \ + qgeocodexmlparser.cpp \ + qgeocodingmanagerengine_nokia.cpp \ + qgeotiledmappingmanagerengine_nokia.cpp \ + qgeotilefetcher_nokia.cpp \ + qgeomapreply_nokia.cpp \ + qgeoroutereply_nokia.cpp \ + qgeoroutexmlparser.cpp \ + qgeoroutingmanagerengine_nokia.cpp \ + qgeoserviceproviderplugin_nokia.cpp \ + qgeointrinsicnetworkaccessmanager.cpp \ + qgeouriprovider.cpp \ + uri_constants.cpp \ + qgeoerror_messages.cpp \ + qgeomapversion.cpp \ + qgeotiledmap_nokia.cpp + +include(placesv2/placesv2.pri) + +RESOURCES += resource.qrc + +INCLUDEPATH += ../../../location/maps + +OTHER_FILES += \ + nokia_plugin.json + +PLUGIN_TYPE = geoservices +PLUGIN_CLASS_NAME = QGeoServiceProviderFactoryNokia +load(qt_plugin) diff --git a/src/plugins/geoservices/nokia/nokia_plugin.json b/src/plugins/geoservices/nokia/nokia_plugin.json new file mode 100644 index 0000000..1fc2827 --- /dev/null +++ b/src/plugins/geoservices/nokia/nokia_plugin.json @@ -0,0 +1,19 @@ +{ + "Keys": ["here"], + "Provider": "here", + "Version": 101, + "Experimental": false, + "Features": [ + "OnlineRoutingFeature", + "RouteUpdatesFeature", + "AlternativeRoutesFeature", + "ExcludeAreasRoutingFeature", + "OnlineGeocodingFeature", + "OnlineMappingFeature", + "OnlinePlacesFeature", + "ReverseGeocodingFeature", + "PlaceRecommendationsFeature", + "SearchSuggestionsFeature", + "LocalizedPlacesFeature" + ] +} diff --git a/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp new file mode 100644 index 0000000..f877e9d --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "jsonparserhelpers.h" +#include "../qplacemanagerengine_nokiav2.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoCoordinate parseCoordinate(const QJsonArray &coordinateArray) +{ + return QGeoCoordinate(coordinateArray.at(0).toDouble(), coordinateArray.at(1).toDouble()); +} + +QPlaceSupplier parseSupplier(const QJsonObject &supplierObject, + const QPlaceManagerEngineNokiaV2 *engine) +{ + Q_ASSERT(engine); + + QPlaceSupplier supplier; + supplier.setName(supplierObject.value(QStringLiteral("title")).toString()); + supplier.setUrl(supplierObject.value(QStringLiteral("href")).toString()); + + supplier.setIcon(engine->icon(supplierObject.value(QStringLiteral("icon")).toString())); + + return supplier; +} + +QPlaceCategory parseCategory(const QJsonObject &categoryObject, + const QPlaceManagerEngineNokiaV2 *engine) +{ + Q_ASSERT(engine); + + QPlaceCategory category; + + category.setName(categoryObject.value(QStringLiteral("title")).toString()); + + const QUrl href(categoryObject.value(QStringLiteral("href")).toString()); + const QString hrefPath(href.path()); + category.setCategoryId(hrefPath.mid(hrefPath.lastIndexOf(QLatin1Char('/')) + 1)); + + + category.setIcon(engine->icon(categoryObject.value(QStringLiteral("icon")).toString())); + return category; +} + +QList parseCategories(const QJsonArray &categoryArray, + const QPlaceManagerEngineNokiaV2 *engine) +{ + Q_ASSERT(engine); + + QList categoryList; + for (int i = 0; i < categoryArray.count(); ++i) + categoryList.append(parseCategory(categoryArray.at(i).toObject(), + engine)); + + return categoryList; +} + +QList parseContactDetails(const QJsonArray &contacts) +{ + QList contactDetails; + + for (int i = 0; i < contacts.count(); ++i) { + QJsonObject contact = contacts.at(i).toObject(); + + QPlaceContactDetail detail; + detail.setLabel(contact.value(QStringLiteral("label")).toString()); + detail.setValue(contact.value(QStringLiteral("value")).toString()); + + contactDetails.append(detail); + } + + return contactDetails; +} + +QPlaceImage parseImage(const QJsonObject &imageObject, + const QPlaceManagerEngineNokiaV2 *engine) +{ + Q_ASSERT(engine); + + QPlaceImage image; + + image.setAttribution(imageObject.value(QStringLiteral("attribution")).toString()); + image.setUrl(imageObject.value(QStringLiteral("src")).toString()); + image.setSupplier(parseSupplier(imageObject.value(QStringLiteral("supplier")).toObject(), + engine)); + + return image; +} + +QPlaceReview parseReview(const QJsonObject &reviewObject, + const QPlaceManagerEngineNokiaV2 *engine) +{ + Q_ASSERT(engine); + + QPlaceReview review; + + review.setDateTime(QDateTime::fromString(reviewObject.value(QStringLiteral("date")).toString())); + + if (reviewObject.contains(QStringLiteral("title"))) + review.setTitle(reviewObject.value(QStringLiteral("title")).toString()); + + if (reviewObject.contains(QStringLiteral("rating"))) + review.setRating(reviewObject.value(QStringLiteral("rating")).toDouble()); + + review.setText(reviewObject.value(QStringLiteral("description")).toString()); + + QJsonObject userObject = reviewObject.value(QStringLiteral("user")).toObject(); + + QPlaceUser user; + user.setUserId(userObject.value(QStringLiteral("id")).toString()); + user.setName(userObject.value(QStringLiteral("title")).toString()); + review.setUser(user); + + review.setAttribution(reviewObject.value(QStringLiteral("attribution")).toString()); + + review.setLanguage(reviewObject.value(QStringLiteral("language")).toString()); + + review.setSupplier(parseSupplier(reviewObject.value(QStringLiteral("supplier")).toObject(), + engine)); + + //if (reviewObject.contains(QStringLiteral("via"))) { + // QJsonObject viaObject = reviewObject.value(QStringLiteral("via")).toObject(); + //} + + return review; +} + +QPlaceEditorial parseEditorial(const QJsonObject &editorialObject, + const QPlaceManagerEngineNokiaV2 *engine) +{ + Q_ASSERT(engine); + + QPlaceEditorial editorial; + + editorial.setAttribution(editorialObject.value(QStringLiteral("attribution")).toString()); + + //if (editorialObject.contains(QStringLiteral("via"))) { + // QJsonObject viaObject = editorialObject.value(QStringLiteral("via")).toObject(); + //} + + editorial.setSupplier(parseSupplier(editorialObject.value(QStringLiteral("supplier")).toObject(), + engine)); + editorial.setLanguage(editorialObject.value(QStringLiteral("language")).toString()); + editorial.setText(editorialObject.value(QStringLiteral("description")).toString()); + + return editorial; +} + +void parseCollection(QPlaceContent::Type type, const QJsonObject &object, + QPlaceContent::Collection *collection, int *totalCount, + QPlaceContentRequest *previous, QPlaceContentRequest *next, + const QPlaceManagerEngineNokiaV2 *engine) +{ + Q_ASSERT(engine); + + if (totalCount) + *totalCount = object.value(QStringLiteral("available")).toDouble(); + + int offset = 0; + if (object.contains(QStringLiteral("offset"))) + offset = object.value(QStringLiteral("offset")).toDouble(); + + if (previous && object.contains(QStringLiteral("previous"))) { + previous->setContentType(type); + previous->setContentContext(QUrl(object.value(QStringLiteral("previous")).toString())); + } + + if (next && object.contains(QStringLiteral("next"))) { + next->setContentType(type); + next->setContentContext(QUrl(object.value(QStringLiteral("next")).toString())); + } + + if (collection) { + QJsonArray items = object.value(QStringLiteral("items")).toArray(); + for (int i = 0; i < items.count(); ++i) { + QJsonObject itemObject = items.at(i).toObject(); + + switch (type) { + case QPlaceContent::ImageType: + collection->insert(offset + i, parseImage(itemObject, engine)); + break; + case QPlaceContent::ReviewType: + collection->insert(offset + i, parseReview(itemObject, engine)); + break; + case QPlaceContent::EditorialType: + collection->insert(offset + i, parseEditorial(itemObject, engine)); + break; + case QPlaceContent::NoType: + break; + } + } + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.h b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.h new file mode 100644 index 0000000..4c7fffb --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef JSONPARSERHELPERS_H +#define JSONPARSERHELPERS_H + +#include + +QT_BEGIN_NAMESPACE + +class QJsonArray; +class QJsonObject; +class QGeoCoordinate; +class QPlaceContactDetail; +class QPlaceImage; +class QPlaceReview; +class QPlaceEditorial; +class QPlaceCategory; +class QPlaceContentRequest; +class QPlaceManagerEngineNokiaV2; + +QGeoCoordinate parseCoordinate(const QJsonArray &coordinateArray); +QPlaceSupplier parseSupplier(const QJsonObject &supplierObject, + const QPlaceManagerEngineNokiaV2 *engine); +QPlaceCategory parseCategory(const QJsonObject &categoryObject, + const QPlaceManagerEngineNokiaV2 *engine); +QList parseCategories(const QJsonArray &categoryArray, + const QPlaceManagerEngineNokiaV2 *engine); +QList parseContactDetails(const QJsonArray &contacts); + +QPlaceImage parseImage(const QJsonObject &imageObject, + const QPlaceManagerEngineNokiaV2 *engine); +QPlaceReview parseReview(const QJsonObject &reviewObject, + const QPlaceManagerEngineNokiaV2 *engine); +QPlaceEditorial parseEditorial(const QJsonObject &editorialObject, + const QPlaceManagerEngineNokiaV2 *engine); + +void parseCollection(QPlaceContent::Type type, const QJsonObject &object, + QPlaceContent::Collection *collection, int *totalCount, + QPlaceContentRequest *previous, QPlaceContentRequest *next, + const QPlaceManagerEngineNokiaV2 *engine); + +QT_END_NAMESPACE + +#endif // JSONPARSERHELPERS_H diff --git a/src/plugins/geoservices/nokia/placesv2/placesv2.pri b/src/plugins/geoservices/nokia/placesv2/placesv2.pri new file mode 100644 index 0000000..18c9fe3 --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/placesv2.pri @@ -0,0 +1,21 @@ +QT *= location network + +HEADERS += \ + qplacemanagerengine_nokiav2.h \ + placesv2/qplacecategoriesreplyhere.h \ + placesv2/qplacecontentreplyimpl.h \ + placesv2/qplacedetailsreplyimpl.h \ + placesv2/qplaceidreplyimpl.h \ + placesv2/qplacesearchreplyhere.h \ + placesv2/qplacesearchsuggestionreplyimpl.h \ + placesv2/jsonparserhelpers.h + +SOURCES += \ + qplacemanagerengine_nokiav2.cpp \ + placesv2/qplacecategoriesreplyhere.cpp \ + placesv2/qplacecontentreplyimpl.cpp \ + placesv2/qplacedetailsreplyimpl.cpp \ + placesv2/qplaceidreplyimpl.cpp \ + placesv2/qplacesearchreplyhere.cpp \ + placesv2/qplacesearchsuggestionreplyimpl.cpp \ + placesv2/jsonparserhelpers.cpp diff --git a/src/plugins/geoservices/nokia/placesv2/qplacecategoriesreplyhere.cpp b/src/plugins/geoservices/nokia/placesv2/qplacecategoriesreplyhere.cpp new file mode 100644 index 0000000..5ae0d92 --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacecategoriesreplyhere.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacecategoriesreplyhere.h" + +QT_BEGIN_NAMESPACE + +QPlaceCategoriesReplyHere::QPlaceCategoriesReplyHere(QObject *parent) +: QPlaceReply(parent) +{ +} + +QPlaceCategoriesReplyHere::~QPlaceCategoriesReplyHere() +{ +} + +void QPlaceCategoriesReplyHere::emitFinished() +{ + setFinished(true); + emit finished(); +} + +void QPlaceCategoriesReplyHere::setError(QPlaceReply::Error error_, const QString &errorString) +{ + QPlaceReply::setError(error_, errorString); + emit error(error_, errorString); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacecategoriesreplyhere.h b/src/plugins/geoservices/nokia/placesv2/qplacecategoriesreplyhere.h new file mode 100644 index 0000000..4258d39 --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacecategoriesreplyhere.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECATEGORIESREPLYHERE_H +#define QPLACECATEGORIESREPLYHERE_H + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceCategoriesReplyHere : public QPlaceReply +{ + Q_OBJECT + +public: + explicit QPlaceCategoriesReplyHere(QObject *parent = 0); + ~QPlaceCategoriesReplyHere(); + + void emitFinished(); + +private slots: + void setError(QPlaceReply::Error error_, const QString &errorString); +}; + +QT_END_NAMESPACE + +#endif // QPLACECATEGORIESREPLYHERE_H diff --git a/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp new file mode 100644 index 0000000..9a5cbf4 --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "jsonparserhelpers.h" +#include "qplacecontentreplyimpl.h" +#include "../qplacemanagerengine_nokiav2.h" +#include "../qgeoerror_messages.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QPlaceContentReplyImpl::QPlaceContentReplyImpl(const QPlaceContentRequest &request, + QNetworkReply *reply, + QPlaceManagerEngineNokiaV2 *engine) + : QPlaceContentReply(engine), m_reply(reply), m_engine(engine) +{ + Q_ASSERT(engine); + setRequest(request); + + if (!m_reply) + return; + + m_reply->setParent(this); + connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(replyError(QNetworkReply::NetworkError))); +} + +QPlaceContentReplyImpl::~QPlaceContentReplyImpl() +{ +} + +void QPlaceContentReplyImpl::abort() +{ + if (m_reply) + m_reply->abort(); +} + +void QPlaceContentReplyImpl::setError(QPlaceReply::Error error_, const QString &errorString) +{ + QPlaceContentReply::setError(error_, errorString); + emit error(error_, errorString); + setFinished(true); + emit finished(); +} + +void QPlaceContentReplyImpl::replyFinished() +{ + if (m_reply->isOpen()) { + QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + if (!document.isObject()) { + setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); + return; + } + + QJsonObject object = document.object(); + + QPlaceContent::Collection collection; + int totalCount; + QPlaceContentRequest previous; + QPlaceContentRequest next; + + parseCollection(request().contentType(), object, &collection, &totalCount, + &previous, &next, m_engine); + + setTotalCount(totalCount); + setContent(collection); + setPreviousPageRequest(previous); + setNextPageRequest(next); + } + + m_reply->deleteLater(); + m_reply = 0; + + setFinished(true); + emit finished(); +} + +void QPlaceContentReplyImpl::replyError(QNetworkReply::NetworkError error) +{ + switch (error) { + case QNetworkReply::OperationCanceledError: + setError(CancelError, "Request canceled."); + break; + default: + setError(CommunicationError, "Network error."); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.h b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.h new file mode 100644 index 0000000..c7ef7ee --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECONTENTREPLYIMPL_H +#define QPLACECONTENTREPLYIMPL_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceManager; +class QPlaceManagerEngineNokiaV2; + +class QPlaceContentReplyImpl : public QPlaceContentReply +{ + Q_OBJECT + +public: + QPlaceContentReplyImpl(const QPlaceContentRequest &request, QNetworkReply *reply, + QPlaceManagerEngineNokiaV2 *engine); + ~QPlaceContentReplyImpl(); + + void abort(); + +private slots: + void setError(QPlaceReply::Error error_, const QString &errorString); + void replyFinished(); + void replyError(QNetworkReply::NetworkError error); + +private: + QNetworkReply *m_reply; + QPlaceManagerEngineNokiaV2 *m_engine; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp new file mode 100644 index 0000000..e85b9cc --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp @@ -0,0 +1,347 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacedetailsreplyimpl.h" +#include "jsonparserhelpers.h" +#include "../qplacemanagerengine_nokiav2.h" +#include "../qgeoerror_messages.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// These countries format the street address as: {house number} {street name} +// All other countries format it as: {street name} {house number} +static const char COUNTRY_TABLE_string[] = + "CAN\0" + "NZL\0" + "GBR\0" + "AUS\0" + "LKA\0" + "USA\0" + "SGP\0" + "FRA\0" + "BHS\0" + "CHN\0" + "IND\0" + "IRL\0" + "ARE\0" + "\0"; + +static const int COUNTRY_TABLE_indices[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, -1 +}; + +static bool countryTableContains(const QString &countryCode) +{ + for (int i = 0; COUNTRY_TABLE_indices[i] != -1; ++i) { + if (countryCode == QLatin1String(COUNTRY_TABLE_string + COUNTRY_TABLE_indices[i])) + return true; + } + + return false; +} + +QPlaceDetailsReplyImpl::QPlaceDetailsReplyImpl(QNetworkReply *reply, + QPlaceManagerEngineNokiaV2 *parent) + : QPlaceDetailsReply(parent), m_reply(reply), m_engine(parent) +{ + Q_ASSERT(parent); + + if (!m_reply) + return; + + m_reply->setParent(this); + connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); +} + +QPlaceDetailsReplyImpl::~QPlaceDetailsReplyImpl() +{ +} + +void QPlaceDetailsReplyImpl::abort() +{ + if (m_reply) + m_reply->abort(); +} + +void QPlaceDetailsReplyImpl::setError(QPlaceReply::Error error_, const QString &errorString) +{ + QPlaceReply::setError(error_, errorString); + emit error(error_, errorString); + setFinished(true); + emit finished(); +} + +void QPlaceDetailsReplyImpl::replyFinished() +{ + if (m_reply->error() != QNetworkReply::NoError) { + switch (m_reply->error()) { + case QNetworkReply::OperationCanceledError: + setError(CancelError, "Request canceled."); + break; + case QNetworkReply::ContentNotFoundError: + setError(PlaceDoesNotExistError, + QString::fromLatin1("The id, %1, does not reference an existing place") + .arg(m_placeId)); + break; + default: + setError(CommunicationError, "Network error."); + } + return; + } + + QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + if (!document.isObject()) { + setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); + return; + } + + QJsonObject object = document.object(); + + QPlace place; + + place.setPlaceId(object.value(QLatin1String("placeId")).toString()); + + //const QUrl view = object.value(QLatin1String("view")).toString(); + + place.setName(object.value(QLatin1String("name")).toString()); + + //if (object.contains(QLatin1String("distance"))) + // double distance = object.value(QLatin1String("distance")).toDouble(); + + //if (object.contains(QLatin1String("alternativeNames"))) { + // QJsonArray alternativeNames = object.value(QLatin1String("alternativeNames")).toArray(); + //} + + QGeoLocation location; + + QJsonObject locationObject = object.value(QLatin1String("location")).toObject(); + + //if (locationObject.contains(QLatin1String("locationId"))) + // const QString locationId = locationObject.value(QLatin1String("locationId")).toString(); + + QJsonArray position = locationObject.value(QLatin1String("position")).toArray(); + location.setCoordinate(QGeoCoordinate(position.at(0).toDouble(), position.at(1).toDouble())); + + QGeoAddress address; + + QJsonObject addressObject = locationObject.value(QLatin1String("address")).toObject(); + + address.setText(addressObject.value(QLatin1String("text")).toString()); + + address.setCountry(addressObject.value(QLatin1String("country")).toString()); + address.setCountryCode(addressObject.value(QLatin1String("countryCode")).toString()); + + QString house; + QString street; + + if (addressObject.contains(QLatin1String("house"))) + house = addressObject.value(QLatin1String("house")).toString(); + if (addressObject.contains(QLatin1String("street"))) + street = addressObject.value(QLatin1String("street")).toString(); + + if (countryTableContains(address.countryCode())) { + if (!house.isEmpty() && !street.startsWith(house)) + street = house + QLatin1Char(' ') + street; + } else { + if (!house.isEmpty() && !street.endsWith(house)) + street += QLatin1Char(' ') + house; + } + + address.setStreet(street); + + if (addressObject.contains(QLatin1String("city"))) + address.setCity(addressObject.value(QLatin1String("city")).toString()); + if (addressObject.contains(QLatin1String("district"))) + address.setDistrict(addressObject.value(QLatin1String("district")).toString()); + if (addressObject.contains(QLatin1String("state"))) + address.setState(addressObject.value(QLatin1String("state")).toString()); + if (addressObject.contains(QLatin1String("county"))) + address.setCounty(addressObject.value(QLatin1String("county")).toString()); + if (addressObject.contains(QLatin1String("postalCode"))) + address.setPostalCode(addressObject.value(QLatin1String("postalCode")).toString()); + + location.setAddress(address); + + if (locationObject.contains(QLatin1String("bbox"))) { + QJsonArray bbox = locationObject.value(QLatin1String("bbox")).toArray(); + QGeoRectangle box(QGeoCoordinate(bbox.at(3).toDouble(), bbox.at(0).toDouble()), + QGeoCoordinate(bbox.at(1).toDouble(), bbox.at(2).toDouble())); + location.setBoundingBox(box); + } + + place.setLocation(location); + + place.setCategories(parseCategories(object.value(QLatin1String("categories")).toArray(), + m_engine)); + + place.setIcon(m_engine->icon(object.value(QLatin1String("icon")).toString(), + place.categories())); + + if (object.contains(QLatin1String("contacts"))) { + QJsonObject contactsObject = object.value(QLatin1String("contacts")).toObject(); + + if (contactsObject.contains(QLatin1String("phone"))) { + place.setContactDetails(QPlaceContactDetail::Phone, + parseContactDetails(contactsObject.value(QLatin1String("phone")).toArray())); + } + if (contactsObject.contains(QLatin1String("fax"))) { + place.setContactDetails(QPlaceContactDetail::Fax, + parseContactDetails(contactsObject.value(QLatin1String("fax")).toArray())); + } + if (contactsObject.contains(QLatin1String("website"))) { + place.setContactDetails(QPlaceContactDetail::Website, + parseContactDetails(contactsObject.value(QLatin1String("website")).toArray())); + } + if (contactsObject.contains(QLatin1String("email"))) { + place.setContactDetails(QPlaceContactDetail::Email, + parseContactDetails(contactsObject.value(QLatin1String("email")).toArray())); + } + } + + //if (object.contains(QLatin1String("verifiedByOwner"))) + // bool verifiedByOwner = object.value(QLatin1String("verifiedByOwner")).toBool(); + + if (object.contains(QLatin1String("attribution"))) + place.setAttribution(object.value(QLatin1String("attribution")).toString()); + + if (object.contains(QLatin1String("supplier"))) { + place.setSupplier(parseSupplier(object.value(QLatin1String("supplier")).toObject(), + m_engine)); + } + + if (object.contains(QLatin1String("ratings"))) { + QJsonObject ratingsObject = object.value(QLatin1String("ratings")).toObject(); + + QPlaceRatings ratings; + ratings.setAverage(ratingsObject.value(QLatin1String("average")).toDouble()); + ratings.setCount(ratingsObject.value(QLatin1String("count")).toDouble()); + ratings.setMaximum(5.0); + + place.setRatings(ratings); + } + + if (object.contains(QLatin1String("extended"))) { + QJsonObject extendedObject = object.value(QLatin1String("extended")).toObject(); + + for (auto it = extendedObject.constBegin(), end = extendedObject.constEnd(); it != end; ++it) { + QJsonObject attributeObject = it.value().toObject(); + + QPlaceAttribute attribute; + + attribute.setLabel(attributeObject.value(QLatin1String("label")).toString()); + attribute.setText(attributeObject.value(QLatin1String("text")).toString()); + + QString key = it.key(); + if (key == QLatin1String("payment")) + place.setExtendedAttribute(QPlaceAttribute::Payment, attribute); + else if (key == QLatin1String("openingHours")) + place.setExtendedAttribute(QPlaceAttribute::OpeningHours, attribute); + else + place.setExtendedAttribute(key, attribute); + } + } + + if (object.contains(QLatin1String("media"))) { + QJsonObject mediaObject = object.value(QLatin1String("media")).toObject(); + + if (mediaObject.contains(QLatin1String("images"))) { + QPlaceContent::Collection collection; + int totalCount = 0; + + parseCollection(QPlaceContent::ImageType, + mediaObject.value(QLatin1String("images")).toObject(), + &collection, &totalCount, 0, 0, m_engine); + + place.setTotalContentCount(QPlaceContent::ImageType, totalCount); + place.setContent(QPlaceContent::ImageType, collection); + } + if (mediaObject.contains(QLatin1String("editorials"))) { + QPlaceContent::Collection collection; + int totalCount = 0; + + parseCollection(QPlaceContent::EditorialType, + mediaObject.value(QLatin1String("editorials")).toObject(), + &collection, &totalCount, 0, 0, m_engine); + + place.setTotalContentCount(QPlaceContent::EditorialType, totalCount); + place.setContent(QPlaceContent::EditorialType, collection); + } + if (mediaObject.contains(QLatin1String("reviews"))) { + QPlaceContent::Collection collection; + int totalCount = 0; + + parseCollection(QPlaceContent::ReviewType, + mediaObject.value(QLatin1String("reviews")).toObject(), + &collection, &totalCount, 0, 0, m_engine); + + place.setTotalContentCount(QPlaceContent::ReviewType, totalCount); + place.setContent(QPlaceContent::ReviewType, collection); + } + } + + //if (object.contains(QLatin1String("related"))) { + // QJsonObject relatedObject = object.value(QLatin1String("related")).toObject(); + //} + + QPlaceAttribute provider; + provider.setText(QLatin1String("here")); + place.setExtendedAttribute(QPlaceAttribute::Provider, provider); + + place.setVisibility(QLocation::PublicVisibility); + place.setDetailsFetched(true); + setPlace(place); + + m_reply->deleteLater(); + m_reply = 0; + + setFinished(true); + emit finished(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.h b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.h new file mode 100644 index 0000000..2524d04 --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEDETAILSREPLYIMPL_H +#define QPLACEDETAILSREPLYIMPL_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceManager; +class QPlaceManagerEngineNokiaV2; + +class QPlaceDetailsReplyImpl : public QPlaceDetailsReply +{ + Q_OBJECT + +public: + QPlaceDetailsReplyImpl(QNetworkReply *reply, QPlaceManagerEngineNokiaV2 *parent); + ~QPlaceDetailsReplyImpl(); + + void abort(); + void setPlaceId(const QString &placeId) { m_placeId = placeId; } + +private slots: + void setError(QPlaceReply::Error error_, const QString &errorString); + void replyFinished(); + +private: + QNetworkReply *m_reply; + QPlaceManagerEngineNokiaV2 *m_engine; + QString m_placeId; +}; + +QT_END_NAMESPACE + +#endif // QPLACEDETAILSREPLYIMPL_H diff --git a/src/plugins/geoservices/nokia/placesv2/qplaceidreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplaceidreplyimpl.cpp new file mode 100644 index 0000000..2378d0b --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplaceidreplyimpl.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplaceidreplyimpl.h" + +QT_BEGIN_NAMESPACE + +QPlaceIdReplyImpl::QPlaceIdReplyImpl(QPlaceIdReply::OperationType type, QObject *parent) +: QPlaceIdReply(type, parent) +{ +} + +QPlaceIdReplyImpl::~QPlaceIdReplyImpl() +{ +} + +void QPlaceIdReplyImpl::setId(const QString &id) +{ + QPlaceIdReply::setId(id); +} + +void QPlaceIdReplyImpl::setError(QPlaceReply::Error error_, const QString &errorString) +{ + if (error_ != QPlaceReply::NoError) { + QPlaceIdReply::setError(error_, errorString); + emit error(error_, errorString); + } + + setFinished(true); + emit finished(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplaceidreplyimpl.h b/src/plugins/geoservices/nokia/placesv2/qplaceidreplyimpl.h new file mode 100644 index 0000000..091f3d6 --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplaceidreplyimpl.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef UNSUPPORTED_REPLIES_H +#define UNSUPPORTED_REPLIES_H + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceIdReplyImpl : public QPlaceIdReply +{ + Q_OBJECT + +public: + QPlaceIdReplyImpl(QPlaceIdReply::OperationType type, QObject *parent = 0); + ~QPlaceIdReplyImpl(); + + void setId(const QString &id); + +private slots: + void setError(QPlaceReply::Error error_, const QString &errorString); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp new file mode 100644 index 0000000..3a56c92 --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacesearchreplyhere.h" +#include "jsonparserhelpers.h" +#include "../qplacemanagerengine_nokiav2.h" +#include "../qgeoerror_messages.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +QPlaceSearchReplyHere::QPlaceSearchReplyHere(const QPlaceSearchRequest &request, + QNetworkReply *reply, + QPlaceManagerEngineNokiaV2 *parent) + : QPlaceSearchReply(parent), m_reply(reply), m_engine(parent) +{ + Q_ASSERT(parent); + + setRequest(request); + + if (!m_reply) + return; + + m_reply->setParent(this); + connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); +} + +QPlaceSearchReplyHere::~QPlaceSearchReplyHere() +{ +} + +void QPlaceSearchReplyHere::abort() +{ + if (m_reply) + m_reply->abort(); +} + +void QPlaceSearchReplyHere::setError(QPlaceReply::Error error_, const QString &errorString) +{ + QPlaceReply::setError(error_, errorString); + emit error(error_, errorString); + setFinished(true); + emit finished(); +} + +void QPlaceSearchReplyHere::replyFinished() +{ + if (m_reply->error() != QNetworkReply::NoError) { + switch (m_reply->error()) { + case QNetworkReply::OperationCanceledError: + setError(CancelError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, CANCEL_ERROR)); + break; + case QNetworkReply::ContentNotFoundError: + setError(PlaceDoesNotExistError, + QString::fromLatin1("The id, %1, does not reference an existing place") + .arg(request().recommendationId())); + break; + default: + setError(CommunicationError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, NETWORK_ERROR)); + } + return; + } + + QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + if (!document.isObject()) { + setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); + return; + } + + QJsonObject resultsObject = document.object(); + + if (resultsObject.contains(QStringLiteral("results"))) + resultsObject = resultsObject.value(QStringLiteral("results")).toObject(); + + QJsonArray items = resultsObject.value(QStringLiteral("items")).toArray(); + + QList results; + for (int i = 0; i < items.count(); ++i) { + QJsonObject item = items.at(i).toObject(); + + const QString type = item.value(QStringLiteral("type")).toString(); + if (type == QStringLiteral("urn:nlp-types:place")) + results.append(parsePlaceResult(item)); + else if (type == QStringLiteral("urn:nlp-types:search")) + results.append(parseSearchResult(item)); + } + + if (resultsObject.contains(QStringLiteral("next"))) { + QPlaceSearchRequest request; + request.setSearchContext(QUrl(resultsObject.value(QStringLiteral("next")).toString())); + setNextPageRequest(request); + } + + if (resultsObject.contains(QStringLiteral("previous"))) { + QPlaceSearchRequest request; + request.setSearchContext(QUrl(resultsObject.value(QStringLiteral("previous")).toString())); + setPreviousPageRequest(request); + } + + setResults(results); + + m_reply->deleteLater(); + m_reply = 0; + + setFinished(true); + emit finished(); +} + +QPlaceResult QPlaceSearchReplyHere::parsePlaceResult(const QJsonObject &item) const +{ + QPlaceResult result; + + if (item.contains(QStringLiteral("distance"))) + result.setDistance(item.value(QStringLiteral("distance")).toDouble()); + + QPlace place; + + QGeoLocation location; + + location.setCoordinate(parseCoordinate(item.value(QStringLiteral("position")).toArray())); + + const QString vicinity = item.value(QStringLiteral("vicinity")).toString(); + QGeoAddress address; + address.setText(vicinity); + location.setAddress(address); + + if (item.contains(QStringLiteral("bbox"))) { + QJsonArray bbox = item.value(QStringLiteral("bbox")).toArray(); + QGeoRectangle box(QGeoCoordinate(bbox.at(3).toDouble(), bbox.at(0).toDouble()), + QGeoCoordinate(bbox.at(1).toDouble(), bbox.at(2).toDouble())); + location.setBoundingBox(box); + } + + place.setLocation(location); + + QPlaceRatings ratings; + ratings.setAverage(item.value(QStringLiteral("averageRating")).toDouble()); + ratings.setMaximum(5.0); + place.setRatings(ratings); + + const QString title = item.value(QStringLiteral("title")).toString(); + place.setName(title); + result.setTitle(title); + + QPlaceIcon icon = m_engine->icon(item.value(QStringLiteral("icon")).toString()); + place.setIcon(icon); + result.setIcon(icon); + + place.setCategory(parseCategory(item.value(QStringLiteral("category")).toObject(), + m_engine)); + + //QJsonArray having = item.value(QStringLiteral("having")).toArray(); + + result.setSponsored(item.value(QStringLiteral("sponsored")).toBool()); + + QUrl href = item.value(QStringLiteral("href")).toString(); + //QUrl type = item.value(QStringLiteral("type")).toString(); + + place.setPlaceId(href.path().mid(18, 41)); + + QPlaceAttribute provider; + provider.setText(QStringLiteral("here")); + place.setExtendedAttribute(QPlaceAttribute::Provider, provider); + place.setVisibility(QLocation::PublicVisibility); + + result.setPlace(place); + + return result; +} + +QPlaceProposedSearchResult QPlaceSearchReplyHere::parseSearchResult(const QJsonObject &item) const +{ + QPlaceProposedSearchResult result; + + result.setTitle(item.value(QStringLiteral("title")).toString()); + + QPlaceIcon icon = m_engine->icon(item.value(QStringLiteral("icon")).toString()); + result.setIcon(icon); + + QPlaceSearchRequest request; + request.setSearchContext(QUrl(item.value("href").toString())); + + result.setSearchRequest(request); + + return result; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.h b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.h new file mode 100644 index 0000000..a712ab8 --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESEARCHREPLYHERE_H +#define QPLACESEARCHREPLYHERE_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceManagerEngineNokiaV2; +class QPlaceResult; +class QPlaceProposedSearchResult; + +class QPlaceSearchReplyHere : public QPlaceSearchReply +{ + Q_OBJECT + +public: + explicit QPlaceSearchReplyHere(const QPlaceSearchRequest &request, + QNetworkReply *reply, + QPlaceManagerEngineNokiaV2 *parent); + ~QPlaceSearchReplyHere(); + + void abort(); + +private slots: + void setError(QPlaceReply::Error error_, const QString &errorString); + void replyFinished(); + +private: + QPlaceResult parsePlaceResult(const QJsonObject &item) const; + QPlaceProposedSearchResult parseSearchResult(const QJsonObject &item) const; + + QNetworkReply *m_reply; + QPlaceManagerEngineNokiaV2 *m_engine; +}; + +QT_END_NAMESPACE + +#endif // QPLACESEARCHREPLYHERE_H diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.cpp new file mode 100644 index 0000000..6ed8b5a --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacesearchsuggestionreplyimpl.h" +#include "../qgeoerror_messages.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QPlaceSearchSuggestionReplyImpl::QPlaceSearchSuggestionReplyImpl(QNetworkReply *reply, + QObject *parent) +: QPlaceSearchSuggestionReply(parent), m_reply(reply) +{ + if (!m_reply) + return; + + m_reply->setParent(this); + connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); +} + +QPlaceSearchSuggestionReplyImpl::~QPlaceSearchSuggestionReplyImpl() +{ +} + +void QPlaceSearchSuggestionReplyImpl::abort() +{ + if (m_reply) + m_reply->abort(); +} + +void QPlaceSearchSuggestionReplyImpl::setError(QPlaceReply::Error error_, + const QString &errorString) +{ + QPlaceReply::setError(error_, errorString); + emit error(error_, errorString); + setFinished(true); + emit finished(); +} + +void QPlaceSearchSuggestionReplyImpl::replyFinished() +{ + if (m_reply->error() != QNetworkReply::NoError) { + switch (m_reply->error()) { + case QNetworkReply::OperationCanceledError: + setError(CancelError, "Request canceled."); + break; + default: + setError(CommunicationError, "Network error."); + } + return; + } + + QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + if (!document.isObject()) { + setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); + emit error(error(), errorString()); + return; + } + + QJsonObject object = document.object(); + + QJsonArray suggestions = object.value(QStringLiteral("suggestions")).toArray(); + + QStringList s; + for (int i = 0; i < suggestions.count(); ++i) { + QJsonValue v = suggestions.at(i); + if (v.isString()) + s.append(v.toString()); + } + + setSuggestions(s); + + m_reply->deleteLater(); + m_reply = 0; + + setFinished(true); + emit finished(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.h b/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.h new file mode 100644 index 0000000..dbcba3a --- /dev/null +++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESEARCHSUGGESTIONREPLYIMPL_H +#define QPLACESEARCHSUGGESTIONREPLYIMPL_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceSearchSuggestionReplyImpl : public QPlaceSearchSuggestionReply +{ + Q_OBJECT + +public: + explicit QPlaceSearchSuggestionReplyImpl(QNetworkReply *reply, QObject *parent = 0); + ~QPlaceSearchSuggestionReplyImpl(); + + void abort(); + +private slots: + void setError(QPlaceReply::Error error_, const QString &errorString); + void replyFinished(); + +private: + QNetworkReply *m_reply; +}; + +QT_END_NAMESPACE + +#endif // QPLACESEARCHSUGGESTIONREPLYIMPL_H diff --git a/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp b/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp new file mode 100644 index 0000000..73d2d4c --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocodereply_nokia.h" +#include "qgeocodexmlparser.h" +#include "qgeoerror_messages.h" + +#include +#include + +Q_DECLARE_METATYPE(QList) + +QT_BEGIN_NAMESPACE + +QGeoCodeReplyNokia::QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offset, + const QGeoShape &viewport, QObject *parent) +: QGeoCodeReply(parent), m_reply(reply), m_parsing(false) +{ + qRegisterMetaType >(); + + connect(m_reply, SIGNAL(finished()), this, SLOT(networkFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkError(QNetworkReply::NetworkError))); + + setLimit(limit); + setOffset(offset); + setViewport(viewport); +} + +QGeoCodeReplyNokia::~QGeoCodeReplyNokia() +{ + abort(); +} + +void QGeoCodeReplyNokia::abort() +{ + if (!m_reply) { + m_parsing = false; + return; + } + + m_reply->abort(); + + m_reply->deleteLater(); + m_reply = 0; + m_parsing = false; +} + +void QGeoCodeReplyNokia::networkFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() != QNetworkReply::NoError) + return; + + QGeoCodeXmlParser *parser = new QGeoCodeXmlParser; + parser->setBounds(viewport()); + connect(parser, SIGNAL(results(QList)), + this, SLOT(appendResults(QList))); + connect(parser, SIGNAL(error(QString)), this, SLOT(parseError(QString))); + + m_parsing = true; + parser->parse(m_reply->readAll()); + + m_reply->deleteLater(); + m_reply = 0; +} + +void QGeoCodeReplyNokia::networkError(QNetworkReply::NetworkError error) +{ + Q_UNUSED(error) + + if (!m_reply) + return; + + setError(QGeoCodeReply::CommunicationError, m_reply->errorString()); + + m_reply->deleteLater(); + m_reply = 0; +} + +void QGeoCodeReplyNokia::appendResults(const QList &locations) +{ + if (!m_parsing) + return; + + m_parsing = false; + setLocations(locations); + setFinished(true); +} + +void QGeoCodeReplyNokia::parseError(const QString &errorString) +{ + Q_UNUSED(errorString) + + setError(QGeoCodeReply::ParseError, + QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, RESPONSE_NOT_RECOGNIZABLE)); + abort(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeocodereply_nokia.h b/src/plugins/geoservices/nokia/qgeocodereply_nokia.h new file mode 100644 index 0000000..85726fc --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeocodereply_nokia.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODEREPLY_NOKIA_H +#define QGEOCODEREPLY_NOKIA_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCodeReplyNokia : public QGeoCodeReply +{ + Q_OBJECT +public: + QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offset, const QGeoShape &viewport, QObject *parent = 0); + ~QGeoCodeReplyNokia(); + + void abort(); + +private Q_SLOTS: + void networkFinished(); + void networkError(QNetworkReply::NetworkError error); + void appendResults(const QList &locations); + void parseError(const QString &errorString); + +private: + QNetworkReply *m_reply; + bool m_parsing; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp b/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp new file mode 100644 index 0000000..8973886 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp @@ -0,0 +1,573 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocodexmlparser.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoCodeXmlParser::QGeoCodeXmlParser() +{ +} + +QGeoCodeXmlParser::~QGeoCodeXmlParser() +{ +} + +void QGeoCodeXmlParser::setBounds(const QGeoShape &bounds) +{ + m_bounds = bounds; +} + +void QGeoCodeXmlParser::parse(const QByteArray &data) +{ + m_data = data; + QThreadPool::globalInstance()->start(this); +} + +void QGeoCodeXmlParser::run() +{ + m_reader = new QXmlStreamReader(m_data); + + if (!parseRootElement()) + emit error(m_reader->errorString()); + else + emit results(m_results); + + delete m_reader; + m_reader = 0; +} + +bool QGeoCodeXmlParser::parseRootElement() +{ + /* + + + + + + + + + + + + + + + + + + */ + + if (m_reader->readNextStartElement()) { + if (m_reader->name() == "places") { + if (m_reader->attributes().hasAttribute("resultCode")) { + QStringRef result = m_reader->attributes().value("resultCode"); + if (result == "FAILED") { + QString resultDesc = m_reader->attributes().value("resultDescription").toString(); + if (resultDesc.isEmpty()) + resultDesc = "The attribute \"resultCode\" of the element \"places\" indicates that the request failed."; + + m_reader->raiseError(resultDesc); + + return false; + } else if (result != "OK") { + m_reader->raiseError(QString("The attribute \"resultCode\" of the element \"places\" has an unknown value (value was %1).").arg(result.toString())); + return false; + } + } + + while (m_reader->readNextStartElement()) { + if (m_reader->name() == "place") { + QGeoLocation location; + + if (!parsePlace(&location)) + return false; + + if (!m_bounds.isValid() || m_bounds.contains(location.coordinate())) + m_results.append(location); + } else { + m_reader->raiseError(QString("The element \"places\" did not expect a child element named \"%1\".").arg(m_reader->name().toString())); + return false; + } + } + } else { + m_reader->raiseError(QString("The root element is expected to have the name \"places\" (root element was named \"%1\").").arg(m_reader->name().toString())); + return false; + } + } else { + m_reader->raiseError("Expected a root element named \"places\" (no root element found)."); + return false; + } + + if (m_reader->readNextStartElement()) { + m_reader->raiseError(QString("A single root element named \"places\" was expected (second root element was named \"%1\")").arg(m_reader->name().toString())); + return false; + } + + return true; +} + + +//Note: the term Place here is semi-confusing since +// the xml 'place' is actually a location ie coord + address +bool QGeoCodeXmlParser::parsePlace(QGeoLocation *location) +{ + /* + + + + + + + + + + + + + + + + */ + + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "place"); + + if (!m_reader->attributes().hasAttribute("title")) { + m_reader->raiseError("The element \"place\" did not have the required attribute \"title\"."); + return false; + } + + if (!m_reader->attributes().hasAttribute("language")) { + //m_reader->raiseError("The element \"place\" did not have the required attribute \"language\"."); + //return false; + } else { + QString lang = m_reader->attributes().value("language").toString(); + + if (lang.length() != 3) { + m_reader->raiseError(QString("The attribute \"language\" of the element \"place\" was not of length 3 (length was %1).").arg(lang.length())); + return false; + } + } + + bool parsedLocation = false; + bool parsedAddress = false; + bool parsedAlternatives = false; + + while (m_reader->readNextStartElement()) { + QString name = m_reader->name().toString(); + if (name == "location") { + if (parsedLocation) { + m_reader->raiseError("The element \"place\" has multiple child elements named \"location\" (exactly one expected)"); + return false; + } + + if (!parseLocation(location)) + return false; + + parsedLocation = true; + } else if (name == "address") { + if (parsedAddress) { + m_reader->raiseError("The element \"place\" has multiple child elements named \"address\" (at most one expected)"); + return false; + } + + QGeoAddress address; + if (!parseAddress(&address)) + return false; + else + location->setAddress(address); + + location->setAddress(address); + + parsedAddress = true; + } else if (name == "alternatives") { + if (parsedAlternatives) { + m_reader->raiseError("The element \"place\" has multiple child elements named \"alternatives\" (at most one expected)"); + return false; + } + + // skip alternatives for now + // need to work out if we have a use for them at all + // and how to store them if we get them + m_reader->skipCurrentElement(); + + parsedAlternatives = true; + } else { + m_reader->raiseError(QString("The element \"place\" did not expect a child element named \"%1\".").arg(m_reader->name().toString())); + return false; + } + } + + if (!parsedLocation) { + m_reader->raiseError("The element \"place\" has no child elements named \"location\" (exactly one expected)"); + return false; + } + + return true; +} + +//Note: the term Place here is semi-confusing since +// the xml 'location' is actually a parital location i.e coord +// as opposed to coord + address +bool QGeoCodeXmlParser::parseLocation(QGeoLocation *location) +{ + /* + + + + + + + + + + + + + + */ + + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "location"); + + bool parsedPosition = false; + bool parsedBounds = false; + + while (m_reader->readNextStartElement()) { + QString name = m_reader->name().toString(); + if (name == "position") { + if (parsedPosition) { + m_reader->raiseError("The element \"location\" has multiple child elements named \"position\" (exactly one expected)"); + return false; + } + + QGeoCoordinate coord; + if (!parseCoordinate(&coord, "position")) + return false; + + location->setCoordinate(coord); + + parsedPosition = true; + } else if (name == "boundingBox") { + if (parsedBounds) { + m_reader->raiseError("The element \"location\" has multiple child elements named \"boundingBox\" (at most one expected)"); + return false; + } + + QGeoRectangle bounds; + + if (!parseBoundingBox(&bounds)) + return false; + + location->setBoundingBox(bounds); + + parsedBounds = true; + } else { + m_reader->raiseError(QString("The element \"location\" did not expect a child element named \"%1\".").arg(m_reader->name().toString())); + return false; + } + } + + if (!parsedPosition) { + m_reader->raiseError("The element \"location\" has no child elements named \"position\" (exactly one expected)"); + return false; + } + + return true; +} + +bool QGeoCodeXmlParser::parseAddress(QGeoAddress *address) +{ + /* + + + + + + + + + + + + + + + + + + + + + + + + + + + */ + + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "address"); + + // currently ignoring the type of the address + + if (!m_reader->readNextStartElement()) + return true; + + if (m_reader->name() == "country") { + address->setCountry(m_reader->readElementText()); + if (!m_reader->readNextStartElement()) + return true; + } + + if (m_reader->name() == "countryCode") { + address->setCountryCode(m_reader->readElementText()); + + if (address->countryCode().length() != 3) { + m_reader->raiseError(QString("The text of the element \"countryCode\" was not of length 3 (length was %1).").arg(address->countryCode().length())); + return false; + } + + if (!m_reader->readNextStartElement()) + return true; + } + + if (m_reader->name() == "state") { + address->setState(m_reader->readElementText()); + if (!m_reader->readNextStartElement()) + return true; + } + + if (m_reader->name() == "county") { + address->setCounty(m_reader->readElementText()); + if (!m_reader->readNextStartElement()) + return true; + } + + if (m_reader->name() == "city") { + address->setCity(m_reader->readElementText()); + if (!m_reader->readNextStartElement()) + return true; + } + + if (m_reader->name() == "district") { + address->setDistrict(m_reader->readElementText()); + if (!m_reader->readNextStartElement()) + return true; + } + + bool inThoroughfare = false; + + if (m_reader->name() == "thoroughfare") { + inThoroughfare = m_reader->readNextStartElement(); + + if (inThoroughfare && (m_reader->name() == "name")) { + address->setStreet(m_reader->readElementText()); + if (!m_reader->readNextStartElement()) + inThoroughfare = false; + } + + if (inThoroughfare && (m_reader->name() == "number")) { + address->setStreet(m_reader->readElementText() + ' ' + address->street()); + if (!m_reader->readNextStartElement()) + inThoroughfare = false; + } + + if (inThoroughfare) { + m_reader->raiseError(QString("The element \"thoroughFare\" did not expect the child element \"%1\" at this point (unknown child element or child element out of order).").arg(m_reader->name().toString())); + return false; + } + + if (!m_reader->readNextStartElement()) + return true; + } + + if (m_reader->name() == "postCode") { + address->setPostalCode(m_reader->readElementText()); + if (!m_reader->readNextStartElement()) + return true; + } + + m_reader->raiseError(QString("The element \"address\" did not expect the child element \"%1\" at this point (unknown child element or child element out of order).").arg(m_reader->name().toString())); + return false; +} + +bool QGeoCodeXmlParser::parseBoundingBox(QGeoRectangle *bounds) +{ + /* + + + + + + + */ + + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "boundingBox"); + + if (!m_reader->readNextStartElement()) { + m_reader->raiseError("The element \"boundingBox\" was expected to have 2 child elements (0 found)"); + return false; + } + + QGeoCoordinate nw; + + if (m_reader->name() == "topLeft") { + if (!parseCoordinate(&nw, "topLeft")) + return false; + } else { + m_reader->raiseError(QString("The element \"boundingBox\" expected this child element to be named \"topLeft\" (found an element named \"%1\")").arg(m_reader->name().toString())); + return false; + } + + if (!m_reader->readNextStartElement()) { + m_reader->raiseError("The element \"boundingBox\" was expected to have 2 child elements (1 found)"); + return false; + } + + QGeoCoordinate se; + + if (m_reader->name() == "bottomRight") { + if (!parseCoordinate(&se, "bottomRight")) + return false; + } else { + m_reader->raiseError(QString("The element \"boundingBox\" expected this child element to be named \"bottomRight\" (found an element named \"%1\")").arg(m_reader->name().toString())); + return false; + } + + if (m_reader->readNextStartElement()) { + m_reader->raiseError("The element \"boundingBox\" was expected to have 2 child elements (more than 2 found)"); + return false; + } + + *bounds = QGeoRectangle(nw, se); + + return true; +} + +bool QGeoCodeXmlParser::parseCoordinate(QGeoCoordinate *coordinate, const QString &elementName) +{ + /* + + + + + + + + + + + + + + + + + + + + + */ + + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == elementName); + + if (!m_reader->readNextStartElement()) { + m_reader->raiseError(QString("The element \"%1\" was expected to have 2 child elements (0 found)").arg(elementName)); + return false; + } + + if (m_reader->name() == "latitude") { + bool ok = false; + QString s = m_reader->readElementText(); + double lat = s.toDouble(&ok); + + if (!ok) { + m_reader->raiseError(QString("The element \"latitude\" expected a value convertable to type float (value was \"%1\")").arg(s)); + return false; + } + + if (lat < -90.0 || 90.0 < lat) { + m_reader->raiseError(QString("The element \"latitude\" expected a value between -90.0 and 90.0 inclusive (value was %1)").arg(lat)); + return false; + } + + coordinate->setLatitude(lat); + } else { + m_reader->raiseError(QString("The element \"%1\" expected this child element to be named \"latitude\" (found an element named \"%2\")").arg(elementName).arg(m_reader->name().toString())); + } + + if (!m_reader->readNextStartElement()) { + m_reader->raiseError(QString("The element \"%1\" was expected to have 2 child elements (1 found)").arg(elementName)); + return false; + } + + if (m_reader->name() == "longitude") { + bool ok = false; + QString s = m_reader->readElementText(); + double lng = s.toDouble(&ok); + + if (!ok) { + m_reader->raiseError(QString("The element \"longitude\" expected a value convertable to type float (value was \"%1\")").arg(s)); + return false; + } + + if (lng < -180.0 || 180.0 < lng) { + m_reader->raiseError(QString("The element \"longitude\" expected a value between -180.0 and 180.0 inclusive (value was %1)").arg(lng)); + return false; + } + + coordinate->setLongitude(lng); + } else { + m_reader->raiseError(QString("The element \"%1\" expected this child element to be named \"longitude\" (found an element named \"%2\")").arg(elementName).arg(m_reader->name().toString())); + } + + if (m_reader->readNextStartElement()) { + m_reader->raiseError(QString("The element \"%1\" was expected to have 2 child elements (more than 2 found)").arg(elementName)); + return false; + } + + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeocodexmlparser.h b/src/plugins/geoservices/nokia/qgeocodexmlparser.h new file mode 100644 index 0000000..83a4b59 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeocodexmlparser.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODEXMLPARSER_H +#define QGEOCODEXMLPARSER_H + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoLocation; +class QGeoAddress; +class QGeoRectangle; +class QGeoCoordinate; +class QXmlStreamReader; + +class QGeoCodeXmlParser : public QObject, public QRunnable +{ + Q_OBJECT + +public: + QGeoCodeXmlParser(); + ~QGeoCodeXmlParser(); + + void setBounds(const QGeoShape &bounds); + void parse(const QByteArray &data); + void run(); + +signals: + void results(const QList &locations); + void error(const QString &errorString); + +private: + bool parseRootElement(); + bool parsePlace(QGeoLocation *location); + bool parseLocation(QGeoLocation *location); + bool parseAddress(QGeoAddress *address); + bool parseBoundingBox(QGeoRectangle *bounds); + bool parseCoordinate(QGeoCoordinate *coordinate, const QString &elementName); + + QGeoShape m_bounds; + QByteArray m_data; + QXmlStreamReader *m_reader; + + QList m_results; + QString m_errorString; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp new file mode 100644 index 0000000..2e0eae4 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp @@ -0,0 +1,295 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocodingmanagerengine_nokia.h" +#include "qgeocodereply_nokia.h" +#include "marclanguagecodes.h" +#include "qgeonetworkaccessmanager.h" +#include "qgeouriprovider.h" +#include "uri_constants.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoCodingManagerEngineNokia::QGeoCodingManagerEngineNokia( + QGeoNetworkAccessManager *networkManager, + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) + : QGeoCodingManagerEngine(parameters) + , m_networkManager(networkManager) + , m_uriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.geocoding.host"), GEOCODING_HOST, GEOCODING_HOST_CN)) +{ + Q_ASSERT(networkManager); + m_networkManager->setParent(this); + + if (parameters.contains(QStringLiteral("here.token"))) + m_token = parameters.value(QStringLiteral("here.token")).toString(); + + if (parameters.contains(QStringLiteral("here.app_id"))) + m_applicationId = parameters.value(QStringLiteral("here.app_id")).toString(); + + if (error) + *error = QGeoServiceProvider::NoError; + + if (errorString) + *errorString = ""; +} + +QGeoCodingManagerEngineNokia::~QGeoCodingManagerEngineNokia() {} + +QString QGeoCodingManagerEngineNokia::getAuthenticationString() const +{ + QString authenticationString; + + if (!m_token.isEmpty() && !m_applicationId.isEmpty()) { + authenticationString += "?token="; + authenticationString += m_token; + + authenticationString += "&app_id="; + authenticationString += m_applicationId; + } + + return authenticationString; +} + + +QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(const QGeoAddress &address, + const QGeoShape &bounds) +{ + QString requestString = "http://"; + requestString += m_uriProvider->getCurrentHost(); + requestString += "/geocoder/gc/2.0"; + + requestString += getAuthenticationString(); + + requestString += "&lg="; + requestString += languageToMarc(locale().language()); + + if (address.country().isEmpty()) { + QStringList parts; + + if (!address.state().isEmpty()) + parts << address.state(); + + if (!address.city().isEmpty()) + parts << address.city(); + + if (!address.postalCode().isEmpty()) + parts << address.postalCode(); + + if (!address.street().isEmpty()) + parts << address.street(); + + requestString += "&obloc="; + requestString += parts.join(" "); + } else { + requestString += "&country="; + requestString += address.country(); + + if (!address.state().isEmpty()) { + requestString += "&state="; + requestString += address.state(); + } + + if (!address.city().isEmpty()) { + requestString += "&city="; + requestString += address.city(); + } + + if (!address.postalCode().isEmpty()) { + requestString += "&zip="; + requestString += address.postalCode(); + } + + if (!address.street().isEmpty()) { + requestString += "&street="; + requestString += address.street(); + } + } + + + // TODO? + // street number has been removed from QGeoAddress + // do we need to try to split it out from QGeoAddress::street + // in order to geocode properly + + // Old code: +// if (!address.streetNumber().isEmpty()) { +// requestString += "&number="; +// requestString += address.streetNumber(); +// } + + return geocode(requestString, bounds); +} + +QGeoCodeReply *QGeoCodingManagerEngineNokia::reverseGeocode(const QGeoCoordinate &coordinate, + const QGeoShape &bounds) +{ + QString requestString = "http://"; + requestString += m_uriProvider->getCurrentHost(); + requestString += "/geocoder/rgc/2.0"; + + requestString += getAuthenticationString(); + + requestString += "&long="; + requestString += trimDouble(coordinate.longitude()); + requestString += "&lat="; + requestString += trimDouble(coordinate.latitude()); + + requestString += "&lg="; + requestString += languageToMarc(locale().language()); + + return geocode(requestString, bounds); +} + +QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(const QString &address, + int limit, + int offset, + const QGeoShape &bounds) +{ + QString requestString = "http://"; + requestString += m_uriProvider->getCurrentHost(); + requestString += "/geocoder/gc/2.0"; + + requestString += getAuthenticationString(); + + requestString += "&lg="; + requestString += languageToMarc(locale().language()); + + requestString += "&obloc="; + requestString += address; + + if (limit > 0) { + requestString += "&total="; + requestString += QString::number(limit); + } + + if (offset > 0) { + requestString += "&offset="; + requestString += QString::number(offset); + } + + return geocode(requestString, bounds, limit, offset); +} + +QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(QString requestString, + const QGeoShape &bounds, + int limit, + int offset) +{ + QNetworkReply *networkReply = m_networkManager->get(QNetworkRequest(QUrl(requestString))); + QGeoCodeReplyNokia *reply = new QGeoCodeReplyNokia(networkReply, limit, offset, bounds, this); + + connect(reply, + SIGNAL(finished()), + this, + SLOT(placesFinished())); + + connect(reply, + SIGNAL(error(QGeoCodeReply::Error,QString)), + this, + SLOT(placesError(QGeoCodeReply::Error,QString))); + + return reply; +} + +QString QGeoCodingManagerEngineNokia::trimDouble(double degree, int decimalDigits) +{ + QString sDegree = QString::number(degree, 'g', decimalDigits); + + int index = sDegree.indexOf('.'); + + if (index == -1) + return sDegree; + else + return QString::number(degree, 'g', decimalDigits + index); +} + +void QGeoCodingManagerEngineNokia::placesFinished() +{ + QGeoCodeReply *reply = qobject_cast(sender()); + + if (!reply) + return; + + if (receivers(SIGNAL(finished(QGeoCodeReply*))) == 0) { + reply->deleteLater(); + return; + } + + emit finished(reply); +} + +void QGeoCodingManagerEngineNokia::placesError(QGeoCodeReply::Error error, const QString &errorString) +{ + QGeoCodeReply *reply = qobject_cast(sender()); + + if (!reply) + return; + + if (receivers(SIGNAL(error(QGeoCodeReply*,QGeoCodeReply::Error,QString))) == 0) { + reply->deleteLater(); + return; + } + + emit this->error(reply, error, errorString); +} + +QString QGeoCodingManagerEngineNokia::languageToMarc(QLocale::Language language) +{ + uint offset = 3 * (uint(language)); + if (language == QLocale::C || offset + 3 > sizeof(marc_language_code_list)) + return QLatin1String("eng"); + + const unsigned char *c = marc_language_code_list + offset; + if (c[0] == 0) + return QLatin1String("eng"); + + QString code(3, Qt::Uninitialized); + code[0] = ushort(c[0]); + code[1] = ushort(c[1]); + code[2] = ushort(c[2]); + + return code; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h new file mode 100644 index 0000000..baa9190 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODINGMANAGER_NOKIA_H +#define QGEOCODINGMANAGER_NOKIA_H + +#include "qgeoserviceproviderplugin_nokia.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoNetworkAccessManager; +class QGeoUriProvider; + +class QGeoCodingManagerEngineNokia : public QGeoCodingManagerEngine +{ + Q_OBJECT +public: + QGeoCodingManagerEngineNokia(QGeoNetworkAccessManager *networkManager, + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString); + ~QGeoCodingManagerEngineNokia(); + + QGeoCodeReply *geocode(const QGeoAddress &address, + const QGeoShape &bounds); + QGeoCodeReply *reverseGeocode(const QGeoCoordinate &coordinate, + const QGeoShape &bounds); + + QGeoCodeReply *geocode(const QString &searchString, + int limit, + int offset, + const QGeoShape &bounds); + +private Q_SLOTS: + void placesFinished(); + void placesError(QGeoCodeReply::Error error, const QString &errorString); + +private: + static QString trimDouble(double degree, int decimalDigits = 10); + QGeoCodeReply *geocode(QString requestString, const QGeoShape &bounds, int limit = -1, int offset = 0); + QString languageToMarc(QLocale::Language language); + QString getAuthenticationString() const; + + QGeoNetworkAccessManager *m_networkManager; + QString m_token; + QString m_applicationId; + QGeoUriProvider *m_uriProvider; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/qgeoerror_messages.cpp b/src/plugins/geoservices/nokia/qgeoerror_messages.cpp new file mode 100644 index 0000000..576ecd4 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoerror_messages.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoerror_messages.h" + +QT_BEGIN_NAMESPACE + +const char NOKIA_PLUGIN_CONTEXT_NAME[] = "QtLocationQML"; +const char MISSED_CREDENTIALS[] = QT_TRANSLATE_NOOP("QtLocationQML", "Qt Location requires app_id and token parameters.\nPlease register at https://developer.here.com/ to get your personal application credentials."); +const char SAVING_PLACE_NOT_SUPPORTED[] = QT_TRANSLATE_NOOP("QtLocationQML", "Saving places is not supported."); +const char REMOVING_PLACE_NOT_SUPPORTED[] = QT_TRANSLATE_NOOP("QtLocationQML", "Removing places is not supported."); +const char SAVING_CATEGORY_NOT_SUPPORTED[] = QT_TRANSLATE_NOOP("QtLocationQML", "Saving categories is not supported."); +const char REMOVING_CATEGORY_NOT_SUPPORTED[] = QT_TRANSLATE_NOOP("QtLocationQML", "Removing categories is not supported."); +const char PARSE_ERROR[] = QT_TRANSLATE_NOOP("QtLocationQML", "Error parsing response."); +const char NETWORK_ERROR[] = QT_TRANSLATE_NOOP("QtLocationQML", "Network error."); +const char CANCEL_ERROR[] = QT_TRANSLATE_NOOP("QtLocationQML", "Request was canceled."); +const char RESPONSE_NOT_RECOGNIZABLE[] = QT_TRANSLATE_NOOP("QtLocationQML", "The response from the service was not in a recognizable format."); + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeoerror_messages.h b/src/plugins/geoservices/nokia/qgeoerror_messages.h new file mode 100644 index 0000000..8bae1f2 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoerror_messages.h @@ -0,0 +1,58 @@ + +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOERROR_MESSAGES_H +#define QGEOERROR_MESSAGES_H + +#include + +QT_BEGIN_NAMESPACE + +extern const char NOKIA_PLUGIN_CONTEXT_NAME[]; +extern const char MISSED_CREDENTIALS[]; +extern const char SAVING_PLACE_NOT_SUPPORTED[]; +extern const char REMOVING_PLACE_NOT_SUPPORTED[]; +extern const char SAVING_CATEGORY_NOT_SUPPORTED[]; +extern const char REMOVING_CATEGORY_NOT_SUPPORTED[]; +extern const char PARSE_ERROR[]; +extern const char NETWORK_ERROR[]; +extern const char CANCEL_ERROR[]; +extern const char RESPONSE_NOT_RECOGNIZABLE[]; + +QT_END_NAMESPACE + +#endif // QGEOERROR_MESSAGES_H diff --git a/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.cpp b/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.cpp new file mode 100644 index 0000000..267c4ca --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeointrinsicnetworkaccessmanager.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoIntrinsicNetworkAccessManager::QGeoIntrinsicNetworkAccessManager(QObject *parent) +: QGeoNetworkAccessManager(parent) +, m_networkManager(new QNetworkAccessManager(this)) +{ +} + +QGeoIntrinsicNetworkAccessManager::QGeoIntrinsicNetworkAccessManager(const QVariantMap ¶meters, const QString &token, QObject *parent) +: QGeoNetworkAccessManager(parent) +, m_customProxyToken(token) +, m_networkManager(new QNetworkAccessManager(this)) +{ + configure(parameters); +} + +void QGeoIntrinsicNetworkAccessManager::configure(const QVariantMap ¶meters) +{ + QString proxy = parameters.value(QStringLiteral("here.proxy")).toString(); + if (proxy.isEmpty() && !m_customProxyToken.isEmpty()) + proxy = parameters.value(m_customProxyToken).toString(); + + if (!proxy.isEmpty()) { +#ifndef QT_NO_NETWORKPROXY + if (proxy.toLower() != QStringLiteral("system")) { + QUrl proxyUrl(proxy); + if (proxyUrl.isValid()) { + qDebug() << "Setting proxy to " << proxyUrl.toString(); + m_networkManager->setProxy( + QNetworkProxy(QNetworkProxy::HttpProxy, + proxyUrl.host(), + proxyUrl.port(8080), + proxyUrl.userName(), + proxyUrl.password())); + } + } else if (QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy) { + QNetworkProxyFactory::setUseSystemConfiguration(true); + qDebug() << "Setting system proxy."; + } +#else + qDebug() << "No proxy support"; +#endif + } else { + qDebug() << "No proxy parameter specified."; + } +} + +QNetworkReply *QGeoIntrinsicNetworkAccessManager::get(const QNetworkRequest &request) +{ + return m_networkManager->get(request); +} + +QNetworkReply *QGeoIntrinsicNetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data) +{ + return m_networkManager->post(request, data); +} +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.h b/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.h new file mode 100644 index 0000000..fb5ab48 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOINTRINSICNETWORKACCESSMANAGER_H +#define QGEOINTRINSICNETWORKACCESSMANAGER_H + +#include "qgeonetworkaccessmanager.h" + +#include + +QT_BEGIN_NAMESPACE + +class QNetworkAccessManager; + +class QGeoIntrinsicNetworkAccessManager : public QGeoNetworkAccessManager +{ +public: + explicit QGeoIntrinsicNetworkAccessManager(QObject *parent = 0); + QGeoIntrinsicNetworkAccessManager(const QVariantMap ¶meters, const QString &token = QString(), QObject *parent = 0); + + virtual QNetworkReply *get(const QNetworkRequest &request); + virtual QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data); + +private: + void configure(const QVariantMap ¶meters); + + const QString m_customProxyToken; + QNetworkAccessManager *m_networkManager; +}; + +QT_END_NAMESPACE + +#endif // QGEOINTRINSICNETWORKACCESSMANAGER_H diff --git a/src/plugins/geoservices/nokia/qgeomapreply_nokia.cpp b/src/plugins/geoservices/nokia/qgeomapreply_nokia.cpp new file mode 100644 index 0000000..c95f8de --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeomapreply_nokia.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomapreply_nokia.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoMapReplyNokia::QGeoMapReplyNokia(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent) + : QGeoTiledMapReply(spec, parent), + m_reply(reply) +{ + connect(m_reply, + SIGNAL(finished()), + this, + SLOT(networkFinished())); + + connect(m_reply, + SIGNAL(error(QNetworkReply::NetworkError)), + this, + SLOT(networkError(QNetworkReply::NetworkError))); +} + +QGeoMapReplyNokia::~QGeoMapReplyNokia() +{ +} + +QNetworkReply *QGeoMapReplyNokia::networkReply() const +{ + return m_reply; +} + +void QGeoMapReplyNokia::abort() +{ + if (!m_reply) + return; + + m_reply->abort(); +} + +void QGeoMapReplyNokia::networkFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() != QNetworkReply::NoError) + return; + + setMapImageData(m_reply->readAll()); + setMapImageFormat("png"); + setFinished(true); + + m_reply->deleteLater(); + m_reply = 0; +} + +void QGeoMapReplyNokia::networkError(QNetworkReply::NetworkError error) +{ + if (!m_reply) + return; + + if (error != QNetworkReply::OperationCanceledError) + setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); + setFinished(true); + m_reply->deleteLater(); + m_reply = 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeomapreply_nokia.h b/src/plugins/geoservices/nokia/qgeomapreply_nokia.h new file mode 100644 index 0000000..5575991 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeomapreply_nokia.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPREPLY_NOKIA_H +#define QGEOMAPREPLY_NOKIA_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMapReplyNokia : public QGeoTiledMapReply +{ + Q_OBJECT + +public: + QGeoMapReplyNokia(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent = 0); + ~QGeoMapReplyNokia(); + + void abort(); + + QNetworkReply *networkReply() const; + +private Q_SLOTS: + void networkFinished(); + void networkError(QNetworkReply::NetworkError error); + +private: + QPointer m_reply; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/qgeomapversion.cpp b/src/plugins/geoservices/nokia/qgeomapversion.cpp new file mode 100644 index 0000000..4432762 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeomapversion.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Appello Systems AB. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomapversion.h" + +#include + +QT_BEGIN_NAMESPACE + +QGeoMapVersion::QGeoMapVersion() + : m_version(-1) {} + +bool QGeoMapVersion::isNewVersion(const QJsonObject &newVersionData) +{ + return m_versionData != newVersionData; +} + +int QGeoMapVersion::version() const +{ + return m_version; +} + +void QGeoMapVersion::setVersion(int version) +{ + m_version = version; +} + +void QGeoMapVersion::setVersionData(const QJsonObject &versionData) +{ + m_versionData = versionData; +} + + +QByteArray QGeoMapVersion::toJson() const +{ + + QJsonObject object; + object[QLatin1String("version")] = m_version; + object[QLatin1String("data")] = m_versionData; + + QJsonDocument document(object); + + return document.toJson(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeomapversion.h b/src/plugins/geoservices/nokia/qgeomapversion.h new file mode 100644 index 0000000..0e602e6 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeomapversion.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Appello Systems AB. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPVERSION_H +#define QGEOMAPVERSION_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMapVersion +{ + +public: + QGeoMapVersion(); + bool isNewVersion(const QJsonObject &newVersionData); + int version() const; + void setVersion(const int); + void setVersionData(const QJsonObject &versionData); + QByteArray toJson() const; + +private: + int m_version; + QJsonObject m_versionData; +}; + +QT_END_NAMESPACE + +#endif // QGEOMAPVERSION_H diff --git a/src/plugins/geoservices/nokia/qgeonetworkaccessmanager.h b/src/plugins/geoservices/nokia/qgeonetworkaccessmanager.h new file mode 100644 index 0000000..541f00c --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeonetworkaccessmanager.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEONETWORKACCESSMANAGER_H +#define QGEONETWORKACCESSMANAGER_H + +#include + +QT_BEGIN_NAMESPACE + +class QNetworkReply; +class QNetworkRequest; +class QByteArray; + +class QGeoNetworkAccessManager : public QObject +{ + Q_OBJECT +public: + virtual ~QGeoNetworkAccessManager() {} + virtual QNetworkReply *get(const QNetworkRequest &request) = 0; + virtual QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data) = 0; + +protected: + QGeoNetworkAccessManager(QObject *parent) : QObject(parent) {} +}; + +QT_END_NAMESPACE + +#endif // QGEONETWORKACCESSMANAGER_H diff --git a/src/plugins/geoservices/nokia/qgeoroutereply_nokia.cpp b/src/plugins/geoservices/nokia/qgeoroutereply_nokia.cpp new file mode 100644 index 0000000..45ea071 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoroutereply_nokia.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroutereply_nokia.h" +#include "qgeoroutexmlparser.h" +#include "qgeoerror_messages.h" + +#include + +#include + +Q_DECLARE_METATYPE(QList) + +QT_BEGIN_NAMESPACE + +QGeoRouteReplyNokia::QGeoRouteReplyNokia(const QGeoRouteRequest &request, + const QList &replies, + QObject *parent) +: QGeoRouteReply(request, parent), m_replies(replies), m_parsers(0) +{ + qRegisterMetaType >(); + + foreach (QNetworkReply *reply, m_replies) { + connect(reply, SIGNAL(finished()), this, SLOT(networkFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkError(QNetworkReply::NetworkError))); + } +} + +QGeoRouteReplyNokia::~QGeoRouteReplyNokia() +{ + abort(); +} + +void QGeoRouteReplyNokia::abort() +{ + if (m_replies.isEmpty() && !m_parsers) + return; + + foreach (QNetworkReply *reply, m_replies) { + reply->abort(); + reply->deleteLater(); + } + m_replies.clear(); + m_parsers = 0; +} + +void QGeoRouteReplyNokia::networkFinished() +{ + QNetworkReply *reply = qobject_cast(sender()); + if (!reply) + return; + + if (reply->error() != QNetworkReply::NoError) + return; + + QGeoRouteXmlParser *parser = new QGeoRouteXmlParser(request()); + connect(parser, SIGNAL(results(QList)), + this, SLOT(appendResults(QList))); + connect(parser, SIGNAL(error(QString)), this, SLOT(parserError(QString))); + + ++m_parsers; + parser->parse(reply->readAll()); + + m_replies.removeOne(reply); + reply->deleteLater(); +} + +void QGeoRouteReplyNokia::networkError(QNetworkReply::NetworkError error) +{ + QNetworkReply *reply = qobject_cast(sender()); + if (!reply) + return; + + if (error == QNetworkReply::UnknownContentError) { + QGeoRouteXmlParser *parser = new QGeoRouteXmlParser(request()); + connect(parser, SIGNAL(results(QList)), + this, SLOT(appendResults(QList))); + connect(parser, SIGNAL(error(QString)), this, SLOT(parserError(QString))); + + ++m_parsers; + parser->parse(reply->readAll()); + + m_replies.removeOne(reply); + reply->deleteLater(); + } else { + setError(QGeoRouteReply::CommunicationError, reply->errorString()); + abort(); + } +} + +void QGeoRouteReplyNokia::appendResults(const QList &routes) +{ + if (!m_parsers) + return; + + --m_parsers; + addRoutes(routes); + + if (!m_parsers && m_replies.isEmpty()) + setFinished(true); +} + +void QGeoRouteReplyNokia::parserError(const QString &errorString) +{ + Q_UNUSED(errorString) + + --m_parsers; + + setError(QGeoRouteReply::ParseError, + QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, RESPONSE_NOT_RECOGNIZABLE)); + abort(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeoroutereply_nokia.h b/src/plugins/geoservices/nokia/qgeoroutereply_nokia.h new file mode 100644 index 0000000..9d32bdb --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoroutereply_nokia.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTEREPLY_NOKIA_H +#define QGEOROUTEREPLY_NOKIA_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRouteXmlParser; + +class QGeoRouteReplyNokia : public QGeoRouteReply +{ + Q_OBJECT +public: + QGeoRouteReplyNokia(const QGeoRouteRequest &request, const QList &replies, QObject *parent = 0); + ~QGeoRouteReplyNokia(); + + void abort(); + +private Q_SLOTS: + void networkFinished(); + void networkError(QNetworkReply::NetworkError error); + void appendResults(const QList &routes); + void parserError(const QString &errorString); + +private: + QList m_replies; + int m_parsers; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/qgeoroutexmlparser.cpp b/src/plugins/geoservices/nokia/qgeoroutexmlparser.cpp new file mode 100644 index 0000000..8e436a9 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoroutexmlparser.cpp @@ -0,0 +1,605 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroutexmlparser.h" + +#include +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoDynamicSpeedInfoContainer::QGeoDynamicSpeedInfoContainer() +: trafficSpeed(0) +, baseSpeed(0) +, trafficTime(0) +, baseTime(0) +{} + +QGeoRouteXmlParser::QGeoRouteXmlParser(const QGeoRouteRequest &request) + : m_request(request) +{ +} + +QGeoRouteXmlParser::~QGeoRouteXmlParser() +{ +} + +void QGeoRouteXmlParser::parse(const QByteArray &data) +{ + m_data = data; + QThreadPool::globalInstance()->start(this); +} + +void QGeoRouteXmlParser::run() +{ + m_reader = new QXmlStreamReader(m_data); + + if (!parseRootElement()) + emit error(m_reader->errorString()); + else + emit results(m_results); + + delete m_reader; + m_reader = 0; +} + +bool QGeoRouteXmlParser::parseRootElement() +{ + if (!m_reader->readNextStartElement()) { + m_reader->raiseError("Expected a root element named \"CalculateRoute\" (no root element found)."); + return false; + } + + if (m_reader->name() == QLatin1String("Error")) { + QXmlStreamAttributes attributes = m_reader->attributes(); + if (attributes.value(QStringLiteral("type")) == QLatin1String("ApplicationError") + && attributes.value("subtype") == QLatin1String("NoRouteFound")) + return true; + } + + bool updateroute = false; + if (m_reader->name() != "CalculateRoute" && m_reader->name() != "GetRoute") { + m_reader->raiseError(QString("The root element is expected to have the name \"CalculateRoute\" or \"GetRoute\" (root element was named \"%1\").").arg(m_reader->name().toString())); + return false; + } else if (m_reader->name() == "GetRoute") { + updateroute = true; + } + + if (m_reader->readNextStartElement()) { + if (m_reader->name() != "Response") { + m_reader->raiseError(QString("Expected a element named \"Response\" (element was named \"%1\").").arg(m_reader->name().toString())); + return false; + } + } + + while (m_reader->readNextStartElement() && !m_reader->hasError()) { + if (m_reader->name() == "Route") { + QGeoRoute route; + route.setRequest(m_request); + if (updateroute) + route.setTravelMode(QGeoRouteRequest::TravelMode(int(m_request.travelModes()))); + if (!parseRoute(&route)) + continue; //route parsing failed move on to the next + m_results.append(route); + } else if (m_reader->name() == "Progress") { + //TODO: updated route progress + m_reader->skipCurrentElement(); + } else { + m_reader->skipCurrentElement(); + } + } + + return !m_reader->hasError(); +} + +bool QGeoRouteXmlParser::parseRoute(QGeoRoute *route) +{ + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Route"); + m_maneuvers.clear(); + m_segments.clear(); + + m_reader->readNext(); + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Route") && + !m_reader->hasError()) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + if (m_reader->name() == "RouteId") { + route->setRouteId(m_reader->readElementText()); + } + //else if (m_reader->name() == "Waypoint") { + // succeeded = parseWaypoint(route); + //} + else if (m_reader->name() == "Mode") { + if (!parseMode(route)) + return false; + } else if (m_reader->name() == "Shape") { + QString elementName = m_reader->name().toString(); + QList path; + if (!parseGeoPoints(m_reader->readElementText(), &path, elementName)) + return false; + route->setPath(path); + } else if (m_reader->name() == "BoundingBox") { + QGeoRectangle bounds; + if (!parseBoundingBox(bounds)) + return false; + route->setBounds(bounds); + } else if (m_reader->name() == "Leg") { + if (!parseLeg()) + return false; + } else if (m_reader->name() == "Summary") { + if (!parseSummary(route)) + return false; + } else { + m_reader->skipCurrentElement(); + } + } + m_reader->readNext(); + } + + if (m_reader->hasError()) + return false; + + return postProcessRoute(route); +} + +bool QGeoRouteXmlParser::parseLeg() +{ + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Leg"); + + m_reader->readNext(); + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Leg") && + !m_reader->hasError()) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + if (m_reader->name() == "Maneuver") { + if (!parseManeuver()) + return false; + } else if (m_reader->name() == "Link") { + if (!parseLink()) + return false; + } else { + m_reader->skipCurrentElement(); + } + } + m_reader->readNext(); + } + + return !m_reader->hasError(); +} + +bool QGeoRouteXmlParser::postProcessRoute(QGeoRoute *route) +{ + QList routeSegments; + + int maneuverIndex = 0; + for (int i = 0; i < m_segments.count(); ++i) { + // In case there is a maneuver in the middle of the list with no + // link ID attached, attach it to the next available segment + while ((maneuverIndex < m_maneuvers.size() - 1) && m_maneuvers.at(maneuverIndex).toId.isEmpty()) { + QGeoRouteSegment segment; + segment.setManeuver(m_maneuvers.at(maneuverIndex).maneuver); + QList path; // use instruction position as one point segment path + path.append(m_maneuvers.at(maneuverIndex).maneuver.position()); + segment.setPath(path); + routeSegments.append(segment); + ++maneuverIndex; + } + + QGeoRouteSegment segment = m_segments.at(i).segment; + if ((maneuverIndex < m_maneuvers.size()) && m_segments.at(i).id == m_maneuvers.at(maneuverIndex).toId) { + segment.setManeuver(m_maneuvers.at(maneuverIndex).maneuver); + ++maneuverIndex; + } + routeSegments.append(segment); + } + + // For the final maneuver in the list, make sure to attach it to the very + // last segment on the path, this is why we don't process the last + // maneuver in the loop above + while (maneuverIndex < m_maneuvers.size()) { + QGeoRouteSegment segment; + segment.setManeuver(m_maneuvers.at(maneuverIndex).maneuver); + QList path; // use instruction position as one point segment path + path.append(m_maneuvers.at(maneuverIndex).maneuver.position()); + segment.setPath(path); + + routeSegments.append(segment); + ++maneuverIndex; + } + + QList compactedRouteSegments; + compactedRouteSegments.append(routeSegments.first()); + routeSegments.removeFirst(); + + while (routeSegments.size() > 0) { + QGeoRouteSegment segment = routeSegments.first(); + routeSegments.removeFirst(); + + QGeoRouteSegment lastSegment = compactedRouteSegments.last(); + + if (lastSegment.maneuver().isValid()) { + compactedRouteSegments.append(segment); + } else { + compactedRouteSegments.removeLast(); + lastSegment.setDistance(lastSegment.distance() + segment.distance()); + lastSegment.setTravelTime(lastSegment.travelTime() + segment.travelTime()); + QList path = lastSegment.path(); + path.append(segment.path()); + lastSegment.setPath(path); + lastSegment.setManeuver(segment.maneuver()); + compactedRouteSegments.append(lastSegment); + } + } + + if (compactedRouteSegments.size() > 0) { + route->setFirstRouteSegment(compactedRouteSegments.at(0)); + for (int i = 0; i < compactedRouteSegments.size() - 1; ++i) + compactedRouteSegments[i].setNextRouteSegment(compactedRouteSegments.at(i + 1)); + } + + m_maneuvers.clear(); + m_segments.clear(); + return true; +} + +/* +bool QGeoRouteXmlParser::parseWaypoint(QGeoRoute *route) +{ + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Waypoint"); + m_reader->readNext(); + QList path(route->pathSummary()); + + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Waypoint")) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + if (m_reader->name() == "MappedPosition") { + QGeoCoordinate coordinates; + if(!parseCoordinates(coordinates)) + return false; + path.append(coordinates); + } + else { + m_reader->skipCurrentElement(); + } + } + m_reader->readNext(); + } + route->setPathSummary(path); + return true; +} +*/ + +bool QGeoRouteXmlParser::parseMode(QGeoRoute *route) +{ + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Mode"); + m_reader->readNext(); + + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Mode") && + !m_reader->hasError()) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + if (m_reader->name() == "TransportModes") { + QString value = m_reader->readElementText(); + if (value == "car") + route->setTravelMode(QGeoRouteRequest::CarTravel); + else if (value == "pedestrian") + route->setTravelMode(QGeoRouteRequest::PedestrianTravel); + else if (value == "publicTransport") + route->setTravelMode(QGeoRouteRequest::PublicTransitTravel); + else if (value == "bicycle") + route->setTravelMode(QGeoRouteRequest::BicycleTravel); + else if (value == "truck") + route->setTravelMode(QGeoRouteRequest::TruckTravel); + else { + // unsupported mode + m_reader->raiseError(QString("Unsupported travel mode '\"%1\"'").arg(value)); + return false; + } + } else { + m_reader->skipCurrentElement(); + } + } + m_reader->readNext(); + } + return !m_reader->hasError(); +} + +bool QGeoRouteXmlParser::parseSummary(QGeoRoute *route) +{ + Q_ASSERT(route); + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Summary"); + m_reader->readNext(); + + double baseTime = -1, trafficTime = -1; + + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Summary") && + !m_reader->hasError()) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + if (m_reader->name() == "Distance") { + route->setDistance(m_reader->readElementText().toDouble()); + } else if (m_reader->name() == "TrafficTime") { + trafficTime = m_reader->readElementText().toDouble(); + } else if (m_reader->name() == "BaseTime") { + baseTime = m_reader->readElementText().toDouble(); + } else { + m_reader->skipCurrentElement(); + } + } + m_reader->readNext(); + } + + if (m_reader->hasError()) + return false; + + if (trafficTime >= 0) + route->setTravelTime(trafficTime); + else if (baseTime >= 0) + route->setTravelTime(baseTime); + + return true; +} + +bool QGeoRouteXmlParser::parseCoordinates(QGeoCoordinate &coord) +{ + QString currentElement = m_reader->name().toString(); + m_reader->readNext(); + + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == currentElement) && + !m_reader->hasError()) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + QString name = m_reader->name().toString(); + QString value = m_reader->readElementText(); + if (name == "Latitude") + coord.setLatitude(value.toDouble()); + else if (name == "Longitude") + coord.setLongitude(value.toDouble()); + } + m_reader->readNext(); + } + + return !m_reader->hasError(); +} + +bool QGeoRouteXmlParser::parseManeuver() +{ + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Maneuver"); + + if (!m_reader->attributes().hasAttribute("id")) { + m_reader->raiseError("The element \"Maneuver\" did not have the required attribute \"id\"."); + return false; + } + QGeoManeuverContainer maneuverContainter; + maneuverContainter.id = m_reader->attributes().value("id").toString(); + + m_reader->readNext(); + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Maneuver") && + !m_reader->hasError()) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + if (m_reader->name() == "Position") { + QGeoCoordinate coordinates; + if (parseCoordinates(coordinates)) + maneuverContainter.maneuver.setPosition(coordinates); + } else if (m_reader->name() == "Instruction") { + maneuverContainter.maneuver.setInstructionText(m_reader->readElementText()); + } else if (m_reader->name() == "ToLink") { + maneuverContainter.toId = m_reader->readElementText(); + } else if (m_reader->name() == "TravelTime") { + maneuverContainter.maneuver.setTimeToNextInstruction(qRound(m_reader->readElementText().toDouble())); + } else if (m_reader->name() == "Length") { + maneuverContainter.maneuver.setDistanceToNextInstruction(m_reader->readElementText().toDouble()); + } else if (m_reader->name() == "Direction") { + QString value = m_reader->readElementText(); + if (value == "forward") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionForward); + else if (value == "bearRight") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionBearRight); + else if (value == "lightRight") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLightRight); + else if (value == "right") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionRight); + else if (value == "hardRight") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionHardRight); + else if (value == "uTurnRight") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionUTurnRight); + else if (value == "uTurnLeft") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionUTurnLeft); + else if (value == "hardLeft") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionHardLeft); + else if (value == "left") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLeft); + else if (value == "lightLeft") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLightLeft); + else if (value == "bearLeft") + maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionBearLeft); + else + maneuverContainter.maneuver.setDirection(QGeoManeuver::NoDirection); + } else { + m_reader->skipCurrentElement(); + } + } + m_reader->readNext(); + } + + if (m_reader->hasError()) + return false; + + m_maneuvers.append(maneuverContainter); + return true; +} + +bool QGeoRouteXmlParser::parseLink() +{ + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral("Link")); + m_reader->readNext(); + + QGeoRouteSegmentContainer segmentContainer; + + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == QStringLiteral("Link")) && + !m_reader->hasError()) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + if (m_reader->name() == QStringLiteral("LinkId")) { + segmentContainer.id = m_reader->readElementText(); + } else if (m_reader->name() == QStringLiteral("Shape")) { + QString elementName = m_reader->name().toString(); + QList path; + parseGeoPoints(m_reader->readElementText(), &path, elementName); + segmentContainer.segment.setPath(path); + } else if (m_reader->name() == QStringLiteral("Length")) { + segmentContainer.segment.setDistance(m_reader->readElementText().toDouble()); + } else if (m_reader->name() == QStringLiteral("Maneuver")) { + segmentContainer.maneuverId = m_reader->readElementText(); + } else if (m_reader->name() == QStringLiteral("DynamicSpeedInfo")) { + QGeoDynamicSpeedInfoContainer speedInfo; + if (!parseDynamicSpeedInfo(speedInfo)) + return false; + const double time = speedInfo.trafficTime >= 0 ? speedInfo.trafficTime : speedInfo.baseTime; + if (time >= 0) + segmentContainer.segment.setTravelTime(time); + } else { + m_reader->skipCurrentElement(); + } + } + m_reader->readNext(); + } + + if (m_reader->hasError()) + return false; + + m_segments.append(segmentContainer); + return true; +} + +bool QGeoRouteXmlParser::parseGeoPoints(const QString &strPoints, QList *geoPoints, const QString &elementName) +{ + QStringList rawPoints = strPoints.split(' '); + + for (int i = 0; i < rawPoints.length(); ++i) { + QStringList coords = rawPoints[i].split(','); + + if (coords.length() != 2) { + m_reader->raiseError(QString("Each of the space separated values of \"%1\" is expected to be a comma separated pair of coordinates (value was \"%2\")").arg(elementName).arg(rawPoints[i])); + return false; + } + + bool ok = false; + QString latString = coords[0]; + double lat = latString.toDouble(&ok); + + if (!ok) { + m_reader->raiseError(QString("The latitude portions of \"%1\" are expected to have a value convertable to a double (value was \"%2\")").arg(elementName).arg(latString)); + return false; + } + + QString lngString = coords[1]; + double lng = lngString.toDouble(&ok); + + if (!ok) { + m_reader->raiseError(QString("The longitude portions of \"%1\" are expected to have a value convertable to a double (value was \"%2\")").arg(elementName).arg(lngString)); + return false; + } + + QGeoCoordinate geoPoint(lat, lng); + geoPoints->append(geoPoint); + } + + return true; +} + +bool QGeoRouteXmlParser::parseBoundingBox(QGeoRectangle &bounds) +{ + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "BoundingBox"); + + QGeoCoordinate tl; + QGeoCoordinate br; + + m_reader->readNext(); + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "BoundingBox") && + !m_reader->hasError()) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + if (m_reader->name() == "TopLeft") { + QGeoCoordinate coordinates; + if (parseCoordinates(coordinates)) + tl = coordinates; + } else if (m_reader->name() == "BottomRight") { + QGeoCoordinate coordinates; + if (parseCoordinates(coordinates)) + br = coordinates; + } else { + m_reader->skipCurrentElement(); + } + } + m_reader->readNext(); + } + + if (m_reader->hasError()) + return false; + + if (tl.isValid() && br.isValid()) { + bounds = QGeoRectangle(tl, br); + return true; + } + + return false; +} + +bool QGeoRouteXmlParser::parseDynamicSpeedInfo(QGeoDynamicSpeedInfoContainer &speedInfo) +{ + Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral("DynamicSpeedInfo")); + + m_reader->readNext(); + while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == QStringLiteral("DynamicSpeedInfo")) && + !m_reader->hasError()) { + if (m_reader->tokenType() == QXmlStreamReader::StartElement) { + if (m_reader->name() == QStringLiteral("TrafficSpeed")) { + speedInfo.trafficSpeed = m_reader->readElementText().toDouble(); + } else if (m_reader->name() == QStringLiteral("TrafficTime")) { + speedInfo.trafficTime = qRound(m_reader->readElementText().toDouble()); + } else if (m_reader->name() == QStringLiteral("BaseSpeed")) { + speedInfo.baseSpeed = m_reader->readElementText().toDouble(); + } else if (m_reader->name() == QStringLiteral("BaseTime")) { + speedInfo.baseTime = qRound(m_reader->readElementText().toDouble()); + } else { + m_reader->skipCurrentElement(); + } + } + m_reader->readNext(); + } + + return !m_reader->hasError(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeoroutexmlparser.h b/src/plugins/geoservices/nokia/qgeoroutexmlparser.h new file mode 100644 index 0000000..e2feb72 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoroutexmlparser.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QROUTEXMLPARSER_H +#define QROUTEXMLPARSER_H + +#include +#include +#include +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QXmlStreamReader; +class QGeoRoute; +class QGeoCoordinate; +class QGeoRectangle; + +class QGeoManeuverContainer +{ +public: + QGeoManeuver maneuver; + QString id; + QString toId; +}; + +class QGeoRouteSegmentContainer +{ +public: + QGeoRouteSegment segment; + QString id; + QString maneuverId; +}; + +class QGeoDynamicSpeedInfoContainer +{ +public: + QGeoDynamicSpeedInfoContainer(); + +public: + double trafficSpeed; + double baseSpeed; + int trafficTime; + int baseTime; +}; + +class QGeoRouteXmlParser : public QObject, public QRunnable +{ + Q_OBJECT + +public: + QGeoRouteXmlParser(const QGeoRouteRequest &request); + ~QGeoRouteXmlParser(); + + void parse(const QByteArray &data); + void run(); + +signals: + void results(const QList &routes); + void error(const QString &errorString); + +private: + bool parseRootElement(); + bool parseRoute(QGeoRoute *route); + //bool parseWaypoint(QGeoRoute *route); + bool parseCoordinates(QGeoCoordinate &coord); + bool parseMode(QGeoRoute *route); + bool parseSummary(QGeoRoute *route); + bool parseGeoPoints(const QString &strPoints, QList *geoPoints, const QString &elementName); + bool parseLeg(); + bool parseManeuver(); + bool parseLink(); + bool postProcessRoute(QGeoRoute *route); + + bool parseBoundingBox(QGeoRectangle &bounds); + bool parseDynamicSpeedInfo(QGeoDynamicSpeedInfoContainer &speedInfo); + + QGeoRouteRequest m_request; + QByteArray m_data; + QXmlStreamReader *m_reader; + + QList m_results; + QList m_maneuvers; + QList m_segments; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp new file mode 100644 index 0000000..a33d1ba --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp @@ -0,0 +1,491 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroutingmanagerengine_nokia.h" +#include "qgeoroutereply_nokia.h" +#include "qgeonetworkaccessmanager.h" +#include "qgeouriprovider.h" +#include "uri_constants.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoRoutingManagerEngineNokia::QGeoRoutingManagerEngineNokia( + QGeoNetworkAccessManager *networkManager, + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) + : QGeoRoutingManagerEngine(parameters) + , m_networkManager(networkManager) + , m_uriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.routing.host"), ROUTING_HOST)) + +{ + Q_ASSERT(networkManager); + m_networkManager->setParent(this); + + m_appId = parameters.value(QStringLiteral("here.app_id")).toString(); + m_token = parameters.value(QStringLiteral("here.token")).toString(); + + QGeoRouteRequest::FeatureTypes featureTypes; + featureTypes |= QGeoRouteRequest::TollFeature; + featureTypes |= QGeoRouteRequest::HighwayFeature; + featureTypes |= QGeoRouteRequest::FerryFeature; + featureTypes |= QGeoRouteRequest::TunnelFeature; + featureTypes |= QGeoRouteRequest::DirtRoadFeature; + featureTypes |= QGeoRouteRequest::ParksFeature; + setSupportedFeatureTypes(featureTypes); + + QGeoRouteRequest::FeatureWeights featureWeights; + featureWeights |= QGeoRouteRequest::DisallowFeatureWeight; + featureWeights |= QGeoRouteRequest::AvoidFeatureWeight; + featureWeights |= QGeoRouteRequest::PreferFeatureWeight; + setSupportedFeatureWeights(featureWeights); + + QGeoRouteRequest::ManeuverDetails maneuverDetails; + maneuverDetails |= QGeoRouteRequest::BasicManeuvers; + setSupportedManeuverDetails(maneuverDetails); + + QGeoRouteRequest::RouteOptimizations optimizations; + optimizations |= QGeoRouteRequest::ShortestRoute; + optimizations |= QGeoRouteRequest::FastestRoute; + setSupportedRouteOptimizations(optimizations); + + QGeoRouteRequest::TravelModes travelModes; + travelModes |= QGeoRouteRequest::CarTravel; + travelModes |= QGeoRouteRequest::PedestrianTravel; + travelModes |= QGeoRouteRequest::PublicTransitTravel; + travelModes |= QGeoRouteRequest::BicycleTravel; + setSupportedTravelModes(travelModes); + + QGeoRouteRequest::SegmentDetails segmentDetails; + segmentDetails |= QGeoRouteRequest::BasicSegmentData; + setSupportedSegmentDetails(segmentDetails); + + if (error) + *error = QGeoServiceProvider::NoError; + + if (errorString) + *errorString = QString(); +} + +QGeoRoutingManagerEngineNokia::~QGeoRoutingManagerEngineNokia() {} + +QGeoRouteReply *QGeoRoutingManagerEngineNokia::calculateRoute(const QGeoRouteRequest &request) +{ + const QStringList reqStrings = calculateRouteRequestString(request); + + if (reqStrings.isEmpty()) { + QGeoRouteReply *reply = new QGeoRouteReply(QGeoRouteReply::UnsupportedOptionError, "The given route request options are not supported by this service provider.", this); + emit error(reply, reply->error(), reply->errorString()); + return reply; + } + + QList replies; + foreach (const QString &reqString, reqStrings) + replies.append(m_networkManager->get(QNetworkRequest(QUrl(reqString)))); + + QGeoRouteReplyNokia *reply = new QGeoRouteReplyNokia(request, replies, this); + + connect(reply, + SIGNAL(finished()), + this, + SLOT(routeFinished())); + + connect(reply, + SIGNAL(error(QGeoRouteReply::Error,QString)), + this, + SLOT(routeError(QGeoRouteReply::Error,QString))); + + return reply; +} + +QGeoRouteReply *QGeoRoutingManagerEngineNokia::updateRoute(const QGeoRoute &route, const QGeoCoordinate &position) +{ + const QStringList reqStrings = updateRouteRequestString(route, position); + + if (reqStrings.isEmpty()) { + QGeoRouteReply *reply = new QGeoRouteReply(QGeoRouteReply::UnsupportedOptionError, "The given route request options are not supported by this service provider.", this); + emit error(reply, reply->error(), reply->errorString()); + return reply; + } + + QList replies; + foreach (const QString &reqString, reqStrings) + replies.append(m_networkManager->get(QNetworkRequest(QUrl(reqString)))); + + QGeoRouteRequest updateRequest(route.request()); + updateRequest.setTravelModes(route.travelMode()); + QGeoRouteReplyNokia *reply = new QGeoRouteReplyNokia(updateRequest, replies, this); + + connect(reply, + SIGNAL(finished()), + this, + SLOT(routeFinished())); + + connect(reply, + SIGNAL(error(QGeoRouteReply::Error,QString)), + this, + SLOT(routeError(QGeoRouteReply::Error,QString))); + + return reply; +} + +bool QGeoRoutingManagerEngineNokia::checkEngineSupport(const QGeoRouteRequest &request, + QGeoRouteRequest::TravelModes travelModes) const +{ + QList featureTypeList = request.featureTypes(); + QGeoRouteRequest::FeatureTypes featureTypeFlag = QGeoRouteRequest::NoFeature; + QGeoRouteRequest::FeatureWeights featureWeightFlag = QGeoRouteRequest::NeutralFeatureWeight; + + for (int i = 0; i < featureTypeList.size(); ++i) { + featureTypeFlag |= featureTypeList.at(i); + featureWeightFlag |= request.featureWeight(featureTypeList.at(i)); + } + + if ((featureTypeFlag & supportedFeatureTypes()) != featureTypeFlag) + return false; + + if ((featureWeightFlag & supportedFeatureWeights()) != featureWeightFlag) + return false; + + + if ((request.maneuverDetail() & supportedManeuverDetails()) != request.maneuverDetail()) + return false; + + if ((request.segmentDetail() & supportedSegmentDetails()) != request.segmentDetail()) + return false; + + if ((request.routeOptimization() & supportedRouteOptimizations()) != request.routeOptimization()) + return false; + + if ((travelModes & supportedTravelModes()) != travelModes) + return false; + + // Count the number of set bits (= number of travel modes) (popcount) + int count = 0; + + for (unsigned bits = travelModes; bits; bits >>= 1) + count += (bits & 1); + + // We only allow one travel mode at a time + if (count != 1) + return false; + + return true; +} + +QStringList QGeoRoutingManagerEngineNokia::calculateRouteRequestString(const QGeoRouteRequest &request) +{ + bool supported = checkEngineSupport(request, request.travelModes()); + + if (!supported) + return QStringList(); + QStringList requests; + + QString baseRequest = QStringLiteral("http://"); + baseRequest += m_uriProvider->getCurrentHost(); + baseRequest += QStringLiteral("/routing/7.2/calculateroute.xml"); + + baseRequest += QStringLiteral("?alternatives="); + baseRequest += QString::number(request.numberAlternativeRoutes()); + + if (!m_appId.isEmpty() && !m_token.isEmpty()) { + baseRequest += QStringLiteral("&app_id="); + baseRequest += m_appId; + baseRequest += QStringLiteral("&token="); + baseRequest += m_token; + } + + int numWaypoints = request.waypoints().size(); + if (numWaypoints < 2) + return QStringList(); + + for (int i = 0;i < numWaypoints;++i) { + baseRequest += QStringLiteral("&waypoint"); + baseRequest += QString::number(i); + baseRequest += QStringLiteral("=geo!"); + baseRequest += trimDouble(request.waypoints().at(i).latitude()); + baseRequest += ','; + baseRequest += trimDouble(request.waypoints().at(i).longitude()); + } + + QGeoRouteRequest::RouteOptimizations optimization = request.routeOptimization(); + + QStringList types; + if (optimization.testFlag(QGeoRouteRequest::ShortestRoute)) + types.append("shortest"); + if (optimization.testFlag(QGeoRouteRequest::FastestRoute)) + types.append("fastest"); + + foreach (const QString &optimization, types) { + QString requestString = baseRequest; + requestString += modesRequestString(request, request.travelModes(), optimization); + requestString += routeRequestString(request); + requests << requestString; + } + + return requests; +} + +QStringList QGeoRoutingManagerEngineNokia::updateRouteRequestString(const QGeoRoute &route, const QGeoCoordinate &position) +{ + if (!checkEngineSupport(route.request(), route.travelMode())) + return QStringList(); + QStringList requests; + + QString baseRequest = "http://"; + baseRequest += m_uriProvider->getCurrentHost(); + baseRequest += "/routing/7.2/getroute.xml"; + + baseRequest += "?routeid="; + baseRequest += route.routeId(); + + baseRequest += "&pos="; + baseRequest += QString::number(position.latitude()); + baseRequest += ','; + baseRequest += QString::number(position.longitude()); + + QGeoRouteRequest::RouteOptimizations optimization = route.request().routeOptimization(); + + QStringList types; + if (optimization.testFlag(QGeoRouteRequest::ShortestRoute)) + types.append("shortest"); + if (optimization.testFlag(QGeoRouteRequest::FastestRoute)) + types.append("fastest"); + + foreach (const QString &optimization, types) { + QString requestString = baseRequest; + requestString += modesRequestString(route.request(), route.travelMode(), optimization); + requestString += routeRequestString(route.request()); + requests << requestString; + } + + return requests; +} + +QString QGeoRoutingManagerEngineNokia::modesRequestString(const QGeoRouteRequest &request, + QGeoRouteRequest::TravelModes travelModes, const QString &optimization) const +{ + QString requestString; + + QStringList modes; + if (travelModes.testFlag(QGeoRouteRequest::CarTravel)) + modes.append("car"); + if (travelModes.testFlag(QGeoRouteRequest::PedestrianTravel)) + modes.append("pedestrian"); + if (travelModes.testFlag(QGeoRouteRequest::PublicTransitTravel)) + modes.append("publicTransport"); + + QStringList featureStrings; + QList featureTypes = request.featureTypes(); + for (int i = 0; i < featureTypes.size(); ++i) { + QGeoRouteRequest::FeatureWeight weight = request.featureWeight(featureTypes.at(i)); + + if (weight == QGeoRouteRequest::NeutralFeatureWeight) + continue; + + QString weightString = ""; + switch (weight) { + case QGeoRouteRequest::PreferFeatureWeight: + weightString = '1'; + break; + case QGeoRouteRequest::AvoidFeatureWeight: + weightString = "-1"; + break; + case QGeoRouteRequest::DisallowFeatureWeight: + weightString = "-3"; + break; + case QGeoRouteRequest::NeutralFeatureWeight: + case QGeoRouteRequest::RequireFeatureWeight: + break; + } + + if (weightString.isEmpty()) + continue; + + switch (featureTypes.at(i)) { + case QGeoRouteRequest::TollFeature: + featureStrings.append("tollroad:" + weightString); + break; + case QGeoRouteRequest::HighwayFeature: + featureStrings.append("motorway:" + weightString); + break; + case QGeoRouteRequest::FerryFeature: + featureStrings.append("boatFerry:" + weightString); + featureStrings.append("railFerry:" + weightString); + break; + case QGeoRouteRequest::TunnelFeature: + featureStrings.append("tunnel:" + weightString); + break; + case QGeoRouteRequest::DirtRoadFeature: + featureStrings.append("dirtRoad:" + weightString); + break; + case QGeoRouteRequest::PublicTransitFeature: + case QGeoRouteRequest::ParksFeature: + case QGeoRouteRequest::MotorPoolLaneFeature: + case QGeoRouteRequest::NoFeature: + break; + } + } + + requestString += "&mode="; + requestString += optimization + ';' + modes.join(','); + if (featureStrings.count()) + requestString += ';' + featureStrings.join(','); + return requestString; +} + +QString QGeoRoutingManagerEngineNokia::routeRequestString(const QGeoRouteRequest &request) const +{ + QString requestString; + + foreach (const QGeoRectangle &area, request.excludeAreas()) { + requestString += QLatin1String("&avoidareas="); + requestString += trimDouble(area.topLeft().latitude()); + requestString += QLatin1String(","); + requestString += trimDouble(area.topLeft().longitude()); + requestString += QLatin1String(";"); + requestString += trimDouble(area.bottomRight().latitude()); + requestString += QLatin1String(","); + requestString += trimDouble(area.bottomRight().longitude()); + } + +// TODO: work out what was going on here +// - segment and instruction/maneuever functions are mixed and matched +// - tried to implement sensible equivalents below +// QStringList legAttributes; +// if (request.instructionDetail() & QGeoRouteRequest::BasicSegmentData) { +// requestString += "&linkattributes=sh,le"; //shape,length +// legAttributes.append("links"); +// } +// +// if (request.instructionDetail() & QGeoRouteRequest::BasicInstructions) { +// legAttributes.append("maneuvers"); +// requestString += "&maneuverattributes=po,tt,le,di"; //position,traveltime,length,direction +// if (!(request.instructionDetail() & QGeoRouteRequest::NoSegmentData)) +// requestString += ",li"; //link +// } + + QStringList legAttributes; + if (request.segmentDetail() & QGeoRouteRequest::BasicSegmentData) { + requestString += "&linkattributes=sh,le"; //shape,length + legAttributes.append("links"); + } + + if (request.maneuverDetail() & QGeoRouteRequest::BasicManeuvers) { + legAttributes.append("maneuvers"); + requestString += "&maneuverattributes=po,tt,le,di"; //position,traveltime,length,direction + if (!(request.segmentDetail() & QGeoRouteRequest::NoSegmentData)) + requestString += ",li"; //link + } + + requestString += "&routeattributes=sm,sh,bb,lg"; //summary,shape,boundingBox,legs + if (legAttributes.count() > 0) { + requestString += "&legattributes="; + requestString += legAttributes.join(","); + } + + requestString += "&departure="; + requestString += QDateTime::currentDateTime().toUTC().toString("yyyy-MM-ddThh:mm:ssZ"); + + requestString += "&instructionformat=text"; + + requestString += "&metricSystem="; + if (QLocale::MetricSystem == measurementSystem()) + requestString += "metric"; + else + requestString += "imperial"; + + const QLocale loc(locale()); + + if (QLocale::C != loc.language() && QLocale::AnyLanguage != loc.language()) { + requestString += "&language="; + requestString += loc.name(); + //If the first language isn't supported, english will be selected automatically + if (QLocale::English != loc.language()) + requestString += ",en_US"; + } + + return requestString; +} + +QString QGeoRoutingManagerEngineNokia::trimDouble(double degree, int decimalDigits) +{ + QString sDegree = QString::number(degree, 'g', decimalDigits); + + int index = sDegree.indexOf('.'); + + if (index == -1) + return sDegree; + else + return QString::number(degree, 'g', decimalDigits + index); +} + +void QGeoRoutingManagerEngineNokia::routeFinished() +{ + QGeoRouteReply *reply = qobject_cast(sender()); + + if (!reply) + return; + + if (receivers(SIGNAL(finished(QGeoRouteReply*))) == 0) { + reply->deleteLater(); + return; + } + + emit finished(reply); +} + +void QGeoRoutingManagerEngineNokia::routeError(QGeoRouteReply::Error error, const QString &errorString) +{ + QGeoRouteReply *reply = qobject_cast(sender()); + + if (!reply) + return; + + if (receivers(SIGNAL(error(QGeoRouteReply*,QGeoRouteReply::Error,QString))) == 0) { + reply->deleteLater(); + return; + } + + emit this->error(reply, error, errorString); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h new file mode 100644 index 0000000..9335bca --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTINGMANAGER_NOKIA_H +#define QGEOROUTINGMANAGER_NOKIA_H + +#include "qgeoserviceproviderplugin_nokia.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoNetworkAccessManager; +class QGeoUriProvider; + +class QGeoRoutingManagerEngineNokia : public QGeoRoutingManagerEngine +{ + Q_OBJECT +public: + QGeoRoutingManagerEngineNokia(QGeoNetworkAccessManager *networkInterface, + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString); + ~QGeoRoutingManagerEngineNokia(); + + QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request); + QGeoRouteReply *updateRoute(const QGeoRoute &route, const QGeoCoordinate &position); + +private Q_SLOTS: + void routeFinished(); + void routeError(QGeoRouteReply::Error error, const QString &errorString); + +private: + QStringList calculateRouteRequestString(const QGeoRouteRequest &request); + QStringList updateRouteRequestString(const QGeoRoute &route, const QGeoCoordinate &position); + QString routeRequestString(const QGeoRouteRequest &request) const; + bool checkEngineSupport(const QGeoRouteRequest &request, + QGeoRouteRequest::TravelModes travelModes) const; + QString modesRequestString(const QGeoRouteRequest &request, + QGeoRouteRequest::TravelModes travelModes, + const QString &optimization) const; + static QString trimDouble(double degree, int decimalDigits = 10); + + QGeoNetworkAccessManager *m_networkManager; + QGeoUriProvider *m_uriProvider; + QString m_appId; + QString m_token; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp b/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp new file mode 100644 index 0000000..f6d05c3 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoserviceproviderplugin_nokia.h" + +#include "qgeocodingmanagerengine_nokia.h" +#include "qgeoroutingmanagerengine_nokia.h" +#include "qgeotiledmappingmanagerengine_nokia.h" +#include "qplacemanagerengine_nokiav2.h" +#include "qgeointrinsicnetworkaccessmanager.h" +#include "qgeoerror_messages.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace +{ + bool isValidParameter(const QString ¶m) + { + if (param.isEmpty()) + return false; + + if (param.length() > 512) + return false; + + foreach (QChar c, param) { + if (!c.isLetterOrNumber() && c.toLatin1() != '%' && c.toLatin1() != '-' && + c.toLatin1() != '+' && c.toLatin1() != '_') { + return false; + } + } + return true; + } + + QGeoNetworkAccessManager *tryGetNetworkAccessManager(const QVariantMap ¶meters) + { + return static_cast(qvariant_cast(parameters.value(QStringLiteral("nam")))); + } + + void checkUsageTerms(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) + { + QString appId, token; + + appId = parameters.value(QStringLiteral("here.app_id")).toString(); + token = parameters.value(QStringLiteral("here.token")).toString(); + + if (isValidParameter(appId) && isValidParameter(token)) + return; + + if (parameters.contains(QStringLiteral("app_id")) || parameters.contains(QStringLiteral("token"))) + qWarning() << QStringLiteral("Please prefix 'app_id' and 'token' with prefix 'here' (e.g.: 'here.app_id')"); + + *error = QGeoServiceProvider::MissingRequiredParameterError; + *errorString = QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, MISSED_CREDENTIALS); + } + + template + TInstance * CreateInstanceOf(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) + { + checkUsageTerms(parameters, error, errorString); + + if (*error != QGeoServiceProvider::NoError) + return 0; + + QGeoNetworkAccessManager *networkManager = tryGetNetworkAccessManager(parameters); + if (!networkManager) + networkManager = new QGeoIntrinsicNetworkAccessManager(parameters); + + return new TInstance(networkManager, parameters, error, errorString); + } +} + +QGeoCodingManagerEngine *QGeoServiceProviderFactoryNokia::createGeocodingManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const +{ + return CreateInstanceOf(parameters, error, errorString); +} + +QGeoMappingManagerEngine *QGeoServiceProviderFactoryNokia::createMappingManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const +{ + return CreateInstanceOf(parameters, error, errorString); +} + +QGeoRoutingManagerEngine *QGeoServiceProviderFactoryNokia::createRoutingManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const +{ + return CreateInstanceOf(parameters, error, errorString); +} + +QPlaceManagerEngine *QGeoServiceProviderFactoryNokia::createPlaceManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const +{ + return CreateInstanceOf(parameters, error, errorString); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.h b/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.h new file mode 100644 index 0000000..bce65cb --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDER_NOKIA_H +#define QGEOSERVICEPROVIDER_NOKIA_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoNetworkAccessManager; + +class QGeoServiceProviderFactoryNokia : public QObject, public QGeoServiceProviderFactory +{ + Q_OBJECT + Q_INTERFACES(QGeoServiceProviderFactory) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0" + FILE "nokia_plugin.json") + +public: + QGeoCodingManagerEngine *createGeocodingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + QGeoMappingManagerEngine *createMappingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + QGeoRoutingManagerEngine *createRoutingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp new file mode 100644 index 0000000..d83ad0f --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** + ** + ** Copyright (C) 2015 The Qt Company Ltd. + ** Contact: http://www.qt.io/licensing/ + ** + ** This file is part of the QtLocation module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL3$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see http://www.qt.io/terms-conditions. For further + ** information use the contact form at http://www.qt.io/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 3 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPLv3 included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 3 requirements + ** will be met: https://www.gnu.org/licenses/lgpl.html. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 2.0 or later as published by the Free + ** Software Foundation and appearing in the file LICENSE.GPL included in + ** the packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 2.0 requirements will be + ** met: http://www.gnu.org/licenses/gpl-2.0.html. + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include "qgeotiledmap_nokia.h" +#include "qgeotiledmappingmanagerengine_nokia.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +/*! + Constructs a new tiled map data object, which stores the map data required by + \a geoMap and makes use of the functionality provided by \a engine. + */ +QGeoTiledMapNokia::QGeoTiledMapNokia(QGeoTiledMappingManagerEngineNokia *engine, QObject *parent /*= 0*/) : + QGeoTiledMap(engine, parent), + m_logo(":/images/logo.png"), // HERE logo image + m_engine(engine) +{} + +QGeoTiledMapNokia::~QGeoTiledMapNokia() {} + +void QGeoTiledMapNokia::evaluateCopyrights(const QSet &visibleTiles) +{ + const int spaceToLogo = 4; + const int blurRate = 1; + const int fontSize = 10; + + if (m_engine.isNull()) + return; + + const QString copyrightsString = m_engine->evaluateCopyrightsText(activeMapType(), cameraData().zoomLevel(), visibleTiles); + + if (width() > 0 && height() > 0 && ((copyrightsString.isNull() && m_copyrightsSlab.isNull()) || copyrightsString != m_lastCopyrightsString)) { + QFont font("Sans Serif"); + font.setPixelSize(fontSize); + font.setStyleHint(QFont::SansSerif); + font.setWeight(QFont::Bold); + + QRect textBounds = QFontMetrics(font).boundingRect(0, 0, width(), height(), Qt::AlignBottom | Qt::AlignLeft | Qt::TextWordWrap, copyrightsString); + + m_copyrightsSlab = QImage(m_logo.width() + textBounds.width() + spaceToLogo + blurRate * 2, + qMax(m_logo.height(), textBounds.height() + blurRate * 2), + QImage::Format_ARGB32_Premultiplied); + m_copyrightsSlab.fill(Qt::transparent); + + QPainter painter(&m_copyrightsSlab); + painter.drawImage(QPoint(0, m_copyrightsSlab.height() - m_logo.height()), m_logo); + painter.setFont(font); + painter.setPen(QColor(0, 0, 0, 64)); + painter.translate(spaceToLogo + m_logo.width(), -blurRate); + for (int x=-blurRate; x<=blurRate; ++x) { + for (int y=-blurRate; y<=blurRate; ++y) { + painter.drawText(x, y, textBounds.width(), m_copyrightsSlab.height(), + Qt::AlignBottom | Qt::AlignLeft | Qt::TextWordWrap, + copyrightsString); + } + } + painter.setPen(Qt::white); + painter.drawText(0, 0, textBounds.width(), m_copyrightsSlab.height(), + Qt::AlignBottom | Qt::AlignLeft | Qt::TextWordWrap, + copyrightsString); + painter.end(); + + m_lastCopyrightsString = copyrightsString; + } + + emit copyrightsChanged(m_copyrightsSlab); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeotiledmap_nokia.h b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.h new file mode 100644 index 0000000..9651cc8 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAP_NOKIA_H +#define QGEOMAP_NOKIA_H + +#include "qgeotiledmap_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoTiledMappingManagerEngineNokia; + +class QGeoTiledMapNokia: public QGeoTiledMap +{ +Q_OBJECT +public: + QGeoTiledMapNokia(QGeoTiledMappingManagerEngineNokia *engine, QObject *parent = 0); + ~QGeoTiledMapNokia(); + + QString getViewCopyright(); + void evaluateCopyrights(const QSet &visibleTiles); + +private: + QImage m_logo; + QImage m_copyrightsSlab; + QString m_lastCopyrightsString; + QPointer m_engine; + + Q_DISABLE_COPY(QGeoTiledMapNokia) +}; + +QT_END_NAMESPACE + +#endif // QGEOMAP_NOKIA_H diff --git a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp new file mode 100644 index 0000000..4f44e5f --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp @@ -0,0 +1,384 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocameracapabilities_p.h" +#include "qgeotiledmappingmanagerengine_nokia.h" +#include "qgeotiledmap_nokia.h" +#include "qgeotilefetcher_nokia.h" +#include "qgeotilespec_p.h" +#include "qgeofiletilecache_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoTiledMappingManagerEngineNokia::QGeoTiledMappingManagerEngineNokia( + QGeoNetworkAccessManager *networkManager, + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) + : QGeoTiledMappingManagerEngine() +{ + Q_UNUSED(error); + Q_UNUSED(errorString); + + QGeoCameraCapabilities capabilities; + + capabilities.setMinimumZoomLevel(0.0); + capabilities.setMaximumZoomLevel(20.0); + + setCameraCapabilities(capabilities); + + setTileSize(QSize(256, 256)); + + QList types; + types << QGeoMapType(QGeoMapType::StreetMap, tr("Street Map"), tr("Normal map view in daylight mode"), false, false, 1); + types << QGeoMapType(QGeoMapType::SatelliteMapDay, tr("Satellite Map"), tr("Satellite map view in daylight mode"), false, false, 2); + types << QGeoMapType(QGeoMapType::TerrainMap, tr("Terrain Map"), tr("Terrain map view in daylight mode"), false, false, 3); + types << QGeoMapType(QGeoMapType::HybridMap, tr("Hybrid Map"), tr("Satellite map view with streets in daylight mode"), false, false, 4); + types << QGeoMapType(QGeoMapType::TransitMap, tr("Transit Map"), tr("Color-reduced map view with public transport scheme in daylight mode"), false, false, 5); + types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Gray Street Map"), tr("Color-reduced map view in daylight mode"), false, false, 6); + types << QGeoMapType(QGeoMapType::StreetMap, tr("Mobile Street Map"), tr("Mobile normal map view in daylight mode"), true, false, 7); + types << QGeoMapType(QGeoMapType::TerrainMap, tr("Mobile Terrain Map"), tr("Mobile terrain map view in daylight mode"), true, false, 8); + types << QGeoMapType(QGeoMapType::HybridMap, tr("Mobile Hybrid Map"), tr("Mobile satellite map view with streets in daylight mode"), true, false, 9); + types << QGeoMapType(QGeoMapType::TransitMap, tr("Mobile Transit Map"), tr("Mobile color-reduced map view with public transport scheme in daylight mode"), true, false, 10); + types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Mobile Gray Street Map"), tr("Mobile color-reduced map view in daylight mode"), true, false, 11); + types << QGeoMapType(QGeoMapType::StreetMap, tr("Custom Street Map"), tr("Normal map view in daylight mode"), false, false, 12); + types << QGeoMapType(QGeoMapType::StreetMap, tr("Night Street Map"), tr("Normal map view in night mode"), false, true, 13); + types << QGeoMapType(QGeoMapType::StreetMap, tr("Mobile Night Street Map"), tr("Mobile normal map view in night mode"), true, true, 14); + types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Gray Night Street Map"), tr("Color-reduced map view in night mode (especially used for background maps)"), false, true, 15); + types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Mobile Gray Night Street Map"), tr("Mobile color-reduced map view in night mode (especially used for background maps)"), true, true, 16); + types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Pedestrian Street Map"), tr("Pedestrian map view in daylight mode"), false, false, 17); + types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Mobile Pedestrian Street Map"), tr("Mobile pedestrian map view in daylight mode for mobile usage"), true, false, 18); + types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Pedestrian Night Street Map"), tr("Pedestrian map view in night mode"), false, true, 19); + types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Mobile Pedestrian Night Street Map"), tr("Mobile pedestrian map view in night mode for mobile usage"), true, true, 20); + types << QGeoMapType(QGeoMapType::CarNavigationMap, tr("Car Navigation Map"), tr("Normal map view in daylight mode for car navigation"), false, false, 21); + setSupportedMapTypes(types); + + QGeoTileFetcherNokia *fetcher = new QGeoTileFetcherNokia(parameters, networkManager, this, tileSize()); + setTileFetcher(fetcher); + + // TODO: do this in a plugin-neutral way so that other tiled map plugins + // don't need this boilerplate or hardcode plugin name + + if (parameters.contains(QStringLiteral("here.mapping.cache.directory"))) { + m_cacheDirectory = parameters.value(QStringLiteral("here.mapping.cache.directory")).toString(); + } else { + // managerName() is not yet set, we have to hardcode the plugin name below + m_cacheDirectory = QAbstractGeoTileCache::baseCacheDirectory() + QLatin1String("here"); + } + + QAbstractGeoTileCache *tileCache = new QGeoFileTileCache(m_cacheDirectory); + setTileCache(tileCache); + + if (parameters.contains(QStringLiteral("here.mapping.cache.disk.size"))) { + bool ok = false; + int cacheSize = parameters.value(QStringLiteral("here.mapping.cache.disk.size")).toString().toInt(&ok); + if (ok) + tileCache->setMaxDiskUsage(cacheSize); + } + + if (parameters.contains(QStringLiteral("here.mapping.cache.memory.size"))) { + bool ok = false; + int cacheSize = parameters.value(QStringLiteral("here.mapping.cache.memory.size")).toString().toInt(&ok); + if (ok) + tileCache->setMaxMemoryUsage(cacheSize); + } + + if (parameters.contains(QStringLiteral("here.mapping.cache.texture.size"))) { + bool ok = false; + int cacheSize = parameters.value(QStringLiteral("here.mapping.cache.texture.size")).toString().toInt(&ok); + if (ok) + tileCache->setExtraTextureUsage(cacheSize); + } + + populateMapSchemes(); + loadMapVersion(); + QMetaObject::invokeMethod(fetcher, "fetchCopyrightsData", Qt::QueuedConnection); + QMetaObject::invokeMethod(fetcher, "fetchVersionData", Qt::QueuedConnection); +} + +QGeoTiledMappingManagerEngineNokia::~QGeoTiledMappingManagerEngineNokia() +{ +} + +void QGeoTiledMappingManagerEngineNokia::populateMapSchemes() +{ + m_mapSchemes[0] = QStringLiteral("normal.day"); + m_mapSchemes[1] = QStringLiteral("normal.day"); + m_mapSchemes[2] = QStringLiteral("satellite.day"); + m_mapSchemes[3] = QStringLiteral("terrain.day"); + m_mapSchemes[4] = QStringLiteral("hybrid.day"); + m_mapSchemes[5] = QStringLiteral("normal.day.transit"); + m_mapSchemes[6] = QStringLiteral("normal.day.grey"); + m_mapSchemes[7] = QStringLiteral("normal.day.mobile"); + m_mapSchemes[8] = QStringLiteral("terrain.day.mobile"); + m_mapSchemes[9] = QStringLiteral("hybrid.day.mobile"); + m_mapSchemes[10] = QStringLiteral("normal.day.transit.mobile"); + m_mapSchemes[11] = QStringLiteral("normal.day.grey.mobile"); + m_mapSchemes[12] = QStringLiteral("normal.day.custom"); + m_mapSchemes[13] = QStringLiteral("normal.night"); + m_mapSchemes[14] = QStringLiteral("normal.night.mobile"); + m_mapSchemes[15] = QStringLiteral("normal.night.grey"); + m_mapSchemes[16] = QStringLiteral("normal.night.grey.mobile"); + m_mapSchemes[17] = QStringLiteral("pedestrian.day"); + m_mapSchemes[18] = QStringLiteral("pedestrian.day.mobile"); + m_mapSchemes[19] = QStringLiteral("pedestrian.night"); + m_mapSchemes[20] = QStringLiteral("pedestrian.night.mobile"); + m_mapSchemes[21] = QStringLiteral("carnav.day.grey"); +} + +QString QGeoTiledMappingManagerEngineNokia::getScheme(int mapId) +{ + return m_mapSchemes[mapId]; +} + +QString QGeoTiledMappingManagerEngineNokia::getBaseScheme(int mapId) +{ + QString fullScheme(m_mapSchemes[mapId]); + + return fullScheme.section(QLatin1Char('.'), 0, 0); +} + +int QGeoTiledMappingManagerEngineNokia::mapVersion() +{ + return m_mapVersion.version(); +} + +void QGeoTiledMappingManagerEngineNokia::loadCopyrightsDescriptorsFromJson(const QByteArray &jsonData) +{ + QJsonDocument doc = QJsonDocument::fromJson(QByteArray(jsonData)); + if (doc.isNull()) { + qDebug() << "QGeoTiledMappingManagerEngineNokia::loadCopyrightsDescriptorsFromJson() Invalid JSon document"; + return; + } + + QJsonObject jsonObj = doc.object(); + + m_copyrights.clear(); + for (auto it = jsonObj.constBegin(), end = jsonObj.constEnd(); it != end; ++it) { + QList copyrightDescList; + + QJsonArray descs = it.value().toArray(); + for (int descIndex = 0; descIndex < descs.count(); descIndex++) { + CopyrightDesc copyrightDesc; + QJsonObject desc = descs.at(descIndex).toObject(); + + copyrightDesc.minLevel = desc["minLevel"].toDouble(); + copyrightDesc.maxLevel = desc["maxLevel"].toDouble(); + copyrightDesc.label = desc["label"].toString(); + copyrightDesc.alt = desc["alt"].toString(); + + QJsonArray coordBoxes = desc["boxes"].toArray(); + for (int boxIndex = 0; boxIndex < coordBoxes.count(); boxIndex++) { + QJsonArray box = coordBoxes[boxIndex].toArray(); + qreal top = box[0].toDouble(); + qreal left = box[1].toDouble(); + qreal bottom = box[2].toDouble(); + qreal right = box[3].toDouble(); + QGeoRectangle boundingBox(QGeoCoordinate(top > bottom? top : bottom, + left), + QGeoCoordinate(top > bottom? bottom : top, + right)); + copyrightDesc.boxes << boundingBox; + } + copyrightDescList << copyrightDesc; + } + m_copyrights[it.key()] = copyrightDescList; + } +} + +void QGeoTiledMappingManagerEngineNokia::parseNewVersionInfo(const QByteArray &versionData) +{ + const QString versionString = QString::fromUtf8(versionData); + + const QStringList versionLines = versionString.split(QLatin1Char('\n')); + QJsonObject newVersionData; + foreach (const QString &line, versionLines) { + const QStringList versionInfo = line.split(':'); + if (versionInfo.size() > 1) { + const QString versionKey = versionInfo[0].trimmed(); + const QString versionValue = versionInfo[1].trimmed(); + if (!versionKey.isEmpty() && !versionValue.isEmpty()) { + newVersionData[versionKey] = versionValue; + } + } + } + + updateVersion(newVersionData); +} + +void QGeoTiledMappingManagerEngineNokia::updateVersion(const QJsonObject &newVersionData) { + + if (m_mapVersion.isNewVersion(newVersionData)) { + + m_mapVersion.setVersionData(newVersionData); + m_mapVersion.setVersion(m_mapVersion.version() + 1); + + saveMapVersion(); + setTileVersion(m_mapVersion.version()); + } +} + +void QGeoTiledMappingManagerEngineNokia::saveMapVersion() +{ + QDir saveDir(m_cacheDirectory); + QFile saveFile(saveDir.filePath(QStringLiteral("here_version"))); + + if (!saveFile.open(QIODevice::WriteOnly)) { + qWarning("Failed to write here/nokia map version."); + return; + } + + saveFile.write(m_mapVersion.toJson()); + saveFile.close(); +} + +void QGeoTiledMappingManagerEngineNokia::loadMapVersion() +{ + QDir saveDir(m_cacheDirectory); + QFile loadFile(saveDir.filePath(QStringLiteral("here_version"))); + + if (!loadFile.open(QIODevice::ReadOnly)) { + qWarning("Failed to read here/nokia map version."); + return; + } + + QByteArray saveData = loadFile.readAll(); + loadFile.close(); + + QJsonDocument doc(QJsonDocument::fromJson(saveData)); + + QJsonObject object = doc.object(); + + m_mapVersion.setVersion(object[QStringLiteral("version")].toInt()); + m_mapVersion.setVersionData(object[QStringLiteral("data")].toObject()); + setTileVersion(m_mapVersion.version()); +} + +QString QGeoTiledMappingManagerEngineNokia::evaluateCopyrightsText(const QGeoMapType mapType, + const qreal zoomLevel, + const QSet &tiles) +{ + static const QChar copyrightSymbol(0x00a9); + typedef QSet::const_iterator tile_iter; + QGeoRectangle viewport; + double viewX0, viewY0, viewX1, viewY1; + + tile_iter tile = tiles.constBegin(); + tile_iter lastTile = tiles.constEnd(); + + if (tiles.count()) { + double divFactor = qPow(2.0, tile->zoom()); + viewX0 = viewX1 = tile->x(); + viewY0 = viewY1 = tile->y(); + + // this approach establishes a geo-bounding box from passed tiles to test for intersecition + // with copyrights boxes. + int numTiles = 0; + for (; tile != lastTile; ++tile) { + if (tile->x() < viewX0) + viewX0 = tile->x(); + if (tile->x() > viewX1) + viewX1 = tile->x(); + if (tile->y() < viewY0) + viewY0 = tile->y(); + if (tile->y() > viewY1) + viewY1 = tile->y(); + numTiles++; + } + + viewX1++; + viewY1++; + + QDoubleVector2D pt; + + pt.setX(viewX0 / divFactor); + pt.setY(viewY0 / divFactor); + viewport.setTopLeft(QGeoProjection::mercatorToCoord(pt)); + pt.setX(viewX1 / divFactor); + pt.setY(viewY1 / divFactor); + viewport.setBottomRight(QGeoProjection::mercatorToCoord(pt)); + } + + // TODO: the following invalidation detection algorithm may be improved later. + QList descriptorList = m_copyrights[ getBaseScheme(mapType.mapId()) ]; + CopyrightDesc *descriptor; + int descIndex, boxIndex; + QString copyrightsText; + QSet copyrightStrings; + + for (descIndex = 0; descIndex < descriptorList.count(); descIndex++) { + if (descriptorList[descIndex].minLevel <= zoomLevel && zoomLevel <= descriptorList[descIndex].maxLevel) { + descriptor = &descriptorList[descIndex]; + + for (boxIndex = 0; boxIndex < descriptor->boxes.count(); boxIndex++) { + QGeoRectangle box = descriptor->boxes[boxIndex]; + + if (box.intersects(viewport)) { + copyrightStrings.insert(descriptor->label); + break; + } + } + if (!descriptor->boxes.count()) + copyrightStrings.insert(descriptor->label); + } + } + + foreach (const QString ©rightString, copyrightStrings) { + if (copyrightsText.length()) + copyrightsText += QLatin1Char('\n'); + copyrightsText += copyrightSymbol; + copyrightsText += copyrightString; + } + + return copyrightsText; +} + +QGeoMap *QGeoTiledMappingManagerEngineNokia::createMap() +{ + return new QGeoTiledMapNokia(this); +} + +QT_END_NAMESPACE + diff --git a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h new file mode 100644 index 0000000..1648312 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEDMAPPINGMANAGERENGINE_NOKIA_H +#define QGEOTILEDMAPPINGMANAGERENGINE_NOKIA_H + +#include "qgeotiledmappingmanagerengine_p.h" +#include +#include "qgeomaptype_p.h" +#include "qgeomapversion.h" + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QByteArray; +class QGeoTileSpec; +class QGeoNetworkAccessManager; + +class QGeoTiledMappingManagerEngineNokia : public QGeoTiledMappingManagerEngine +{ + Q_OBJECT + +public: + QGeoTiledMappingManagerEngineNokia(QGeoNetworkAccessManager *networkManager, + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString); + ~QGeoTiledMappingManagerEngineNokia(); + + virtual QGeoMap *createMap(); + QString evaluateCopyrightsText(const QGeoMapType mapType, + const qreal zoomLevel, + const QSet &tiles); + QString getScheme(int mapId); + QString getBaseScheme(int mapId); + int mapVersion(); + +public Q_SLOTS: + void loadCopyrightsDescriptorsFromJson(const QByteArray &jsonData); + void parseNewVersionInfo(const QByteArray &versionData); + +private: + class CopyrightDesc + { + public: + CopyrightDesc() + : maxLevel(-1), + minLevel(-1) {} + + qreal maxLevel; + qreal minLevel; + QList boxes; + QString alt; + QString label; + }; + + void initialize(); + void populateMapSchemes(); + void updateVersion(const QJsonObject &newVersionData); + void saveMapVersion(); + void loadMapVersion(); + + QHash > m_copyrights; + QHash m_mapSchemes; + QGeoMapVersion m_mapVersion; + + QString m_cacheDirectory; +}; + +QT_END_NAMESPACE + +#endif // QGEOTILEDMAPPINGMANAGERENGINE_NOKIA_H diff --git a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp new file mode 100644 index 0000000..50acc2a --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp @@ -0,0 +1,323 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotilefetcher_nokia.h" +#include "qgeomapreply_nokia.h" +#include "qgeotiledmap_nokia.h" +#include "qgeotiledmappingmanagerengine_nokia.h" +#include "qgeonetworkaccessmanager.h" +#include "qgeouriprovider.h" +#include "uri_constants.h" + +#include + +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace +{ + QString sizeToStr(const QSize &size) + { + if (size.height() >= 512 || size.width() >= 512) + return QStringLiteral("512"); + else if (size.height() >= 256 || size.width() >= 256) + return QStringLiteral("256"); + else + return QStringLiteral("128"); // 128 pixel tiles are deprecated. + } + + bool isAerialType(const QString mapScheme) + { + return mapScheme.startsWith("satellite") || mapScheme.startsWith("hybrid") || mapScheme.startsWith("terrain"); + } +} +QGeoTileFetcherNokia::QGeoTileFetcherNokia(const QVariantMap ¶meters, + QGeoNetworkAccessManager *networkManager, + QGeoTiledMappingManagerEngineNokia *engine, + const QSize &tileSize) +: QGeoTileFetcher(engine), m_engineNokia(engine), m_networkManager(networkManager), + m_tileSize(tileSize), m_copyrightsReply(0), + m_baseUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.mapping.host"), MAP_TILES_HOST)), + m_aerialUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.mapping.host.aerial"), MAP_TILES_HOST_AERIAL)) +{ + Q_ASSERT(networkManager); + m_networkManager->setParent(this); + + m_applicationId = parameters.value(QStringLiteral("here.app_id")).toString(); + m_token = parameters.value(QStringLiteral("here.token")).toString(); +} + +QGeoTileFetcherNokia::~QGeoTileFetcherNokia() +{ +} + +QGeoTiledMapReply *QGeoTileFetcherNokia::getTileImage(const QGeoTileSpec &spec) +{ + // TODO add error detection for if request.connectivityMode() != QGraphicsGeoMap::OnlineMode + QString rawRequest = getRequestString(spec); + if (rawRequest.isEmpty()) { + return new QGeoTiledMapReply(QGeoTiledMapReply::UnknownError, + tr("Mapping manager no longer exists"), this); + } + + QNetworkRequest netRequest((QUrl(rawRequest))); // The extra pair of parens disambiguates this from a function declaration + netRequest.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + + QNetworkReply *netReply = m_networkManager->get(netRequest); + + QGeoTiledMapReply *mapReply = new QGeoMapReplyNokia(netReply, spec); + + return mapReply; +} + +QString QGeoTileFetcherNokia::getRequestString(const QGeoTileSpec &spec) +{ + if (!m_engineNokia) + return QString(); + + static const QString http("http://"); + static const QString path("/maptile/2.1/maptile/newest/"); + static const QChar slash('/'); + + QString requestString = http; + + const QString mapScheme = m_engineNokia->getScheme(spec.mapId()); + if (isAerialType(mapScheme)) + requestString += m_aerialUriProvider->getCurrentHost(); + else + requestString += m_baseUriProvider->getCurrentHost(); + + requestString += path; + requestString += mapScheme; + requestString += slash; + requestString += QString::number(spec.zoom()); + requestString += slash; + requestString += QString::number(spec.x()); + requestString += slash; + requestString += QString::number(spec.y()); + requestString += slash; + requestString += sizeToStr(m_tileSize); + static const QString slashpng("/png8"); + requestString += slashpng; + + if (!m_token.isEmpty() && !m_applicationId.isEmpty()) { + requestString += "?token="; + requestString += m_token; + + requestString += "&app_id="; + requestString += m_applicationId; + } + + requestString += "&lg="; + requestString += getLanguageString(); + + return requestString; +} + +QString QGeoTileFetcherNokia::getLanguageString() const +{ + if (!m_engineNokia) + return QStringLiteral("ENG"); + + QLocale locale = m_engineNokia.data()->locale(); + + // English is the default, where no ln is specified. We hardcode the languages + // here even though the entire list is updated automagically from the server. + // The current languages are Arabic, Chinese, Simplified Chinese, English + // French, German, Italian, Polish, Russian and Spanish. The default is English. + // These are actually available from the same host under the URL: /maptiler/v2/info + + switch (locale.language()) { + case QLocale::Arabic: + return QStringLiteral("ARA"); + case QLocale::Chinese: + if (locale.script() == QLocale::TraditionalChineseScript) + return QStringLiteral("CHI"); + else + return QStringLiteral("CHT"); + case QLocale::Dutch: + return QStringLiteral("DUT"); + case QLocale::French: + return QStringLiteral("FRE"); + case QLocale::German: + return QStringLiteral("GER"); + case QLocale::Gaelic: + return QStringLiteral("GLE"); + case QLocale::Greek: + return QStringLiteral("GRE"); + case QLocale::Hebrew: + return QStringLiteral("HEB"); + case QLocale::Hindi: + return QStringLiteral("HIN"); + case QLocale::Indonesian: + return QStringLiteral("IND"); + case QLocale::Italian: + return QStringLiteral("ITA"); + case QLocale::Persian: + return QStringLiteral("PER"); + case QLocale::Polish: + return QStringLiteral("POL"); + case QLocale::Portuguese: + return QStringLiteral("POR"); + case QLocale::Russian: + return QStringLiteral("RUS"); + case QLocale::Sinhala: + return QStringLiteral("SIN"); + case QLocale::Spanish: + return QStringLiteral("SPA"); + case QLocale::Thai: + return QStringLiteral("THA"); + case QLocale::Turkish: + return QStringLiteral("TUR"); + case QLocale::Ukrainian: + return QStringLiteral("UKR"); + case QLocale::Urdu: + return QStringLiteral("URD"); + case QLocale::Vietnamese: + return QStringLiteral("VIE"); + + default: + return QStringLiteral("ENG"); + } + // No "lg" param means that we want English. +} + +QString QGeoTileFetcherNokia::token() const +{ + return m_token; +} + +QString QGeoTileFetcherNokia::applicationId() const +{ + return m_applicationId; +} + +void QGeoTileFetcherNokia::copyrightsFetched() +{ + if (m_engineNokia && m_copyrightsReply->error() == QNetworkReply::NoError) { + QMetaObject::invokeMethod(m_engineNokia.data(), + "loadCopyrightsDescriptorsFromJson", + Qt::QueuedConnection, + Q_ARG(QByteArray, m_copyrightsReply->readAll())); + } + + m_copyrightsReply->deleteLater(); +} + +void QGeoTileFetcherNokia::versionFetched() +{ + if (m_engineNokia && m_versionReply->error() == QNetworkReply::NoError) { + QMetaObject::invokeMethod(m_engineNokia.data(), + "parseNewVersionInfo", + Qt::QueuedConnection, + Q_ARG(QByteArray, m_versionReply->readAll())); + } + + m_versionReply->deleteLater(); +} + +void QGeoTileFetcherNokia::fetchCopyrightsData() +{ + QString copyrightUrl = QStringLiteral("http://"); + + copyrightUrl += m_baseUriProvider->getCurrentHost(); + copyrightUrl += QStringLiteral("/maptile/2.1/copyright/newest?output=json"); + + if (!token().isEmpty()) { + copyrightUrl += QStringLiteral("&token="); + copyrightUrl += token(); + } + + if (!applicationId().isEmpty()) { + copyrightUrl += QStringLiteral("&app_id="); + copyrightUrl += applicationId(); + } + + QNetworkRequest netRequest((QUrl(copyrightUrl))); + m_copyrightsReply = m_networkManager->get(netRequest); + if (m_copyrightsReply->error() != QNetworkReply::NoError) { + qWarning() << __FUNCTION__ << m_copyrightsReply->errorString(); + m_copyrightsReply->deleteLater(); + return; + } + + if (m_copyrightsReply->isFinished()) { + copyrightsFetched(); + } else { + connect(m_copyrightsReply, SIGNAL(finished()), this, SLOT(copyrightsFetched())); + } +} + +void QGeoTileFetcherNokia::fetchVersionData() +{ + QString versionUrl = QStringLiteral("http://"); + + versionUrl += m_baseUriProvider->getCurrentHost(); + versionUrl += QStringLiteral("/maptile/2.1/version"); + + if (!token().isEmpty()) { + versionUrl += QStringLiteral("?token="); + versionUrl += token(); + } + + if (!applicationId().isEmpty()) { + versionUrl += QStringLiteral("&app_id="); + versionUrl += applicationId(); + } + + QNetworkRequest netRequest((QUrl(versionUrl))); + m_versionReply = m_networkManager->get(netRequest); + + if (m_versionReply->error() != QNetworkReply::NoError) { + qWarning() << __FUNCTION__ << m_versionReply->errorString(); + m_versionReply->deleteLater(); + return; + } + + if (m_versionReply->isFinished()) + versionFetched(); + else + connect(m_versionReply, SIGNAL(finished()), this, SLOT(versionFetched())); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h new file mode 100644 index 0000000..44f2ad0 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEFETCHER_NOKIA_H +#define QGEOTILEFETCHER_NOKIA_H + +#include "qgeoserviceproviderplugin_nokia.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoTiledMapReply; +class QGeoTileSpec; +class QGeoTiledMappingManagerEngine; +class QGeoTiledMappingManagerEngineNokia; +class QNetworkReply; +class QGeoNetworkAccessManager; +class QGeoUriProvider; + +class QGeoTileFetcherNokia : public QGeoTileFetcher +{ + Q_OBJECT + +public: + QGeoTileFetcherNokia(const QVariantMap ¶meters, QGeoNetworkAccessManager *networkManager, + QGeoTiledMappingManagerEngineNokia *engine, const QSize &tileSize); + ~QGeoTileFetcherNokia(); + + QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec); + + QString token() const; + QString applicationId() const; + +public Q_SLOTS: + void copyrightsFetched(); + void fetchCopyrightsData(); + void versionFetched(); + void fetchVersionData(); + +private: + Q_DISABLE_COPY(QGeoTileFetcherNokia) + + QString getRequestString(const QGeoTileSpec &spec); + + QString getLanguageString() const; + + QPointer m_engineNokia; + QGeoNetworkAccessManager *m_networkManager; + QSize m_tileSize; + QString m_token; + QNetworkReply *m_copyrightsReply; + QNetworkReply *m_versionReply; + + QString m_applicationId; + QGeoUriProvider *m_baseUriProvider; + QGeoUriProvider *m_aerialUriProvider; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/nokia/qgeouriprovider.cpp b/src/plugins/geoservices/nokia/qgeouriprovider.cpp new file mode 100644 index 0000000..05ace12 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeouriprovider.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeouriprovider.h" + +#ifdef USE_CHINA_NETWORK_REGISTRATION +#include +#endif + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace +{ + const QString CHINA_MCC = QLatin1String("460"); // China mobile country code + const QString CHINA2_MCC = QLatin1String("461"); // China mobile country code + const QString HONG_KONG_MCC = QLatin1String("454"); // Hong Kong mobile country code + const QString MACAU_MCC = QLatin1String("455"); // Macau mobile country code +} + +QGeoUriProvider::QGeoUriProvider( + QObject *parent, + const QVariantMap ¶meters, + const QString &hostParameterName, + const QString &internationalHost, + const QString &localizedHost) + : QObject(parent) +#ifdef USE_CHINA_NETWORK_REGISTRATION + , m_networkInfo(new QNetworkInfo(this)) +#endif + , m_internationalHost(parameters.value(hostParameterName, internationalHost).toString()) + , m_localizedHost(localizedHost) + , m_firstSubdomain(QChar::Null) + , m_maxSubdomains(0) +{ +#ifdef USE_CHINA_NETWORK_REGISTRATION + QObject::connect(m_networkInfo, SIGNAL(currentMobileCountryCodeChanged(int,QString)), this, SLOT(mobileCountryCodeChanged(int,QString))); +#endif + setCurrentHost(isInternationalNetwork() || m_localizedHost.isEmpty() ? m_internationalHost : m_localizedHost); +} + +QString QGeoUriProvider::getCurrentHost() const +{ + if (m_maxSubdomains) { + QString result(m_firstSubdomain.toLatin1() + qrand() % m_maxSubdomains); + result += '.' + m_currentHost; + return result; + } + return m_currentHost; +} + +void QGeoUriProvider::setCurrentHost(const QString &host) +{ + if (host.length() > 4 && host.at(1) == QChar('-') && host.at(3) == QChar('.')) { + QString realHost = host.right(host.length() - 4); + m_firstSubdomain = host.at(0); + m_maxSubdomains = host.at(2).toLatin1() - host.at(0).toLatin1() + 1; + m_currentHost = realHost; + } else { + m_currentHost = host; + m_firstSubdomain = QChar::Null; + m_maxSubdomains = 0; + } +} + +void QGeoUriProvider::mobileCountryCodeChanged(int interface, const QString& mcc) +{ + Q_UNUSED(interface) + Q_UNUSED(mcc) + + setCurrentHost(isInternationalNetwork() || m_localizedHost.isEmpty() ? m_internationalHost : m_localizedHost); +} + +bool QGeoUriProvider::isInternationalNetwork() const +{ +#ifndef USE_CHINA_NETWORK_REGISTRATION + return true; +#else + static QSet codes; + if (codes.empty()) { + codes.insert(CHINA_MCC); + codes.insert(CHINA2_MCC); + } + + QNetworkInfo::NetworkMode mode = m_networkInfo->currentNetworkMode(); + + int interfaces = m_networkInfo->networkInterfaceCount(mode); + for (int i = 0; i < interfaces; ++i) { + QString mcc = m_networkInfo->currentMobileCountryCode(interfaces); + if (codes.contains(mcc)) + return false; + } + + return true; +#endif // USE_CHINA_NETWORK_REGISTRATION +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeouriprovider.h b/src/plugins/geoservices/nokia/qgeouriprovider.h new file mode 100644 index 0000000..1bd30b5 --- /dev/null +++ b/src/plugins/geoservices/nokia/qgeouriprovider.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEO_MOBILE_COUNTRY_TRACKER_H +#define QGEO_MOBILE_COUNTRY_TRACKER_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QNetworkInfo; + +class QGeoUriProvider : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(QGeoUriProvider) + +public: + QGeoUriProvider(QObject *parent, + const QVariantMap ¶meters, + const QString &hostParameterName, + const QString &internationalHost, + const QString &localizedHost = QString()); + + QString getCurrentHost() const; + +private Q_SLOTS: + void mobileCountryCodeChanged(int interface, const QString& mcc); + +private: + bool isInternationalNetwork() const; + void setCurrentHost(const QString &host); + +#ifdef USE_CHINA_NETWORK_REGISTRATION + QNetworkInfo *m_networkInfo; +#endif + const QString m_internationalHost; + const QString m_localizedHost; + QString m_currentHost; + QChar m_firstSubdomain; + unsigned char m_maxSubdomains; +}; + +QT_END_NAMESPACE + +#endif // QGEO_MOBILE_COUNTRY_TRACKER_H diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp new file mode 100644 index 0000000..6dcb28d --- /dev/null +++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp @@ -0,0 +1,863 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacemanagerengine_nokiav2.h" + +#include "placesv2/qplacecategoriesreplyhere.h" +#include "placesv2/qplacecontentreplyimpl.h" +#include "placesv2/qplacesearchsuggestionreplyimpl.h" +#include "placesv2/qplacesearchreplyhere.h" +#include "placesv2/qplacedetailsreplyimpl.h" +#include "placesv2/qplaceidreplyimpl.h" +#include "qgeonetworkaccessmanager.h" +#include "qgeouriprovider.h" +#include "uri_constants.h" +#include "qgeoerror_messages.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +static const char FIXED_CATEGORIES_string[] = + "eat-drink\0" + "going-out\0" + "sights-museums\0" + "transport\0" + "accommodation\0" + "shopping\0" + "leisure-outdoor\0" + "administrative-areas-buildings\0" + "natural-geographical\0" + "petrol-station\0" + "atm-bank-exchange\0" + "toilet-rest-area\0" + "hospital-health-care-facility\0" + "eat-drink|restaurant\0" // subcategories always start after relative parent category + "eat-drink|coffee-tea\0" + "eat-drink|snacks-fast-food\0" + "transport|airport" + "\0"; + +static const int FIXED_CATEGORIES_indices[] = { + 0, 10, 20, 35, 45, 59, 68, 84, + 115, 136, 151, 169, 186, 216, 237, 258, + 285, -1 +}; + +static const char * const NokiaIcon = "nokiaIcon"; +static const char * const IconPrefix = "iconPrefix"; +static const char * const NokiaIconGenerated = "nokiaIconGenerated"; + +static const char * const IconThemeKey = "places.icons.theme"; +static const char * const LocalDataPathKey = "places.local_data_path"; + +class CategoryParser +{ +public: + CategoryParser(); + bool parse(const QString &fileName); + + QPlaceCategoryTree tree() const { return m_tree; } + QHash restIdToIconHash() const { return m_restIdToIconHash; } + + QString errorString() const; + +private: + void processCategory(int level, const QString &id, + const QString &parentId = QString()); + + QJsonObject m_exploreObject; + QPlaceCategoryTree m_tree; + QString m_errorString; + + QHash m_restIdToIconHash; +}; + +CategoryParser::CategoryParser() +{ +} + +bool CategoryParser::parse(const QString &fileName) +{ + m_exploreObject = QJsonObject(); + m_tree.clear(); + m_errorString.clear(); + + QFile mappingFile(fileName); + + if (mappingFile.open(QIODevice::ReadOnly)) { + QJsonDocument document = QJsonDocument::fromJson(mappingFile.readAll()); + if (document.isObject()) { + QJsonObject docObject = document.object(); + if (docObject.contains(QStringLiteral("offline_explore"))) { + m_exploreObject = docObject.value(QStringLiteral("offline_explore")) + .toObject(); + if (m_exploreObject.contains(QStringLiteral("ROOT"))) { + processCategory(0, QString()); + return true; + } + } else { + m_errorString = fileName + + QStringLiteral("does not contain the offline_explore property"); + return false; + } + } else { + m_errorString = fileName + QStringLiteral("is not an json object"); + return false; + } + } + m_errorString = QString::fromLatin1("Unable to open ") + fileName; + return false; +} + +void CategoryParser::processCategory(int level, const QString &id, const QString &parentId) +{ + //We are basing the tree on a DAG from the input file, however we are simplyfing + //this into a 2 level tree, and a given category only has one parent + // + // A->B->Z + // A->C->Z + // Z in this case is not in the tree because it is 3 levels deep. + // + // X->Z + // Y->Z + // Only one of these is shown in the tree since Z can only have one parent + // the choice made between X and Y is arbitrary. + const int maxLevel = 2; + PlaceCategoryNode node; + node.category.setCategoryId(id); + node.parentId = parentId; + + m_tree.insert(node.category.categoryId(), node); + //this is simply to mark the node as being visited. + //a proper assignment to the tree happens at the end of function + + QJsonObject categoryJson = m_exploreObject.value(id.isEmpty() + ? QStringLiteral("ROOT") : id).toObject(); + QJsonArray children = categoryJson.value(QStringLiteral("children")).toArray(); + + if (level + 1 <= maxLevel && !categoryJson.contains(QStringLiteral("final"))) { + for (int i = 0; i < children.count(); ++i) { + QString childId = children.at(i).toString(); + if (!m_tree.contains(childId)) { + node.childIds.append(childId); + processCategory(level + 1, childId, id); + } + } + } + + m_tree.insert(node.category.categoryId(), node); +} + +QPlaceManagerEngineNokiaV2::QPlaceManagerEngineNokiaV2( + QGeoNetworkAccessManager *networkManager, + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) + : QPlaceManagerEngine(parameters) + , m_manager(networkManager) + , m_uriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.places.host"), PLACES_HOST, PLACES_HOST_CN)) +{ + Q_ASSERT(networkManager); + m_manager->setParent(this); + + m_locales.append(QLocale()); + + m_appId = parameters.value(QStringLiteral("here.app_id")).toString(); + m_appCode = parameters.value(QStringLiteral("here.token")).toString(); + + m_theme = parameters.value(IconThemeKey, QString()).toString(); + + if (m_theme == QStringLiteral("default")) + m_theme.clear(); + + m_localDataPath = parameters.value(LocalDataPathKey, QString()).toString(); + if (m_localDataPath.isEmpty()) { + QStringList dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); + + if (!dataLocations.isEmpty() && !dataLocations.first().isEmpty()) { + m_localDataPath = dataLocations.first() + + QStringLiteral("/here/qtlocation/data"); + } + } + + if (error) + *error = QGeoServiceProvider::NoError; + + if (errorString) + errorString->clear(); +} + +QPlaceManagerEngineNokiaV2::~QPlaceManagerEngineNokiaV2() {} + +QPlaceDetailsReply *QPlaceManagerEngineNokiaV2::getPlaceDetails(const QString &placeId) +{ + QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() + + QStringLiteral("/places/v1/places/") + placeId); + + QUrlQuery queryItems; + + queryItems.addQueryItem(QStringLiteral("tf"), QStringLiteral("html")); + //queryItems.append(qMakePair(QStringLiteral("size"), QString::number(5))); + //queryItems.append(qMakePair(QStringLiteral("image_dimensions"), QStringLiteral("w64-h64,w100"))); + + requestUrl.setQuery(queryItems); + + QNetworkReply *networkReply = sendRequest(requestUrl); + + QPlaceDetailsReplyImpl *reply = new QPlaceDetailsReplyImpl(networkReply, this); + reply->setPlaceId(placeId); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + + return reply; +} + +QPlaceContentReply *QPlaceManagerEngineNokiaV2::getPlaceContent(const QPlaceContentRequest &request) +{ + QNetworkReply *networkReply = 0; + + if (request.contentContext().userType() == qMetaTypeId()) { + QUrl u = request.contentContext().value(); + + networkReply = sendRequest(u); + } else { + QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() + + QStringLiteral("/places/v1/places/") + request.placeId() + + QStringLiteral("/media/")); + + QUrlQuery queryItems; + + switch (request.contentType()) { + case QPlaceContent::ImageType: + requestUrl.setPath(requestUrl.path() + QStringLiteral("images")); + + queryItems.addQueryItem(QStringLiteral("tf"), QStringLiteral("html")); + + if (request.limit() > 0) + queryItems.addQueryItem(QStringLiteral("size"), QString::number(request.limit())); + + //queryItems.append(qMakePair(QStringLiteral("image_dimensions"), QStringLiteral("w64-h64,w100"))); + + requestUrl.setQuery(queryItems); + + networkReply = sendRequest(requestUrl); + break; + case QPlaceContent::ReviewType: + requestUrl.setPath(requestUrl.path() + QStringLiteral("reviews")); + + queryItems.addQueryItem(QStringLiteral("tf"), QStringLiteral("html")); + + if (request.limit() > 0) + queryItems.addQueryItem(QStringLiteral("size"), QString::number(request.limit())); + + requestUrl.setQuery(queryItems); + + networkReply = sendRequest(requestUrl); + break; + case QPlaceContent::EditorialType: + requestUrl.setPath(requestUrl.path() + QStringLiteral("editorials")); + + queryItems.addQueryItem(QStringLiteral("tf"), QStringLiteral("html")); + + if (request.limit() > 0) + queryItems.addQueryItem(QStringLiteral("size"), QString::number(request.limit())); + + requestUrl.setQuery(queryItems); + + networkReply = sendRequest(requestUrl); + break; + case QPlaceContent::NoType: + ; + } + } + + QPlaceContentReply *reply = new QPlaceContentReplyImpl(request, networkReply, this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + + if (!networkReply) { + QMetaObject::invokeMethod(reply, "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::UnsupportedError), + Q_ARG(QString, QString("Retrieval of given content type not supported."))); + } + + return reply; +} + +static bool addAtForBoundingArea(const QGeoShape &area, + QUrlQuery *queryItems) +{ + QGeoCoordinate center = area.center(); + if (!center.isValid()) + return false; + + queryItems->addQueryItem(QStringLiteral("at"), + QString::number(center.latitude()) + + QLatin1Char(',') + + QString::number(center.longitude())); + return true; +} + +QPlaceSearchReply *QPlaceManagerEngineNokiaV2::search(const QPlaceSearchRequest &query) +{ + bool unsupported = false; + + unsupported |= query.visibilityScope() != QLocation::UnspecifiedVisibility && + query.visibilityScope() != QLocation::PublicVisibility; + + // Both a search term and search categories are not supported. + unsupported |= !query.searchTerm().isEmpty() && !query.categories().isEmpty(); + + //only a recommendation id by itself is supported. + unsupported |= !query.recommendationId().isEmpty() + && (!query.searchTerm().isEmpty() || !query.categories().isEmpty() + || query.searchArea().type() != QGeoShape::UnknownType); + + if (unsupported) { + QPlaceSearchReplyHere *reply = new QPlaceSearchReplyHere(query, 0, this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + QMetaObject::invokeMethod(reply, "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::BadArgumentError), + Q_ARG(QString, "Unsupported search request options specified.")); + return reply; + } + + QUrlQuery queryItems; + + // Check that the search area is valid for all searches except recommendation and proposed + // searches, which do not need search centers. + if (query.recommendationId().isEmpty() && !query.searchContext().isValid()) { + if (!addAtForBoundingArea(query.searchArea(), &queryItems)) { + QPlaceSearchReplyHere *reply = new QPlaceSearchReplyHere(query, 0, this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + QMetaObject::invokeMethod(reply, "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::BadArgumentError), + Q_ARG(QString, "Invalid search area provided")); + return reply; + } + } + + QNetworkReply *networkReply = 0; + + if (query.searchContext().userType() == qMetaTypeId()) { + // provided search context + QUrl u = query.searchContext().value(); + + typedef QPair QueryItem; + QList queryItemList = queryItems.queryItems(QUrl::FullyEncoded); + queryItems = QUrlQuery(u); + foreach (const QueryItem &item, queryItemList) + queryItems.addQueryItem(item.first, item.second); + + if (query.limit() > 0) + queryItems.addQueryItem(QStringLiteral("size"), QString::number(query.limit())); + + u.setQuery(queryItems); + + networkReply = sendRequest(u); + } else if (!query.searchTerm().isEmpty()) { + // search term query + QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() + + QStringLiteral("/places/v1/discover/search")); + + queryItems.addQueryItem(QStringLiteral("q"), query.searchTerm()); + queryItems.addQueryItem(QStringLiteral("tf"), QStringLiteral("html")); + + if (query.limit() > 0) { + queryItems.addQueryItem(QStringLiteral("size"), + QString::number(query.limit())); + } + + requestUrl.setQuery(queryItems); + + QNetworkReply *networkReply = sendRequest(requestUrl); + + QPlaceSearchReplyHere *reply = new QPlaceSearchReplyHere(query, networkReply, this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + + return reply; + } else if (!query.recommendationId().isEmpty()) { + QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() + + QStringLiteral("/places/v1/places/") + query.recommendationId() + + QStringLiteral("/related/recommended")); + + queryItems.addQueryItem(QStringLiteral("tf"), QStringLiteral("html")); + + requestUrl.setQuery(queryItems); + + networkReply = sendRequest(requestUrl); + } else { + // category search + QUrl requestUrl(QStringLiteral("http://") + m_uriProvider->getCurrentHost() + + QStringLiteral("/places/v1/discover/explore")); + + QStringList ids; + foreach (const QPlaceCategory &category, query.categories()) + ids.append(category.categoryId()); + + QUrlQuery queryItems; + + if (!ids.isEmpty()) + queryItems.addQueryItem(QStringLiteral("cat"), ids.join(QStringLiteral(","))); + + addAtForBoundingArea(query.searchArea(), &queryItems); + + queryItems.addQueryItem(QStringLiteral("tf"), QStringLiteral("html")); + + if (query.limit() > 0) { + queryItems.addQueryItem(QStringLiteral("size"), + QString::number(query.limit())); + } + + requestUrl.setQuery(queryItems); + + networkReply = sendRequest(requestUrl); + } + + QPlaceSearchReplyHere *reply = new QPlaceSearchReplyHere(query, networkReply, this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + + return reply; +} + +QPlaceSearchSuggestionReply *QPlaceManagerEngineNokiaV2::searchSuggestions(const QPlaceSearchRequest &query) +{ + bool unsupported = false; + + unsupported |= query.visibilityScope() != QLocation::UnspecifiedVisibility && + query.visibilityScope() != QLocation::PublicVisibility; + + unsupported |= !query.categories().isEmpty(); + unsupported |= !query.recommendationId().isEmpty(); + + if (unsupported) { + QPlaceSearchSuggestionReplyImpl *reply = new QPlaceSearchSuggestionReplyImpl(0, this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + QMetaObject::invokeMethod(reply, "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::BadArgumentError), + Q_ARG(QString, "Unsupported search request options specified.")); + return reply; + } + + QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() + + QStringLiteral("/places/v1/suggest")); + + QUrlQuery queryItems; + + queryItems.addQueryItem(QStringLiteral("q"), query.searchTerm()); + + if (!addAtForBoundingArea(query.searchArea(), &queryItems)) { + QPlaceSearchSuggestionReplyImpl *reply = new QPlaceSearchSuggestionReplyImpl(0, this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + QMetaObject::invokeMethod(reply, "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::BadArgumentError), + Q_ARG(QString, "Invalid search area provided")); + return reply; + } + + requestUrl.setQuery(queryItems); + + QNetworkReply *networkReply = sendRequest(requestUrl); + + QPlaceSearchSuggestionReplyImpl *reply = new QPlaceSearchSuggestionReplyImpl(networkReply, this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + + return reply; +} + +QPlaceIdReply *QPlaceManagerEngineNokiaV2::savePlace(const QPlace &place) +{ + QPlaceIdReplyImpl *reply = new QPlaceIdReplyImpl(QPlaceIdReply::SavePlace, this); + reply->setId(place.placeId()); + QMetaObject::invokeMethod(reply, "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::UnsupportedError), + Q_ARG(QString, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, SAVING_PLACE_NOT_SUPPORTED))); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + return reply; +} + +QPlaceIdReply *QPlaceManagerEngineNokiaV2::removePlace(const QString &placeId) +{ + QPlaceIdReplyImpl *reply = new QPlaceIdReplyImpl(QPlaceIdReply::RemovePlace, this); + reply->setId(placeId); + QMetaObject::invokeMethod(reply, "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::UnsupportedError), + Q_ARG(QString, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, REMOVING_PLACE_NOT_SUPPORTED))); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + return reply; +} + +QPlaceIdReply *QPlaceManagerEngineNokiaV2::saveCategory(const QPlaceCategory &category, const QString &parentId) +{ + Q_UNUSED(parentId) + + QPlaceIdReplyImpl *reply = new QPlaceIdReplyImpl(QPlaceIdReply::SaveCategory, this); + reply->setId(category.categoryId()); + QMetaObject::invokeMethod(reply, "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::UnsupportedError), + Q_ARG(QString, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, SAVING_CATEGORY_NOT_SUPPORTED))); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + return reply; +} + +QPlaceIdReply *QPlaceManagerEngineNokiaV2::removeCategory(const QString &categoryId) +{ + QPlaceIdReplyImpl *reply = new QPlaceIdReplyImpl(QPlaceIdReply::RemoveCategory, this); + reply->setId(categoryId); + QMetaObject::invokeMethod(reply, "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::UnsupportedError), + Q_ARG(QString, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, REMOVING_CATEGORY_NOT_SUPPORTED))); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + return reply; +} + +QPlaceReply *QPlaceManagerEngineNokiaV2::initializeCategories() +{ + if (m_categoryReply) + return m_categoryReply.data(); + + m_tempTree.clear(); + CategoryParser parser; + + if (parser.parse(m_localDataPath + QStringLiteral("/offline/offline-mapping.json"))) { + m_tempTree = parser.tree(); + } else { + PlaceCategoryNode rootNode; + + for (int i = 0; FIXED_CATEGORIES_indices[i] != -1; ++i) { + const QString id = QString::fromLatin1(FIXED_CATEGORIES_string + + FIXED_CATEGORIES_indices[i]); + + int subCatDivider = id.indexOf(QChar('|')); + if (subCatDivider >= 0) { + // found a sub category + const QString subCategoryId = id.mid(subCatDivider+1); + const QString parentCategoryId = id.left(subCatDivider); + + if (m_tempTree.contains(parentCategoryId)) { + PlaceCategoryNode node; + node.category.setCategoryId(subCategoryId); + node.parentId = parentCategoryId; + + // find parent + PlaceCategoryNode &parent = m_tempTree[parentCategoryId]; + parent.childIds.append(subCategoryId); + m_tempTree.insert(subCategoryId, node); + } + + } else { + PlaceCategoryNode node; + node.category.setCategoryId(id); + + m_tempTree.insert(id, node); + rootNode.childIds.append(id); + } + } + + m_tempTree.insert(QString(), rootNode); + } + + //request all categories in the tree from the server + //because we don't want the root node, we skip it + for (auto it = m_tempTree.keyBegin(), end = m_tempTree.keyEnd(); it != end; ++it) { + if (*it == QString()) + continue; + QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() + + QStringLiteral("/places/v1/categories/places/") + *it); + QNetworkReply *networkReply = sendRequest(requestUrl); + connect(networkReply, SIGNAL(finished()), this, SLOT(categoryReplyFinished())); + connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(categoryReplyError())); + + m_categoryRequests.insert(*it, networkReply); + } + + QPlaceCategoriesReplyHere *reply = new QPlaceCategoriesReplyHere(this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + + m_categoryReply = reply; + return reply; +} + +QString QPlaceManagerEngineNokiaV2::parentCategoryId(const QString &categoryId) const +{ + return m_categoryTree.value(categoryId).parentId; +} + +QStringList QPlaceManagerEngineNokiaV2::childCategoryIds(const QString &categoryId) const +{ + return m_categoryTree.value(categoryId).childIds; +} + +QPlaceCategory QPlaceManagerEngineNokiaV2::category(const QString &categoryId) const +{ + return m_categoryTree.value(categoryId).category; +} + +QList QPlaceManagerEngineNokiaV2::childCategories(const QString &parentId) const +{ + QList results; + foreach (const QString &childId, m_categoryTree.value(parentId).childIds) + results.append(m_categoryTree.value(childId).category); + return results; +} + +QList QPlaceManagerEngineNokiaV2::locales() const +{ + return m_locales; +} + +void QPlaceManagerEngineNokiaV2::setLocales(const QList &locales) +{ + m_locales = locales; +} + +QPlaceIcon QPlaceManagerEngineNokiaV2::icon(const QString &remotePath, + const QList &categories) const +{ + QPlaceIcon icon; + QVariantMap params; + + QRegExp rx("(.*)(/icons/categories/.*)"); + + QString iconPrefix; + QString nokiaIcon; + if (rx.indexIn(remotePath) != -1 && !rx.cap(1).isEmpty() && !rx.cap(2).isEmpty()) { + iconPrefix = rx.cap(1); + nokiaIcon = rx.cap(2); + + if (QFile::exists(m_localDataPath + nokiaIcon)) + iconPrefix = QString::fromLatin1("file://") + m_localDataPath; + + params.insert(NokiaIcon, nokiaIcon); + params.insert(IconPrefix, iconPrefix); + + foreach (const QPlaceCategory &category, categories) { + if (category.icon().parameters().value(NokiaIcon) == nokiaIcon) { + params.insert(NokiaIconGenerated, true); + break; + } + } + } else { + QString path = remotePath + (!m_theme.isEmpty() + ? QLatin1Char('.') + m_theme : QString()); + params.insert(QPlaceIcon::SingleUrl, QUrl(path)); + + if (!nokiaIcon.isEmpty()) { + params.insert(NokiaIcon, nokiaIcon); + params.insert(IconPrefix, iconPrefix); + params.insert(NokiaIconGenerated, true); + } + } + + icon.setParameters(params); + + if (!icon.isEmpty()) + icon.setManager(manager()); + + return icon; +} + +QUrl QPlaceManagerEngineNokiaV2::constructIconUrl(const QPlaceIcon &icon, + const QSize &size) const +{ + Q_UNUSED(size) + QVariantMap params = icon.parameters(); + QString nokiaIcon = params.value(NokiaIcon).toString(); + + if (!nokiaIcon.isEmpty()) { + nokiaIcon.append(!m_theme.isEmpty() ? + QLatin1Char('.') + m_theme : QString()); + + if (params.contains(IconPrefix)) { + return QUrl(params.value(IconPrefix).toString() + + nokiaIcon); + } else { + return QUrl(QString::fromLatin1("file://") + m_localDataPath + + nokiaIcon); + } + } + + return QUrl(); +} + +void QPlaceManagerEngineNokiaV2::replyFinished() +{ + QPlaceReply *reply = qobject_cast(sender()); + if (reply) + emit finished(reply); +} + +void QPlaceManagerEngineNokiaV2::replyError(QPlaceReply::Error error_, const QString &errorString) +{ + QPlaceReply *reply = qobject_cast(sender()); + if (reply) + emit error(reply, error_, errorString); +} + +void QPlaceManagerEngineNokiaV2::categoryReplyFinished() +{ + QNetworkReply *reply = qobject_cast(sender()); + if (!reply) + return; + + QString categoryId; + + if (reply->error() == QNetworkReply::NoError) { + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + if (!document.isObject()) { + if (m_categoryReply) { + QMetaObject::invokeMethod(m_categoryReply.data(), "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::ParseError), + Q_ARG(QString, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR))); + } + return; + } + + QJsonObject category = document.object(); + + categoryId = category.value(QStringLiteral("categoryId")).toString(); + if (m_tempTree.contains(categoryId)) { + PlaceCategoryNode node = m_tempTree.value(categoryId); + node.category.setName(category.value(QStringLiteral("name")).toString()); + node.category.setCategoryId(categoryId); + node.category.setIcon(icon(category.value(QStringLiteral("icon")).toString())); + + m_tempTree.insert(categoryId, node); + } + } else { + categoryId = m_categoryRequests.key(reply); + PlaceCategoryNode rootNode = m_tempTree.value(QString()); + rootNode.childIds.removeAll(categoryId); + m_tempTree.insert(QString(), rootNode); + m_tempTree.remove(categoryId); + } + + m_categoryRequests.remove(categoryId); + reply->deleteLater(); + + if (m_categoryRequests.isEmpty()) { + m_categoryTree = m_tempTree; + m_tempTree.clear(); + + if (m_categoryReply) + m_categoryReply.data()->emitFinished(); + } +} + +void QPlaceManagerEngineNokiaV2::categoryReplyError() +{ + if (m_categoryReply) { + QMetaObject::invokeMethod(m_categoryReply.data(), "setError", Qt::QueuedConnection, + Q_ARG(QPlaceReply::Error, QPlaceReply::CommunicationError), + Q_ARG(QString, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, NETWORK_ERROR))); + } +} + +QNetworkReply *QPlaceManagerEngineNokiaV2::sendRequest(const QUrl &url) +{ + QUrlQuery queryItems(url); + queryItems.addQueryItem(QStringLiteral("app_id"), m_appId); + queryItems.addQueryItem(QStringLiteral("app_code"), m_appCode); + + QUrl requestUrl = url; + requestUrl.setQuery(queryItems); + + QNetworkRequest request; + request.setUrl(requestUrl); + + request.setRawHeader("Accept", "application/json"); + request.setRawHeader("Accept-Language", createLanguageString()); + + return m_manager->get(request); +} + +QByteArray QPlaceManagerEngineNokiaV2::createLanguageString() const +{ + QByteArray language; + + QList locales = m_locales; + if (locales.isEmpty()) + locales << QLocale(); + + foreach (const QLocale &loc, locales) { + language.append(loc.name().replace(2, 1, QLatin1Char('-')).toLatin1()); + language.append(", "); + } + language.chop(2); + + return language; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h new file mode 100644 index 0000000..fe2e537 --- /dev/null +++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEMANAGERENGINE_NOKIAV2_H +#define QPLACEMANAGERENGINE_NOKIAV2_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlaceContentReply; +class QNetworkReply; +class QNetworkAccessManager; +class QPlaceCategoriesReplyHere; +class QGeoNetworkAccessManager; +class QGeoUriProvider; + +struct PlaceCategoryNode +{ + QString parentId; + QStringList childIds; + QPlaceCategory category; +}; + +typedef QMap QPlaceCategoryTree; + +class QPlaceManagerEngineNokiaV2 : public QPlaceManagerEngine +{ + Q_OBJECT + +public: + QPlaceManagerEngineNokiaV2(QGeoNetworkAccessManager *networkManager, + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString); + ~QPlaceManagerEngineNokiaV2(); + + QPlaceDetailsReply *getPlaceDetails(const QString &placeId) Q_DECL_OVERRIDE; + + QPlaceContentReply *getPlaceContent(const QPlaceContentRequest &request) Q_DECL_OVERRIDE; + + QPlaceSearchReply *search(const QPlaceSearchRequest &query) Q_DECL_OVERRIDE; + + QPlaceSearchSuggestionReply *searchSuggestions(const QPlaceSearchRequest &query) Q_DECL_OVERRIDE; + + QPlaceIdReply *savePlace(const QPlace &place) Q_DECL_OVERRIDE; + QPlaceIdReply *removePlace(const QString &placeId) Q_DECL_OVERRIDE; + + QPlaceIdReply *saveCategory(const QPlaceCategory &category, const QString &parentId) Q_DECL_OVERRIDE; + QPlaceIdReply *removeCategory(const QString &categoryId) Q_DECL_OVERRIDE; + + QPlaceReply *initializeCategories() Q_DECL_OVERRIDE; + QString parentCategoryId(const QString &categoryId) const Q_DECL_OVERRIDE; + QStringList childCategoryIds(const QString &categoryId) const Q_DECL_OVERRIDE; + QPlaceCategory category(const QString &categoryId) const Q_DECL_OVERRIDE; + QList childCategories(const QString &parentId) const Q_DECL_OVERRIDE; + + QList locales() const Q_DECL_OVERRIDE; + void setLocales(const QList &locales) Q_DECL_OVERRIDE; + + QPlaceIcon icon(const QString &remotePath, + const QList &categories = QList()) const; + + QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size) const Q_DECL_OVERRIDE; + +private: + QNetworkReply *sendRequest(const QUrl &url); + QByteArray createLanguageString() const; + +private Q_SLOTS: + void replyFinished(); + void replyError(QPlaceReply::Error error_, const QString &errorString); + void categoryReplyFinished(); + void categoryReplyError(); + +private: + QGeoNetworkAccessManager *m_manager; + QGeoUriProvider *m_uriProvider; + + QList m_locales; + + QPlaceCategoryTree m_categoryTree; + QPlaceCategoryTree m_tempTree; + QHash m_restIdToIconHash; + + QPointer m_categoryReply; + QHash m_categoryRequests; + + QString m_appId; + QString m_appCode; + + QString m_localDataPath; + QString m_theme; +}; + +QT_END_NAMESPACE + +#endif // QPLACEMANAGERENGINE_NOKIAV2_H diff --git a/src/plugins/geoservices/nokia/resource.qrc b/src/plugins/geoservices/nokia/resource.qrc new file mode 100644 index 0000000..d48a6ca --- /dev/null +++ b/src/plugins/geoservices/nokia/resource.qrc @@ -0,0 +1,5 @@ + + + logo.png + + diff --git a/src/plugins/geoservices/nokia/uri_constants.cpp b/src/plugins/geoservices/nokia/uri_constants.cpp new file mode 100644 index 0000000..8a07532 --- /dev/null +++ b/src/plugins/geoservices/nokia/uri_constants.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "uri_constants.h" + +QT_BEGIN_NAMESPACE + +const QString ROUTING_HOST = QLatin1String("route.api.here.com"); +const QString GEOCODING_HOST = QLatin1String("loc.desktop.maps.svc.ovi.com"); +const QString GEOCODING_HOST_CN = QLatin1String("pr.geo.maps.svc.nokia.com.cn"); +const QString PLACES_HOST = QLatin1String("places.api.here.com"); +const QString PLACES_HOST_CN = QLatin1String("places.nlp.nokia.com.cn"); +const QString MAP_TILES_HOST = QLatin1String("1-4.base.maps.api.here.com"); +const QString MAP_TILES_HOST_AERIAL = QLatin1String("1-4.aerial.maps.api.here.com"); + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/uri_constants.h b/src/plugins/geoservices/nokia/uri_constants.h new file mode 100644 index 0000000..151a4aa --- /dev/null +++ b/src/plugins/geoservices/nokia/uri_constants.h @@ -0,0 +1,54 @@ + +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef URI_CONSTANTS_H +#define URI_CONSTANTS_H + +#include + +QT_BEGIN_NAMESPACE + +extern const QString ROUTING_HOST; +extern const QString GEOCODING_HOST; +extern const QString GEOCODING_HOST_CN; +extern const QString PLACES_HOST; +extern const QString PLACES_HOST_CN; +extern const QString MAP_TILES_HOST; +extern const QString MAP_TILES_HOST_AERIAL; + +QT_END_NAMESPACE + +#endif // URI_CONSTANTS_H diff --git a/src/plugins/geoservices/osm/osm.pro b/src/plugins/geoservices/osm/osm.pro new file mode 100644 index 0000000..56f4cb3 --- /dev/null +++ b/src/plugins/geoservices/osm/osm.pro @@ -0,0 +1,41 @@ +TARGET = qtgeoservices_osm + +QT += location-private positioning-private network + +HEADERS += \ + qgeoserviceproviderpluginosm.h \ + qgeotiledmappingmanagerengineosm.h \ + qgeotilefetcherosm.h \ + qgeomapreplyosm.h \ + qgeocodingmanagerengineosm.h \ + qgeocodereplyosm.h \ + qgeoroutingmanagerengineosm.h \ + qgeoroutereplyosm.h \ + qplacemanagerengineosm.h \ + qplacesearchreplyosm.h \ + qplacecategoriesreplyosm.h \ + qgeotiledmaposm.h \ + qgeotileproviderosm.h + +SOURCES += \ + qgeoserviceproviderpluginosm.cpp \ + qgeotiledmappingmanagerengineosm.cpp \ + qgeotilefetcherosm.cpp \ + qgeomapreplyosm.cpp \ + qgeocodingmanagerengineosm.cpp \ + qgeocodereplyosm.cpp \ + qgeoroutingmanagerengineosm.cpp \ + qgeoroutereplyosm.cpp \ + qplacemanagerengineosm.cpp \ + qplacesearchreplyosm.cpp \ + qplacecategoriesreplyosm.cpp \ + qgeotiledmaposm.cpp \ + qgeotileproviderosm.cpp + + +OTHER_FILES += \ + osm_plugin.json + +PLUGIN_TYPE = geoservices +PLUGIN_CLASS_NAME = QGeoServiceProviderFactoryOsm +load(qt_plugin) diff --git a/src/plugins/geoservices/osm/osm_plugin.json b/src/plugins/geoservices/osm/osm_plugin.json new file mode 100644 index 0000000..1aaf6f7 --- /dev/null +++ b/src/plugins/geoservices/osm/osm_plugin.json @@ -0,0 +1,13 @@ +{ + "Keys": ["osm"], + "Provider": "osm", + "Version": 100, + "Experimental": false, + "Features": [ + "OnlineMappingFeature", + "OnlineGeocodingFeature", + "ReverseGeocodingFeature", + "OnlineRoutingFeature", + "OnlinePlacesFeature" + ] +} diff --git a/src/plugins/geoservices/osm/qgeocodereplyosm.cpp b/src/plugins/geoservices/osm/qgeocodereplyosm.cpp new file mode 100644 index 0000000..15b1724 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeocodereplyosm.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocodereplyosm.h" + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGeoCodeReplyOsm::QGeoCodeReplyOsm(QNetworkReply *reply, QObject *parent) +: QGeoCodeReply(parent), m_reply(reply) +{ + connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + + setLimit(1); + setOffset(0); +} + +QGeoCodeReplyOsm::~QGeoCodeReplyOsm() +{ + if (m_reply) + m_reply->deleteLater(); +} + +void QGeoCodeReplyOsm::abort() +{ + if (!m_reply) + return; + + m_reply->abort(); + + m_reply->deleteLater(); + m_reply = 0; +} + +static QGeoAddress parseAddressObject(const QJsonObject &object) +{ + QGeoAddress address; + address.setText(object.value(QStringLiteral("display_name")).toString()); + QJsonObject ao = object.value(QStringLiteral("address")).toObject(); + // setCountry + address.setCountry(ao.value(QStringLiteral("country")).toString()); + // setCountryCode + address.setCountryCode(ao.value(QStringLiteral("country_code")).toString()); + // setState + address.setState(ao.value(QStringLiteral("state")).toString()); + // setCity + if (ao.contains(QLatin1String("city"))) + address.setCity(ao.value(QStringLiteral("city")).toString()); + else if (ao.contains(QLatin1String("town"))) + address.setCity(ao.value(QLatin1String("town")).toString()); + else if (ao.contains(QLatin1String("village"))) + address.setCity(ao.value(QLatin1String("village")).toString()); + else + address.setCity(ao.value(QLatin1String("hamlet")).toString()); + // setDistrict + address.setDistrict(ao.value(QStringLiteral("suburb")).toString()); + // setPostalCode + address.setPostalCode(ao.value(QStringLiteral("postcode")).toString()); + // setStreet + address.setStreet(ao.value(QStringLiteral("road")).toString()); + return address; +} + +void QGeoCodeReplyOsm::networkReplyFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() != QNetworkReply::NoError) + return; + + QList locations; + QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + + if (document.isObject()) { + QJsonObject object = document.object(); + + QGeoCoordinate coordinate; + + coordinate.setLatitude(object.value(QStringLiteral("lat")).toString().toDouble()); + coordinate.setLongitude(object.value(QStringLiteral("lon")).toString().toDouble()); + + QGeoLocation location; + location.setCoordinate(coordinate); + location.setAddress(parseAddressObject(object)); + + locations.append(location); + + setLocations(locations); + } else if (document.isArray()) { + QJsonArray results = document.array(); + + for (int i = 0; i < results.count(); ++i) { + if (!results.at(i).isObject()) + continue; + + QJsonObject object = results.at(i).toObject(); + + QGeoCoordinate coordinate; + + coordinate.setLatitude(object.value(QStringLiteral("lat")).toString().toDouble()); + coordinate.setLongitude(object.value(QStringLiteral("lon")).toString().toDouble()); + + QGeoRectangle rectangle; + + if (object.contains(QStringLiteral("boundingbox"))) { + QJsonArray a = object.value(QStringLiteral("boundingbox")).toArray(); + if (a.count() == 4) { + rectangle.setTopLeft(QGeoCoordinate(a.at(1).toString().toDouble(), + a.at(2).toString().toDouble())); + rectangle.setBottomRight(QGeoCoordinate(a.at(0).toString().toDouble(), + a.at(3).toString().toDouble())); + } + } + + QGeoLocation location; + location.setCoordinate(coordinate); + location.setBoundingBox(rectangle); + location.setAddress(parseAddressObject(object)); + locations.append(location); + } + + } + + setLocations(locations); + setFinished(true); + + m_reply->deleteLater(); + m_reply = 0; +} + +void QGeoCodeReplyOsm::networkReplyError(QNetworkReply::NetworkError error) +{ + Q_UNUSED(error) + + if (!m_reply) + return; + + setError(QGeoCodeReply::CommunicationError, m_reply->errorString()); + + m_reply->deleteLater(); + m_reply = 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeocodereplyosm.h b/src/plugins/geoservices/osm/qgeocodereplyosm.h new file mode 100644 index 0000000..2772910 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeocodereplyosm.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODEREPLYOSM_H +#define QGEOCODEREPLYOSM_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoCodeReplyOsm : public QGeoCodeReply +{ + Q_OBJECT + +public: + explicit QGeoCodeReplyOsm(QNetworkReply *reply, QObject *parent = 0); + ~QGeoCodeReplyOsm(); + + void abort(); + +private Q_SLOTS: + void networkReplyFinished(); + void networkReplyError(QNetworkReply::NetworkError error); + +private: + QNetworkReply *m_reply; +}; + +QT_END_NAMESPACE + +#endif // QGEOCODEREPLYOSM_H diff --git a/src/plugins/geoservices/osm/qgeocodingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeocodingmanagerengineosm.cpp new file mode 100644 index 0000000..693a80a --- /dev/null +++ b/src/plugins/geoservices/osm/qgeocodingmanagerengineosm.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocodingmanagerengineosm.h" +#include "qgeocodereplyosm.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static QString addressToQuery(const QGeoAddress &address) +{ + return address.street() + QStringLiteral(", ") + + address.district() + QStringLiteral(", ") + + address.city() + QStringLiteral(", ") + + address.state() + QStringLiteral(", ") + + address.country(); +} + +static QString boundingBoxToLtrb(const QGeoRectangle &rect) +{ + return QString::number(rect.topLeft().longitude()) + QLatin1Char(',') + + QString::number(rect.topLeft().latitude()) + QLatin1Char(',') + + QString::number(rect.bottomRight().longitude()) + QLatin1Char(',') + + QString::number(rect.bottomRight().latitude()); +} + +QGeoCodingManagerEngineOsm::QGeoCodingManagerEngineOsm(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) +: QGeoCodingManagerEngine(parameters), m_networkManager(new QNetworkAccessManager(this)) +{ + if (parameters.contains(QStringLiteral("osm.useragent"))) + m_userAgent = parameters.value(QStringLiteral("osm.useragent")).toString().toLatin1(); + else + m_userAgent = "Qt Location based application"; + + if (parameters.contains(QStringLiteral("osm.geocoding.host"))) + m_urlPrefix = parameters.value(QStringLiteral("osm.geocoding.host")).toString().toLatin1(); + else + m_urlPrefix = QStringLiteral("http://nominatim.openstreetmap.org"); + + *error = QGeoServiceProvider::NoError; + errorString->clear(); +} + +QGeoCodingManagerEngineOsm::~QGeoCodingManagerEngineOsm() +{ +} + +QGeoCodeReply *QGeoCodingManagerEngineOsm::geocode(const QGeoAddress &address, const QGeoShape &bounds) +{ + return geocode(addressToQuery(address), -1, -1, bounds); +} + +QGeoCodeReply *QGeoCodingManagerEngineOsm::geocode(const QString &address, int limit, int offset, const QGeoShape &bounds) +{ + Q_UNUSED(offset) + + QNetworkRequest request; + request.setRawHeader("User-Agent", m_userAgent); + + QUrl url(QString("%1/search").arg(m_urlPrefix)); + QUrlQuery query; + query.addQueryItem(QStringLiteral("q"), address); + query.addQueryItem(QStringLiteral("format"), QStringLiteral("json")); + query.addQueryItem(QStringLiteral("accept-language"), locale().name().left(2)); + //query.addQueryItem(QStringLiteral("countrycodes"), QStringLiteral("au,jp")); + if (bounds.type() == QGeoShape::RectangleType) { + query.addQueryItem(QStringLiteral("viewbox"), boundingBoxToLtrb(bounds)); + query.addQueryItem(QStringLiteral("bounded"), QStringLiteral("1")); + } + query.addQueryItem(QStringLiteral("polygon_geojson"), QStringLiteral("1")); + query.addQueryItem(QStringLiteral("addressdetails"), QStringLiteral("1")); + if (limit != -1) + query.addQueryItem(QStringLiteral("limit"), QString::number(limit)); + + url.setQuery(query); + request.setUrl(url); + + QNetworkReply *reply = m_networkManager->get(request); + + QGeoCodeReplyOsm *geocodeReply = new QGeoCodeReplyOsm(reply, this); + + connect(geocodeReply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(geocodeReply, SIGNAL(error(QGeoCodeReply::Error,QString)), + this, SLOT(replyError(QGeoCodeReply::Error,QString))); + + return geocodeReply; +} + +QGeoCodeReply *QGeoCodingManagerEngineOsm::reverseGeocode(const QGeoCoordinate &coordinate, + const QGeoShape &bounds) +{ + Q_UNUSED(bounds) + + QNetworkRequest request; + request.setRawHeader("User-Agent", m_userAgent); + + QUrl url(QString("%1/reverse").arg(m_urlPrefix)); + QUrlQuery query; + query.addQueryItem(QStringLiteral("format"), QStringLiteral("json")); + query.addQueryItem(QStringLiteral("accept-language"), locale().name().left(2)); + query.addQueryItem(QStringLiteral("lat"), QString::number(coordinate.latitude())); + query.addQueryItem(QStringLiteral("lon"), QString::number(coordinate.longitude())); + query.addQueryItem(QStringLiteral("zoom"), QStringLiteral("18")); + query.addQueryItem(QStringLiteral("addressdetails"), QStringLiteral("1")); + + url.setQuery(query); + request.setUrl(url); + + QNetworkReply *reply = m_networkManager->get(request); + + QGeoCodeReplyOsm *geocodeReply = new QGeoCodeReplyOsm(reply, this); + + connect(geocodeReply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(geocodeReply, SIGNAL(error(QGeoCodeReply::Error,QString)), + this, SLOT(replyError(QGeoCodeReply::Error,QString))); + + return geocodeReply; +} + +void QGeoCodingManagerEngineOsm::replyFinished() +{ + QGeoCodeReply *reply = qobject_cast(sender()); + if (reply) + emit finished(reply); +} + +void QGeoCodingManagerEngineOsm::replyError(QGeoCodeReply::Error errorCode, const QString &errorString) +{ + QGeoCodeReply *reply = qobject_cast(sender()); + if (reply) + emit error(reply, errorCode, errorString); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeocodingmanagerengineosm.h b/src/plugins/geoservices/osm/qgeocodingmanagerengineosm.h new file mode 100644 index 0000000..4eea2cd --- /dev/null +++ b/src/plugins/geoservices/osm/qgeocodingmanagerengineosm.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODINGMANAGERENGINEOSM_H +#define QGEOCODINGMANAGERENGINEOSM_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QNetworkAccessManager; + +class QGeoCodingManagerEngineOsm : public QGeoCodingManagerEngine +{ + Q_OBJECT + +public: + QGeoCodingManagerEngineOsm(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, + QString *errorString); + ~QGeoCodingManagerEngineOsm(); + + QGeoCodeReply *geocode(const QGeoAddress &address, const QGeoShape &bounds) Q_DECL_OVERRIDE; + QGeoCodeReply *geocode(const QString &address, int limit, int offset, + const QGeoShape &bounds) Q_DECL_OVERRIDE; + QGeoCodeReply *reverseGeocode(const QGeoCoordinate &coordinate, + const QGeoShape &bounds) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void replyFinished(); + void replyError(QGeoCodeReply::Error errorCode, const QString &errorString); + +private: + QNetworkAccessManager *m_networkManager; + QByteArray m_userAgent; + QString m_urlPrefix; +}; + +QT_END_NAMESPACE + +#endif // QGEOCODINGMANAGERENGINEOSM_H diff --git a/src/plugins/geoservices/osm/qgeomapreplyosm.cpp b/src/plugins/geoservices/osm/qgeomapreplyosm.cpp new file mode 100644 index 0000000..052ed35 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeomapreplyosm.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomapreplyosm.h" + +#include + +QGeoMapReplyOsm::QGeoMapReplyOsm(QNetworkReply *reply, + const QGeoTileSpec &spec, + const QString &imageFormat, + QObject *parent) +: QGeoTiledMapReply(spec, parent), m_reply(reply) +{ + connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + setMapImageFormat(imageFormat); +} + +QGeoMapReplyOsm::~QGeoMapReplyOsm() +{ + if (m_reply) { + m_reply->deleteLater(); + m_reply = 0; + } +} + +void QGeoMapReplyOsm::abort() +{ + if (!m_reply) + return; + + m_reply->abort(); +} + +QNetworkReply *QGeoMapReplyOsm::networkReply() const +{ + return m_reply; +} + +void QGeoMapReplyOsm::networkReplyFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() != QNetworkReply::NoError) { + m_reply->deleteLater(); + m_reply = 0; + return; + } + + QByteArray a = m_reply->readAll(); + + setMapImageData(a); + setFinished(true); + + m_reply->deleteLater(); + m_reply = 0; +} + +void QGeoMapReplyOsm::networkReplyError(QNetworkReply::NetworkError error) +{ + if (!m_reply) + return; + + if (error != QNetworkReply::OperationCanceledError) + setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); + + setFinished(true); + m_reply->deleteLater(); + m_reply = 0; +} diff --git a/src/plugins/geoservices/osm/qgeomapreplyosm.h b/src/plugins/geoservices/osm/qgeomapreplyosm.h new file mode 100644 index 0000000..804a0a2 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeomapreplyosm.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPREPLYOSM_H +#define QGEOMAPREPLYOSM_H + +#include "qgeotilefetcherosm.h" +#include "qgeotileproviderosm.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMapReplyOsm : public QGeoTiledMapReply +{ + Q_OBJECT + +public: + QGeoMapReplyOsm(QNetworkReply *reply, const QGeoTileSpec &spec, const QString &imageFormat, QObject *parent = 0); + ~QGeoMapReplyOsm(); + + void abort(); + + QNetworkReply *networkReply() const; + +private Q_SLOTS: + void networkReplyFinished(); + void networkReplyError(QNetworkReply::NetworkError error); + +private: + QPointer m_reply; +}; + +QT_END_NAMESPACE + +#endif // QGEOMAPREPLYOSM_H diff --git a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp new file mode 100644 index 0000000..da28317 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroutereplyosm.h" +#include "qgeoroutingmanagerengineosm.h" + +QT_BEGIN_NAMESPACE + +QGeoRouteReplyOsm::QGeoRouteReplyOsm(QNetworkReply *reply, const QGeoRouteRequest &request, + QObject *parent) +: QGeoRouteReply(request, parent), m_reply(reply) +{ + connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkReplyError(QNetworkReply::NetworkError))); +} + +QGeoRouteReplyOsm::~QGeoRouteReplyOsm() +{ + if (m_reply) + m_reply->deleteLater(); +} + +void QGeoRouteReplyOsm::abort() +{ + if (!m_reply) + return; + + m_reply->abort(); + + m_reply->deleteLater(); + m_reply = 0; +} + +void QGeoRouteReplyOsm::networkReplyFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() != QNetworkReply::NoError) { + setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); + m_reply->deleteLater(); + m_reply = 0; + return; + } + + if (m_reply->error() != QNetworkReply::NoError) { + setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); + m_reply->deleteLater(); + m_reply = 0; + return; + } + + QGeoRoutingManagerEngineOsm *engine = qobject_cast(parent()); + const QGeoRouteParser *parser = engine->routeParser(); + + QList routes; + QString errorString; + QGeoRouteReply::Error error = parser->parseReply(routes, errorString, m_reply->readAll()); + + if (error == QGeoRouteReply::NoError) { + setRoutes(routes.mid(0,1)); // TODO QTBUG-56426 + // setError(QGeoRouteReply::NoError, status); // can't do this, or NoError is emitted and does damages + setFinished(true); + } else { + setError(error, errorString); + } + + m_reply->deleteLater(); + m_reply = 0; +} + +void QGeoRouteReplyOsm::networkReplyError(QNetworkReply::NetworkError error) +{ + Q_UNUSED(error) + + if (!m_reply) + return; + + setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); + + m_reply->deleteLater(); + m_reply = 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeoroutereplyosm.h b/src/plugins/geoservices/osm/qgeoroutereplyosm.h new file mode 100644 index 0000000..8733c15 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeoroutereplyosm.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTEREPLYOSM_H +#define QGEOROUTEREPLYOSM_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoRouteReplyOsm : public QGeoRouteReply +{ + Q_OBJECT + +public: + explicit QGeoRouteReplyOsm(QObject *parent = 0); + QGeoRouteReplyOsm(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent = 0); + ~QGeoRouteReplyOsm(); + + void abort() Q_DECL_OVERRIDE; + +private Q_SLOTS: + void networkReplyFinished(); + void networkReplyError(QNetworkReply::NetworkError error); + +private: + QNetworkReply *m_reply; +}; + +QT_END_NAMESPACE + +#endif // QGEOROUTEREPLYOSM_H + diff --git a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp new file mode 100644 index 0000000..12db22a --- /dev/null +++ b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroutingmanagerengineosm.h" +#include "qgeoroutereplyosm.h" +#include "QtLocation/private/qgeorouteparserosrmv4_p.h" +#include "QtLocation/private/qgeorouteparserosrmv5_p.h" + +#include + +#include + +QGeoRoutingManagerEngineOsm::QGeoRoutingManagerEngineOsm(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) +: QGeoRoutingManagerEngine(parameters), m_networkManager(new QNetworkAccessManager(this)) +{ + if (parameters.contains(QStringLiteral("osm.useragent"))) + m_userAgent = parameters.value(QStringLiteral("osm.useragent")).toString().toLatin1(); + else + m_userAgent = "Qt Location based application"; + + if (parameters.contains(QStringLiteral("osm.routing.host"))) + m_urlPrefix = parameters.value(QStringLiteral("osm.routing.host")).toString().toLatin1(); + else + m_urlPrefix = QStringLiteral("http://router.project-osrm.org/route/v1/driving/"); + // for v4 it was "http://router.project-osrm.org/viaroute" + + if (parameters.contains(QStringLiteral("osm.routing.apiversion")) + && (parameters.value(QStringLiteral("osm.routing.apiversion")).toString().toLatin1() == QByteArray("v4"))) + m_routeParser = new QGeoRouteParserOsrmV4(this); + else + m_routeParser = new QGeoRouteParserOsrmV5(this); + + *error = QGeoServiceProvider::NoError; + errorString->clear(); +} + +QGeoRoutingManagerEngineOsm::~QGeoRoutingManagerEngineOsm() +{ +} + +QGeoRouteReply* QGeoRoutingManagerEngineOsm::calculateRoute(const QGeoRouteRequest &request) +{ + QNetworkRequest networkRequest; + networkRequest.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent); + + networkRequest.setUrl(routeParser()->requestUrl(request, m_urlPrefix)); + + QNetworkReply *reply = m_networkManager->get(networkRequest); + + QGeoRouteReplyOsm *routeReply = new QGeoRouteReplyOsm(reply, request, this); + + connect(routeReply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(routeReply, SIGNAL(error(QGeoRouteReply::Error,QString)), + this, SLOT(replyError(QGeoRouteReply::Error,QString))); + + return routeReply; +} + +const QGeoRouteParser *QGeoRoutingManagerEngineOsm::routeParser() const +{ + return m_routeParser; +} + +void QGeoRoutingManagerEngineOsm::replyFinished() +{ + QGeoRouteReply *reply = qobject_cast(sender()); + if (reply) + emit finished(reply); +} + +void QGeoRoutingManagerEngineOsm::replyError(QGeoRouteReply::Error errorCode, + const QString &errorString) +{ + QGeoRouteReply *reply = qobject_cast(sender()); + if (reply) + emit error(reply, errorCode, errorString); +} diff --git a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h new file mode 100644 index 0000000..8e2d7f5 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTINGMANAGERENGINEOSM_H +#define QGEOROUTINGMANAGERENGINEOSM_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QNetworkAccessManager; + +class QGeoRoutingManagerEngineOsm : public QGeoRoutingManagerEngine +{ + Q_OBJECT + +public: + QGeoRoutingManagerEngineOsm(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString); + ~QGeoRoutingManagerEngineOsm(); + + QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request); + const QGeoRouteParser *routeParser() const; + +private Q_SLOTS: + void replyFinished(); + void replyError(QGeoRouteReply::Error errorCode, const QString &errorString); + +private: + QNetworkAccessManager *m_networkManager; + QGeoRouteParser *m_routeParser; + QByteArray m_userAgent; + QString m_urlPrefix; +}; + +QT_END_NAMESPACE + +#endif // QGEOROUTINGMANAGERENGINEOSM_H + diff --git a/src/plugins/geoservices/osm/qgeoserviceproviderpluginosm.cpp b/src/plugins/geoservices/osm/qgeoserviceproviderpluginosm.cpp new file mode 100644 index 0000000..b028a94 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeoserviceproviderpluginosm.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoserviceproviderpluginosm.h" +#include "qgeotiledmappingmanagerengineosm.h" +#include "qgeocodingmanagerengineosm.h" +#include "qgeoroutingmanagerengineosm.h" +#include "qplacemanagerengineosm.h" + +QT_BEGIN_NAMESPACE + +QGeoCodingManagerEngine *QGeoServiceProviderFactoryOsm::createGeocodingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + return new QGeoCodingManagerEngineOsm(parameters, error, errorString); +} + +QGeoMappingManagerEngine *QGeoServiceProviderFactoryOsm::createMappingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + return new QGeoTiledMappingManagerEngineOsm(parameters, error, errorString); +} + +QGeoRoutingManagerEngine *QGeoServiceProviderFactoryOsm::createRoutingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + return new QGeoRoutingManagerEngineOsm(parameters, error, errorString); +} + +QPlaceManagerEngine *QGeoServiceProviderFactoryOsm::createPlaceManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + return new QPlaceManagerEngineOsm(parameters, error, errorString); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeoserviceproviderpluginosm.h b/src/plugins/geoservices/osm/qgeoserviceproviderpluginosm.h new file mode 100644 index 0000000..5e4ab3e --- /dev/null +++ b/src/plugins/geoservices/osm/qgeoserviceproviderpluginosm.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDER_OSM_H +#define QGEOSERVICEPROVIDER_OSM_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoServiceProviderFactoryOsm: public QObject, public QGeoServiceProviderFactory +{ + Q_OBJECT + Q_INTERFACES(QGeoServiceProviderFactory) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0" + FILE "osm_plugin.json") + +public: + QGeoCodingManagerEngine *createGeocodingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + QGeoMappingManagerEngine *createMappingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + QGeoRoutingManagerEngine *createRoutingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; + QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/osm/qgeotiledmaposm.cpp b/src/plugins/geoservices/osm/qgeotiledmaposm.cpp new file mode 100644 index 0000000..f16e602 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeotiledmaposm.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotiledmaposm.h" +#include "qgeotiledmappingmanagerengineosm.h" +#include "qgeotilefetcherosm.h" + +#include + +QT_BEGIN_NAMESPACE + +QGeoTiledMapOsm::QGeoTiledMapOsm(QGeoTiledMappingManagerEngineOsm *engine, QObject *parent) +: QGeoTiledMap(engine, parent), m_mapId(-1), m_engine(engine) +{ + // Needed because evaluateCopyrights() is only triggered if visible tiles change in the map. + // It fails the first time it gets called if providers aren't resolved, and subsequent calls + // to it will be skipped until visible tiles change. + // This connection makes sure the copyrights are evaluated when copyright data are ready regardless + // of what tiles are visible. + connect(qobject_cast(engine->tileFetcher()), &QGeoTileFetcherOsm::providerDataUpdated, + this, &QGeoTiledMapOsm::onProviderDataUpdated); +} + +QGeoTiledMapOsm::~QGeoTiledMapOsm() +{ +} + +void QGeoTiledMapOsm::evaluateCopyrights(const QSet &visibleTiles) +{ + if (visibleTiles.isEmpty()) + return; + + QGeoTileSpec tile = *visibleTiles.constBegin(); + if (tile.mapId() == m_mapId) + return; + + int providerId = tile.mapId() - 1; + if (providerId < 0 || providerId >= m_engine->providers().size() || !m_engine->providers().at(providerId)->isValid()) + return; + + m_mapId = tile.mapId(); + onProviderDataUpdated(m_engine->providers().at(providerId)); +} + +void QGeoTiledMapOsm::onProviderDataUpdated(const QGeoTileProviderOsm *provider) +{ + if (!provider->isResolved() || provider->mapType().mapId() != m_mapId) + return; + QString copyRights; + const QString mapCopy = provider->mapCopyRight(); + const QString dataCopy = provider->dataCopyRight(); + const QString styleCopy = provider->styleCopyRight(); + if (!mapCopy.isEmpty()) { + copyRights += QStringLiteral("Map © "); + copyRights += mapCopy; + } + if (!dataCopy.isEmpty()) { + if (!copyRights.isEmpty()) + copyRights += QStringLiteral("
"); + copyRights += QStringLiteral("Data © "); + copyRights += dataCopy; + } + if (!styleCopy.isEmpty()) { + if (!copyRights.isEmpty()) + copyRights += QStringLiteral("
"); + copyRights += QStringLiteral("Style © "); + copyRights += styleCopy; + } + + if (copyRights.isEmpty() && provider->mapType().style() == QGeoMapType::CustomMap) + copyRights = m_engine->customCopyright(); + + emit copyrightsChanged(copyRights); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeotiledmaposm.h b/src/plugins/geoservices/osm/qgeotiledmaposm.h new file mode 100644 index 0000000..cfc7294 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeotiledmaposm.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEDMAPOSM_H +#define QGEOTILEDMAPOSM_H + +#include "qgeotileproviderosm.h" + +#include + +QT_BEGIN_NAMESPACE + +class QGeoTiledMappingManagerEngineOsm; +class QGeoTiledMapOsm: public QGeoTiledMap +{ + Q_OBJECT + +public: + QGeoTiledMapOsm(QGeoTiledMappingManagerEngineOsm *engine, QObject *parent = 0); + ~QGeoTiledMapOsm(); + +protected: + void evaluateCopyrights(const QSet &visibleTiles) Q_DECL_OVERRIDE; + +protected Q_SLOTS: + void onProviderDataUpdated(const QGeoTileProviderOsm *provider); + +private: + int m_mapId; + QGeoTiledMappingManagerEngineOsm *m_engine; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp new file mode 100644 index 0000000..fba177f --- /dev/null +++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp @@ -0,0 +1,251 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotiledmappingmanagerengineosm.h" +#include "qgeotilefetcherosm.h" +#include "qgeotiledmaposm.h" +#include "qgeotileproviderosm.h" + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) +: QGeoTiledMappingManagerEngine() +{ + QGeoCameraCapabilities cameraCaps; + cameraCaps.setMinimumZoomLevel(0.0); + cameraCaps.setMaximumZoomLevel(19.0); + setCameraCapabilities(cameraCaps); + + setTileSize(QSize(256, 256)); + + QNetworkAccessManager *nm = new QNetworkAccessManager(); + QString domain = QStringLiteral("http://maps-redirect.qt.io/osm/5.6/"); + if (parameters.contains(QStringLiteral("osm.mapping.providersrepository.address"))) { + QString customAddress = parameters.value(QStringLiteral("osm.mapping.providersrepository.address")).toString(); + // Allowing some malformed addresses ( containing the suffix "/osm/5.6/" + if (customAddress.indexOf(QStringLiteral(":")) < 0) // defaulting to http:// if no prefix is found + customAddress = QStringLiteral("http://") + customAddress; + if (customAddress[customAddress.length()-1] != QLatin1Char('/')) + customAddress += QLatin1Char('/'); + domain = customAddress; + } + + m_providers.push_back( + new QGeoTileProviderOsm(domain + "street", + nm, + QGeoMapType(QGeoMapType::StreetMap, tr("Street Map"), tr("Street map view in daylight mode"), false, false, 1), + QGeoTileProviderOsm::TileProvider(QStringLiteral("http://c.tile.openstreetmap.org/%z/%x/%y.png"), + QStringLiteral("png"), + QStringLiteral("OpenStreetMap.org"), + QStringLiteral("OpenStreetMap contributors") + ))); + m_providers.push_back( + new QGeoTileProviderOsm(domain + "satellite", + nm, + QGeoMapType(QGeoMapType::SatelliteMapDay, tr("Satellite Map"), tr("Satellite map view in daylight mode"), false, false, 2), + QGeoTileProviderOsm::TileProvider() + )); + m_providers.push_back( + new QGeoTileProviderOsm(domain + "cycle", + nm, + QGeoMapType(QGeoMapType::CycleMap, tr("Cycle Map"), tr("Cycle map view in daylight mode"), false, false, 3), + QGeoTileProviderOsm::TileProvider(QStringLiteral("http://c.tile.opencyclemap.org/cycle/%z/%x/%y.png"), + QStringLiteral("png"), + QStringLiteral("Thunderforest"), + QStringLiteral("OpenStreetMap contributors") + ))); + m_providers.push_back( + new QGeoTileProviderOsm(domain + "transit", + nm, + QGeoMapType(QGeoMapType::TransitMap, tr("Transit Map"), tr("Public transit map view in daylight mode"), false, false, 4), + QGeoTileProviderOsm::TileProvider(QStringLiteral("http://c.tile2.opencyclemap.org/transport/%z/%x/%y.png"), + QStringLiteral("png"), + QStringLiteral("Thunderforest"), + QStringLiteral("OpenStreetMap contributors") + ))); + m_providers.push_back( + new QGeoTileProviderOsm(domain + "night-transit", + nm, + QGeoMapType(QGeoMapType::TransitMap, tr("Night Transit Map"), tr("Public transit map view in night mode"), false, true, 5), + QGeoTileProviderOsm::TileProvider(QStringLiteral("http://a.tile.thunderforest.com/transport-dark/%z/%x/%y.png"), + QStringLiteral("png"), + QStringLiteral("Thunderforest"), + QStringLiteral("OpenStreetMap contributors") + ))); + m_providers.push_back( + new QGeoTileProviderOsm(domain + "terrain", + nm, + QGeoMapType(QGeoMapType::TerrainMap, tr("Terrain Map"), tr("Terrain map view"), false, false, 6), + QGeoTileProviderOsm::TileProvider(QStringLiteral("http://a.tile.thunderforest.com/landscape/%z/%x/%y.png"), + QStringLiteral("png"), + QStringLiteral("Thunderforest"), + QStringLiteral("OpenStreetMap contributors") + ))); + m_providers.push_back( + new QGeoTileProviderOsm(domain + "hiking", + nm, + QGeoMapType(QGeoMapType::PedestrianMap, tr("Hiking Map"), tr("Hiking map view"), false, false, 7), + QGeoTileProviderOsm::TileProvider(QStringLiteral("http://a.tile.thunderforest.com/outdoors/%z/%x/%y.png"), + QStringLiteral("png"), + QStringLiteral("Thunderforest"), + QStringLiteral("OpenStreetMap contributors") + ))); + + if (parameters.contains(QStringLiteral("osm.mapping.custom.host")) + || parameters.contains(QStringLiteral("osm.mapping.host"))) { + // Adding a custom provider + QString tmsServer; + if (parameters.contains(QStringLiteral("osm.mapping.host"))) + tmsServer = parameters.value(QStringLiteral("osm.mapping.host")).toString(); + if (parameters.contains(QStringLiteral("osm.mapping.custom.host"))) // priority to the new one + tmsServer = parameters.value(QStringLiteral("osm.mapping.custom.host")).toString(); + + QString mapCopyright; + QString dataCopyright; + if (parameters.contains(QStringLiteral("osm.mapping.custom.mapcopyright"))) + mapCopyright = parameters.value(QStringLiteral("osm.mapping.custom.mapcopyright")).toString(); + if (parameters.contains(QStringLiteral("osm.mapping.custom.datacopyright"))) + dataCopyright = parameters.value(QStringLiteral("osm.mapping.custom.datacopyright")).toString(); + + if (parameters.contains(QStringLiteral("osm.mapping.copyright"))) + m_customCopyright = parameters.value(QStringLiteral("osm.mapping.copyright")).toString(); + + m_providers.push_back( + new QGeoTileProviderOsm("", + nm, + QGeoMapType(QGeoMapType::CustomMap, tr("Custom URL Map"), tr("Custom url map view set via urlprefix parameter"), false, false, 8), + QGeoTileProviderOsm::TileProvider(tmsServer + QStringLiteral("%z/%x/%y.png"), + QStringLiteral("png"), + mapCopyright, + dataCopyright + ))); + + m_providers.last()->disableRedirection(); + } + + bool disableRedirection = false; + if (parameters.contains(QStringLiteral("osm.mapping.providersrepository.disabled"))) + disableRedirection = parameters.value(QStringLiteral("osm.mapping.providersrepository.disabled")).toBool(); + + foreach (QGeoTileProviderOsm * provider, m_providers) { + provider->setParent(this); + if (disableRedirection) + provider->disableRedirection(); + + connect(provider, &QGeoTileProviderOsm::resolutionFinished, + this, &QGeoTiledMappingManagerEngineOsm::onProviderResolutionFinished); + connect(provider, &QGeoTileProviderOsm::resolutionError, + this, &QGeoTiledMappingManagerEngineOsm::onProviderResolutionError); + } + updateMapTypes(); + + QGeoTileFetcherOsm *tileFetcher = new QGeoTileFetcherOsm(m_providers, nm, this); + if (parameters.contains(QStringLiteral("osm.useragent"))) { + const QByteArray ua = parameters.value(QStringLiteral("osm.useragent")).toString().toLatin1(); + tileFetcher->setUserAgent(ua); + } + + + setTileFetcher(tileFetcher); + + QAbstractGeoTileCache *tileCache = new QGeoFileTileCache(QAbstractGeoTileCache::baseCacheDirectory() + QStringLiteral("osm")); + // 50mb of disk cache by default to minimize n. of accesses to public OSM servers + tileCache->setMaxDiskUsage(50 * 1024 * 1024); + setTileCache(tileCache); + + *error = QGeoServiceProvider::NoError; + errorString->clear(); +} + +QGeoTiledMappingManagerEngineOsm::~QGeoTiledMappingManagerEngineOsm() +{ +} + +QGeoMap *QGeoTiledMappingManagerEngineOsm::createMap() +{ + return new QGeoTiledMapOsm(this); +} + +const QVector &QGeoTiledMappingManagerEngineOsm::providers() +{ + return m_providers; +} + +QString QGeoTiledMappingManagerEngineOsm::customCopyright() const +{ + return m_customCopyright; +} + +void QGeoTiledMappingManagerEngineOsm::onProviderResolutionFinished(const QGeoTileProviderOsm *provider) +{ + if (!provider->isResolved()) + return; + updateMapTypes(); +} + +void QGeoTiledMappingManagerEngineOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error) +{ + Q_UNUSED(error) + if (!provider->isResolved()) + return; + updateMapTypes(); +} + +void QGeoTiledMappingManagerEngineOsm::updateMapTypes() +{ + QList mapTypes; + foreach (QGeoTileProviderOsm * provider, m_providers) { + // assume provider are ok until they have been resolved invalid + if (!provider->isResolved() || provider->isValid()) + mapTypes << provider->mapType(); + } + const QList currentlySupportedMapTypes = supportedMapTypes(); + if (currentlySupportedMapTypes != mapTypes) + // See map type implementations in QGeoTiledMapOsm and QGeoTileFetcherOsm. + setSupportedMapTypes(mapTypes); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h new file mode 100644 index 0000000..247e437 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEDMAPPINGMANAGERENGINEOSM_H +#define QGEOTILEDMAPPINGMANAGERENGINEOSM_H + +#include "qgeotileproviderosm.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoTiledMappingManagerEngineOsm : public QGeoTiledMappingManagerEngine +{ + Q_OBJECT + + friend class QGeoTiledMapOsm; +public: + QGeoTiledMappingManagerEngineOsm(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString); + ~QGeoTiledMappingManagerEngineOsm(); + + QGeoMap *createMap(); + const QVector &providers(); + QString customCopyright() const; + +protected Q_SLOTS: + void onProviderResolutionFinished(const QGeoTileProviderOsm *provider); + void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error); + +protected: + void updateMapTypes(); + +private: + QVector m_providers; + QString m_customCopyright; +}; + +QT_END_NAMESPACE + +#endif // QGEOTILEDMAPPINGMANAGERENGINEOSM_H diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp new file mode 100644 index 0000000..9862141 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotilefetcherosm.h" +#include "qgeomapreplyosm.h" + +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +static bool providersResolved(const QVector &providers) +{ + foreach (const QGeoTileProviderOsm *provider, providers) + if (!provider->isResolved()) + return false; + return true; +} + +QGeoTileFetcherOsm::QGeoTileFetcherOsm(const QVector &providers, + QNetworkAccessManager *nm, + QObject *parent) +: QGeoTileFetcher(parent), m_userAgent("Qt Location based application"), + m_providers(providers), m_nm(nm), m_ready(true) +{ + m_nm->setParent(this); + foreach (QGeoTileProviderOsm *provider, m_providers) { + if (!provider->isResolved()) { + m_ready = false; + connect(provider, &QGeoTileProviderOsm::resolutionFinished, + this, &QGeoTileFetcherOsm::onProviderResolutionFinished); + connect(provider, &QGeoTileProviderOsm::resolutionError, + this, &QGeoTileFetcherOsm::onProviderResolutionError); + provider->resolveProvider(); + } + } + if (m_ready) + readyUpdated(); +} + +void QGeoTileFetcherOsm::setUserAgent(const QByteArray &userAgent) +{ + m_userAgent = userAgent; +} + +bool QGeoTileFetcherOsm::initialized() const +{ + if (!m_ready) { + foreach (QGeoTileProviderOsm *provider, m_providers) + if (!provider->isResolved()) + provider->resolveProvider(); + } + return m_ready; +} + +void QGeoTileFetcherOsm::onProviderResolutionFinished(const QGeoTileProviderOsm *provider) +{ + if ((m_ready = providersResolved(m_providers))) { + qWarning("QGeoTileFetcherOsm: all providers resolved"); + readyUpdated(); + } + emit providerDataUpdated(provider); +} + +void QGeoTileFetcherOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error) +{ + Q_UNUSED(error) + if ((m_ready = providersResolved(m_providers))) { + qWarning("QGeoTileFetcherOsm: all providers resolved"); + readyUpdated(); + } + emit providerDataUpdated(provider); +} + +QGeoTiledMapReply *QGeoTileFetcherOsm::getTileImage(const QGeoTileSpec &spec) +{ + int id = spec.mapId(); + if (id < 1 || id > m_providers.size()) { + qWarning("Unknown map id %d\n", spec.mapId()); + if (m_providers.isEmpty()) + return Q_NULLPTR; + else + id = 1; + } + id -= 1; // TODO: make OSM map ids start from 0. + + const QUrl url = m_providers[id]->tileAddress(spec.x(), spec.y(), spec.zoom()); + QNetworkRequest request; + request.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent); + request.setUrl(url); + QNetworkReply *reply = m_nm->get(request); + return new QGeoMapReplyOsm(reply, spec, m_providers[id]->format()); +} + +void QGeoTileFetcherOsm::readyUpdated() +{ + updateTileRequests(QSet(), QSet()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.h b/src/plugins/geoservices/osm/qgeotilefetcherosm.h new file mode 100644 index 0000000..8d69cc5 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEFETCHEROSM_H +#define QGEOTILEFETCHEROSM_H + +#include "qgeotileproviderosm.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QNetworkAccessManager; + +class QGeoTileFetcherOsm : public QGeoTileFetcher +{ + Q_OBJECT + + friend class QGeoMapReplyOsm; + friend class QGeoTiledMappingManagerEngineOsm; +public: + QGeoTileFetcherOsm(const QVector &providers, + QNetworkAccessManager *nm, + QObject *parent = 0); + + void setUserAgent(const QByteArray &userAgent); + +Q_SIGNALS: + void providerDataUpdated(const QGeoTileProviderOsm *provider); + +protected: + bool initialized() const Q_DECL_OVERRIDE; + +protected Q_SLOTS: + void onProviderResolutionFinished(const QGeoTileProviderOsm *provider); + void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error); + +private: + QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec); + void readyUpdated(); + + QByteArray m_userAgent; + QVector m_providers; + QNetworkAccessManager *m_nm; + bool m_ready; +}; + +QT_END_NAMESPACE + +#endif // QGEOTILEFETCHEROSM_H + diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp new file mode 100644 index 0000000..3d46a42 --- /dev/null +++ b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotileproviderosm.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static const int maxValidZoom = 30; + +QGeoTileProviderOsm::QGeoTileProviderOsm(const QString &urlRedir, + QNetworkAccessManager *nm, + const QGeoMapType &mapType, + const QGeoTileProviderOsm::TileProvider &providerFallback) + : m_nm(nm), m_urlRedirector(urlRedir), + m_providerFallback(providerFallback), + m_mapType(mapType), m_status(Idle) +{ + if (!m_urlRedirector.isValid()) + disableRedirection(); +} + +QGeoTileProviderOsm::~QGeoTileProviderOsm() +{ + +} + +void QGeoTileProviderOsm::resolveProvider() +{ + switch (m_status) { + case Resolving: + case Invalid: + case Valid: + return; + case Idle: + m_status = Resolving; + break; + } + + QNetworkRequest request; + request.setHeader(QNetworkRequest::UserAgentHeader, QByteArrayLiteral("QGeoTileFetcherOsm")); + request.setUrl(m_urlRedirector); + QNetworkReply *reply = m_nm->get(request); + connect(reply, SIGNAL(finished()), this, SLOT(onNetworkReplyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(onNetworkReplyError(QNetworkReply::NetworkError))); +} + +void QGeoTileProviderOsm::disableRedirection() +{ + m_status = Invalid; + m_provider.m_valid = false; +} + +void QGeoTileProviderOsm::handleError(QNetworkReply::NetworkError error) +{ + switch (error) { + case QNetworkReply::ConnectionRefusedError: + case QNetworkReply::TooManyRedirectsError: + case QNetworkReply::InsecureRedirectError: + case QNetworkReply::ContentAccessDenied: + case QNetworkReply::ContentOperationNotPermittedError: + case QNetworkReply::ContentNotFoundError: + case QNetworkReply::AuthenticationRequiredError: + case QNetworkReply::ContentGoneError: + case QNetworkReply::OperationNotImplementedError: + case QNetworkReply::ServiceUnavailableError: + // Errors we don't expect to recover from in the near future, which + // prevent accessing the redirection info but not the actual providers. + m_status = Invalid; + default: + break; + } +} + +QUrl QGeoTileProviderOsm::tileAddress(int x, int y, int z) const +{ + if (m_provider.isValid()) + return m_provider.tileAddress(x,y,z); + if (m_providerFallback.isValid()) + return m_providerFallback.tileAddress(x,y,z); + return QUrl(); +} + +QString QGeoTileProviderOsm::mapCopyRight() const +{ + if (m_provider.isValid()) + return m_provider.mapCopyRight(); + if (m_providerFallback.isValid()) + return m_providerFallback.mapCopyRight(); + return QString(); +} + +QString QGeoTileProviderOsm::dataCopyRight() const +{ + if (m_provider.isValid()) + return m_provider.dataCopyRight(); + if (m_providerFallback.isValid()) + return m_providerFallback.dataCopyRight(); + return QString(); +} + +QString QGeoTileProviderOsm::styleCopyRight() const +{ + if (m_provider.isValid()) + return m_provider.styleCopyRight(); + if (m_providerFallback.isValid()) + return m_providerFallback.styleCopyRight(); + return QString(); +} + +QString QGeoTileProviderOsm::format() const +{ + if (m_provider.isValid()) + return m_provider.format(); + if (m_providerFallback.isValid()) + return m_providerFallback.format(); + return QString(); +} + +const QGeoMapType &QGeoTileProviderOsm::mapType() const +{ + return m_mapType; +} + +bool QGeoTileProviderOsm::isValid() const +{ + return (m_provider.isValid() || m_providerFallback.isValid()); +} + +bool QGeoTileProviderOsm::isResolved() const +{ + return (m_status == Valid || m_status == Invalid); +} + +void QGeoTileProviderOsm::onNetworkReplyFinished() +{ + QNetworkReply *reply = static_cast(sender()); + reply->deleteLater(); + + switch (m_status) { + case Resolving: + m_status = Idle; + case Idle: // should not happen + case Invalid: // should not happen + break; + case Valid: // should not happen + return; + } + + if (reply->error() != QNetworkReply::NoError) { + handleError(reply->error()); + if (m_status == Invalid) + emit resolutionError(this, reply->error()); + return; + } + m_status = Invalid; + + /* + * The content of a provider information file must be in JSON format, containing + * (as of Qt 5.6.2) the following fields: + * + * { + * "Enabled" : bool, (optional) + * "UrlTemplate" : "", (mandatory) + * "ImageFormat" : "", (mandatory) + * "MapCopyRight" : "", (mandatory) + * "DataCopyRight" : "", (mandatory) + * "StyleCopyRight" : "", (optional) + * "MinimumZoomLevel" : , (optional) + * "MaximumZoomLevel" : , (optional) + * } + * + * Enabled is optional, and allows to temporarily disable a tile provider if it becomes + * unavailable, without making the osm plugin fire requests to it. Default is true. + * + * MinimumZoomLevel and MaximumZoomLevel are also optional, and allow to prevent invalid tile + * requests to the providers, if they do not support the specific ZL. Default is 0 and 19, + * respectively. + * + * is required, and is the tile url template, with %x, %y and %z as + * placeholders for the actual parameters. + * Example: + * http://localhost:8080/maps/%z/%x/%y.png + * + * is required, and is the format of the tile. + * Examples: + * "png", "jpg" + * + * is required and is the string that will be displayed in the "Map (c)" part + * of the on-screen copyright notice. Can be an empty string. + * Example: + * "MapQuest" + * + * is required and is the string that will be displayed in the "Data (c)" part + * of the on-screen copyright notice. Can be an empty string. + * Example: + * "OpenStreetMap contributors" + * + * is optional and is the string that will be displayed in the optional "Style (c)" part + * of the on-screen copyright notice. + */ + + QJsonParseError error; + QJsonDocument d = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) { + qWarning() << "QGeoTileProviderOsm: Error parsing redirection data: "<(sender())->deleteLater(); + if (m_status == Invalid) + emit resolutionError(this, error); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.h b/src/plugins/geoservices/osm/qgeotileproviderosm.h new file mode 100644 index 0000000..f396b3b --- /dev/null +++ b/src/plugins/geoservices/osm/qgeotileproviderosm.h @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTILEPROVIDEROSM_H +#define QTILEPROVIDEROSM_H + +#include + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoTileProviderOsm: public QObject +{ + Q_OBJECT + + friend class QGeoTileFetcherOsm; + friend class QGeoMapReplyOsm; + friend class QGeoTiledMappingManagerEngineOsm; +public: + struct TileProvider { + + static inline void sort2(int &a, int &b) + { + if (a > b) { + int temp=a; + a=b; + b=temp; + } + } + + TileProvider() : m_valid(false) + { + + } + + TileProvider(const QString &urlTemplate, + const QString &format, + const QString ©RightMap, + const QString ©RightData, + int minimumZoomLevel = 0, + int maximumZoomLevel = 19) : m_valid(false) + { + if (urlTemplate.isEmpty()) + return; + m_urlTemplate = urlTemplate; + + if (format.isEmpty()) + return; + m_format = format; + + m_copyRightMap = copyRightMap; + m_copyRightData = copyRightData; + + if (minimumZoomLevel < 0 || minimumZoomLevel > 30) + return; + m_minimumZoomLevel = minimumZoomLevel; + + if (maximumZoomLevel < 0 || maximumZoomLevel > 30 || maximumZoomLevel < minimumZoomLevel) + return; + m_maximumZoomLevel = maximumZoomLevel; + + // Currently supporting only %x, %y and &z + int offset[3]; + offset[0] = m_urlTemplate.indexOf(QLatin1String("%x")); + if (offset[0] < 0) + return; + + offset[1] = m_urlTemplate.indexOf(QLatin1String("%y")); + if (offset[1] < 0) + return; + + offset[2] = m_urlTemplate.indexOf(QLatin1String("%z")); + if (offset[2] < 0) + return; + + int sortedOffsets[3]; + std::copy(offset, offset + 3, sortedOffsets); + sort2(sortedOffsets[0] ,sortedOffsets[1]); + sort2(sortedOffsets[1] ,sortedOffsets[2]); + sort2(sortedOffsets[0] ,sortedOffsets[1]); + + int min = sortedOffsets[0]; + int max = sortedOffsets[2]; + int mid = sortedOffsets[1]; + + // Initing LUT + for (int i=0; i<3; i++) { + if (offset[0] == sortedOffsets[i]) + paramsLUT[i] = 0; + else if (offset[1] == sortedOffsets[i]) + paramsLUT[i] = 1; + else + paramsLUT[i] = 2; + } + + m_urlPrefix = m_urlTemplate.mid(0 , min); + m_urlSuffix = m_urlTemplate.mid(max + 2, m_urlTemplate.size() - max - 2); + + paramsSep[0] = m_urlTemplate.mid(min + 2, mid - min - 2); + paramsSep[1] = m_urlTemplate.mid(mid + 2, max - mid - 2); + m_valid = true; + } + + ~TileProvider() + { + } + + inline bool isValid() const + { + return m_valid; + } + + inline QString mapCopyRight() const + { + return m_copyRightMap; + } + + inline QString dataCopyRight() const + { + return m_copyRightData; + } + + inline QString styleCopyRight() const + { + return m_copyRightStyle; + } + + inline QString format() const + { + return m_format; + } + + // Optional properties, not needed to construct a provider + void setStyleCopyRight(const QString ©right) + { + m_copyRightStyle = copyright; + } + + QUrl tileAddress(int x, int y, int z) const + { + if (z < m_minimumZoomLevel || z > m_maximumZoomLevel) + return QUrl(); + int params[3] = { x, y, z}; + QString url; + url += m_urlPrefix; + url += QString::number(params[paramsLUT[0]]); + url += paramsSep[0]; + url += QString::number(params[paramsLUT[1]]); + url += paramsSep[1]; + url += QString::number(params[paramsLUT[2]]); + url += m_urlSuffix; + return QUrl(url); + } + + bool m_valid; + QString m_urlTemplate; + QString m_format; + QString m_copyRightMap; + QString m_copyRightData; + QString m_copyRightStyle; + QString m_urlPrefix; + QString m_urlSuffix; + int m_minimumZoomLevel; + int m_maximumZoomLevel; + + int paramsLUT[3]; //Lookup table to handle possibly shuffled x,y,z + QString paramsSep[2]; // what goes in between %x, %y and %z + }; + + enum Status {Idle, + Resolving, + Valid, + Invalid }; + + QGeoTileProviderOsm(const QString &urlRedir, + QNetworkAccessManager *nm, + const QGeoMapType &mapType, + const TileProvider &providerFallback); + + ~QGeoTileProviderOsm(); + + + + QUrl tileAddress(int x, int y, int z) const; + QString mapCopyRight() const; + QString dataCopyRight() const; + QString styleCopyRight() const; + QString format() const; + const QGeoMapType &mapType() const; + bool isValid() const; + bool isResolved() const; + +Q_SIGNALS: + void resolutionFinished(const QGeoTileProviderOsm *provider); + void resolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error); + +public Q_SLOTS: + void onNetworkReplyFinished(); + void onNetworkReplyError(QNetworkReply::NetworkError error); + void resolveProvider(); + +protected: + void disableRedirection(); + void handleError(QNetworkReply::NetworkError error); + + QNetworkAccessManager *m_nm; + QUrl m_urlRedirector; // The URL from where to fetch the URL template + TileProvider m_provider; + TileProvider m_providerFallback; + QGeoMapType m_mapType; + Status m_status; + QTimer m_retryTimer; +}; + +QT_END_NAMESPACE + +#endif // QTILEPROVIDEROSM_H diff --git a/src/plugins/geoservices/osm/qplacecategoriesreplyosm.cpp b/src/plugins/geoservices/osm/qplacecategoriesreplyosm.cpp new file mode 100644 index 0000000..fe506bb --- /dev/null +++ b/src/plugins/geoservices/osm/qplacecategoriesreplyosm.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacecategoriesreplyosm.h" + +QT_BEGIN_NAMESPACE + +QPlaceCategoriesReplyOsm::QPlaceCategoriesReplyOsm(QObject *parent) +: QPlaceReply(parent) +{ +} + +QPlaceCategoriesReplyOsm::~QPlaceCategoriesReplyOsm() +{ +} + +void QPlaceCategoriesReplyOsm::emitFinished() +{ + setFinished(true); + emit finished(); +} + +void QPlaceCategoriesReplyOsm::setError(QPlaceReply::Error errorCode, const QString &errorString) +{ + QPlaceReply::setError(errorCode, errorString); + emit error(errorCode, errorString); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qplacecategoriesreplyosm.h b/src/plugins/geoservices/osm/qplacecategoriesreplyosm.h new file mode 100644 index 0000000..af2919d --- /dev/null +++ b/src/plugins/geoservices/osm/qplacecategoriesreplyosm.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACECATEGORIESREPLYOSM_H +#define QPLACECATEGORIESREPLYOSM_H + +#include + +QT_BEGIN_NAMESPACE + +class QPlaceCategoriesReplyOsm : public QPlaceReply +{ + Q_OBJECT + +public: + explicit QPlaceCategoriesReplyOsm(QObject *parent = 0); + ~QPlaceCategoriesReplyOsm(); + + void emitFinished(); + void setError(QPlaceReply::Error errorCode, const QString &errorString); +}; + +QT_END_NAMESPACE + +#endif // QPLACECATEGORIESREPLYOSM_H diff --git a/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp b/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp new file mode 100644 index 0000000..719769f --- /dev/null +++ b/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp @@ -0,0 +1,365 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtFoo module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacemanagerengineosm.h" +#include "qplacesearchreplyosm.h" +#include "qplacecategoriesreplyosm.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace +{ +QString SpecialPhrasesBaseUrl = QStringLiteral("http://wiki.openstreetmap.org/wiki/Special:Export/Nominatim/Special_Phrases/"); + +QString nameForTagKey(const QString &tagKey) +{ + if (tagKey == QLatin1String("aeroway")) + return QPlaceManagerEngineOsm::tr("Aeroway"); + else if (tagKey == QLatin1String("amenity")) + return QPlaceManagerEngineOsm::tr("Amenity"); + else if (tagKey == QLatin1String("building")) + return QPlaceManagerEngineOsm::tr("Building"); + else if (tagKey == QLatin1String("highway")) + return QPlaceManagerEngineOsm::tr("Highway"); + else if (tagKey == QLatin1String("historic")) + return QPlaceManagerEngineOsm::tr("Historic"); + else if (tagKey == QLatin1String("landuse")) + return QPlaceManagerEngineOsm::tr("Land use"); + else if (tagKey == QLatin1String("leisure")) + return QPlaceManagerEngineOsm::tr("Leisure"); + else if (tagKey == QLatin1String("man_made")) + return QPlaceManagerEngineOsm::tr("Man made"); + else if (tagKey == QLatin1String("natural")) + return QPlaceManagerEngineOsm::tr("Natural"); + else if (tagKey == QLatin1String("place")) + return QPlaceManagerEngineOsm::tr("Place"); + else if (tagKey == QLatin1String("railway")) + return QPlaceManagerEngineOsm::tr("Railway"); + else if (tagKey == QLatin1String("shop")) + return QPlaceManagerEngineOsm::tr("Shop"); + else if (tagKey == QLatin1String("tourism")) + return QPlaceManagerEngineOsm::tr("Tourism"); + else if (tagKey == QLatin1String("waterway")) + return QPlaceManagerEngineOsm::tr("Waterway"); + else + return tagKey; +} + +} + +QPlaceManagerEngineOsm::QPlaceManagerEngineOsm(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) +: QPlaceManagerEngine(parameters), m_networkManager(new QNetworkAccessManager(this)), + m_categoriesReply(0) +{ + if (parameters.contains(QStringLiteral("osm.useragent"))) + m_userAgent = parameters.value(QStringLiteral("osm.useragent")).toString().toLatin1(); + else + m_userAgent = "Qt Location based application"; + + if (parameters.contains(QStringLiteral("osm.places.host"))) + m_urlPrefix = parameters.value(QStringLiteral("osm.places.host")).toString(); + else + m_urlPrefix = QStringLiteral("http://nominatim.openstreetmap.org/search"); + + *error = QGeoServiceProvider::NoError; + errorString->clear(); +} + +QPlaceManagerEngineOsm::~QPlaceManagerEngineOsm() +{ +} + +QPlaceSearchReply *QPlaceManagerEngineOsm::search(const QPlaceSearchRequest &request) +{ + bool unsupported = false; + + // Only public visibility supported + unsupported |= request.visibilityScope() != QLocation::UnspecifiedVisibility && + request.visibilityScope() != QLocation::PublicVisibility; + unsupported |= request.searchTerm().isEmpty() && request.categories().isEmpty(); + + if (unsupported) + return QPlaceManagerEngine::search(request); + + QUrlQuery queryItems; + + queryItems.addQueryItem(QStringLiteral("format"), QStringLiteral("jsonv2")); + + //queryItems.addQueryItem(QStringLiteral("accept-language"), QStringLiteral("en")); + + QGeoRectangle boundingBox; + QGeoShape searchArea = request.searchArea(); + switch (searchArea.type()) { + case QGeoShape::CircleType: { + QGeoCircle c(searchArea); + qreal radius = c.radius(); + if (radius < 0) + radius = 50000; + + boundingBox = QGeoRectangle(c.center().atDistanceAndAzimuth(radius, -45), + c.center().atDistanceAndAzimuth(radius, 135)); + break; + } + case QGeoShape::RectangleType: + boundingBox = searchArea; + break; + default: + ; + } + + if (!boundingBox.isEmpty()) { + queryItems.addQueryItem(QStringLiteral("bounded"), QStringLiteral("1")); + QString coordinates; + coordinates = QString::number(boundingBox.topLeft().longitude()) + QLatin1Char(',') + + QString::number(boundingBox.topLeft().latitude()) + QLatin1Char(',') + + QString::number(boundingBox.bottomRight().longitude()) + QLatin1Char(',') + + QString::number(boundingBox.bottomRight().latitude()); + queryItems.addQueryItem(QStringLiteral("viewbox"), coordinates); + } + + QStringList queryParts; + if (!request.searchTerm().isEmpty()) + queryParts.append(request.searchTerm()); + + foreach (const QPlaceCategory &category, request.categories()) { + QString id = category.categoryId(); + int index = id.indexOf(QLatin1Char('=')); + if (index != -1) + id = id.mid(index+1); + queryParts.append(QLatin1Char('[') + id + QLatin1Char(']')); + } + + queryItems.addQueryItem(QStringLiteral("q"), queryParts.join(QLatin1Char('+'))); + + QVariantMap parameters = request.searchContext().toMap(); + + QStringList placeIds = parameters.value(QStringLiteral("ExcludePlaceIds")).toStringList(); + if (!placeIds.isEmpty()) + queryItems.addQueryItem(QStringLiteral("exclude_place_ids"), placeIds.join(QLatin1Char(','))); + + queryItems.addQueryItem(QStringLiteral("addressdetails"), QStringLiteral("1")); + + QUrl requestUrl(m_urlPrefix); + requestUrl.setQuery(queryItems); + + QNetworkReply *networkReply = m_networkManager->get(QNetworkRequest(requestUrl)); + + QPlaceSearchReplyOsm *reply = new QPlaceSearchReplyOsm(request, networkReply, this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + + return reply; +} + +QPlaceReply *QPlaceManagerEngineOsm::initializeCategories() +{ + // Only fetch categories once + if (m_categories.isEmpty() && !m_categoriesReply) { + m_categoryLocales = m_locales; + m_categoryLocales.append(QLocale(QLocale::English)); + fetchNextCategoryLocale(); + } + + QPlaceCategoriesReplyOsm *reply = new QPlaceCategoriesReplyOsm(this); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), + this, SLOT(replyError(QPlaceReply::Error,QString))); + + // TODO delayed finished() emission + if (!m_categories.isEmpty()) + reply->emitFinished(); + + m_pendingCategoriesReply.append(reply); + return reply; +} + +QString QPlaceManagerEngineOsm::parentCategoryId(const QString &categoryId) const +{ + Q_UNUSED(categoryId) + + // Only a two category levels + return QString(); +} + +QStringList QPlaceManagerEngineOsm::childCategoryIds(const QString &categoryId) const +{ + return m_subcategories.value(categoryId); +} + +QPlaceCategory QPlaceManagerEngineOsm::category(const QString &categoryId) const +{ + return m_categories.value(categoryId); +} + +QList QPlaceManagerEngineOsm::childCategories(const QString &parentId) const +{ + QList categories; + foreach (const QString &id, m_subcategories.value(parentId)) + categories.append(m_categories.value(id)); + return categories; +} + +QList QPlaceManagerEngineOsm::locales() const +{ + return m_locales; +} + +void QPlaceManagerEngineOsm::setLocales(const QList &locales) +{ + m_locales = locales; +} + +void QPlaceManagerEngineOsm::categoryReplyFinished() +{ + QNetworkReply *reply = qobject_cast(sender()); + if (!reply) + return; + + reply->deleteLater(); + + QXmlStreamReader parser(reply); + while (!parser.atEnd() && parser.readNextStartElement()) { + if (parser.name() == QLatin1String("mediawiki")) + continue; + if (parser.name() == QLatin1String("page")) + continue; + if (parser.name() == QLatin1String("revision")) + continue; + if (parser.name() == QLatin1String("text")) { + // parse + QString page = parser.readElementText(); + QRegularExpression regex(QStringLiteral("\\| ([^|]+) \\|\\| ([^|]+) \\|\\| ([^|]+) \\|\\| ([^|]+) \\|\\| ([\\-YN])")); + QRegularExpressionMatchIterator i = regex.globalMatch(page); + while (i.hasNext()) { + QRegularExpressionMatch match = i.next(); + QString name = match.capturedRef(1).toString(); + QString tagKey = match.capturedRef(2).toString(); + QString tagValue = match.capturedRef(3).toString(); + QString op = match.capturedRef(4).toString(); + QString plural = match.capturedRef(5).toString(); + + // Only interested in any operator plural forms + if (op != QLatin1String("-") || plural != QLatin1String("Y")) + continue; + + if (!m_categories.contains(tagKey)) { + QPlaceCategory category; + category.setCategoryId(tagKey); + category.setName(nameForTagKey(tagKey)); + m_categories.insert(category.categoryId(), category); + m_subcategories[QString()].append(tagKey); + emit categoryAdded(category, QString()); + } + + QPlaceCategory category; + category.setCategoryId(tagKey + QLatin1Char('=') + tagValue); + category.setName(name); + + if (!m_categories.contains(category.categoryId())) { + m_categories.insert(category.categoryId(), category); + m_subcategories[tagKey].append(category.categoryId()); + emit categoryAdded(category, tagKey); + } + } + } + + parser.skipCurrentElement(); + } + + if (m_categories.isEmpty() && !m_categoryLocales.isEmpty()) { + fetchNextCategoryLocale(); + return; + } else { + m_categoryLocales.clear(); + } + + foreach (QPlaceCategoriesReplyOsm *reply, m_pendingCategoriesReply) + reply->emitFinished(); + m_pendingCategoriesReply.clear(); +} + +void QPlaceManagerEngineOsm::categoryReplyError() +{ + foreach (QPlaceCategoriesReplyOsm *reply, m_pendingCategoriesReply) + reply->setError(QPlaceReply::CommunicationError, tr("Network request error")); +} + +void QPlaceManagerEngineOsm::replyFinished() +{ + QPlaceReply *reply = qobject_cast(sender()); + if (reply) + emit finished(reply); +} + +void QPlaceManagerEngineOsm::replyError(QPlaceReply::Error errorCode, const QString &errorString) +{ + QPlaceReply *reply = qobject_cast(sender()); + if (reply) + emit error(reply, errorCode, errorString); +} + +void QPlaceManagerEngineOsm::fetchNextCategoryLocale() +{ + if (m_categoryLocales.isEmpty()) { + qWarning("No locales specified to fetch categories for"); + return; + } + + QLocale locale = m_categoryLocales.takeFirst(); + + // FIXME: Categories should be cached. + QUrl requestUrl = QUrl(SpecialPhrasesBaseUrl + locale.name().left(2).toUpper()); + + m_categoriesReply = m_networkManager->get(QNetworkRequest(requestUrl)); + connect(m_categoriesReply, SIGNAL(finished()), this, SLOT(categoryReplyFinished())); + connect(m_categoriesReply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(categoryReplyError())); +} diff --git a/src/plugins/geoservices/osm/qplacemanagerengineosm.h b/src/plugins/geoservices/osm/qplacemanagerengineosm.h new file mode 100644 index 0000000..675c4ea --- /dev/null +++ b/src/plugins/geoservices/osm/qplacemanagerengineosm.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtFoo module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEMANAGERENGINEOSM_H +#define QPLACEMANAGERENGINEOSM_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QNetworkAccessManager; +class QNetworkReply; +class QPlaceCategoriesReplyOsm; + +class QPlaceManagerEngineOsm : public QPlaceManagerEngine +{ + Q_OBJECT + +public: + QPlaceManagerEngineOsm(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, + QString *errorString); + ~QPlaceManagerEngineOsm(); + + QPlaceSearchReply *search(const QPlaceSearchRequest &request) Q_DECL_OVERRIDE; + + QPlaceReply *initializeCategories() Q_DECL_OVERRIDE; + QString parentCategoryId(const QString &categoryId) const Q_DECL_OVERRIDE; + QStringList childCategoryIds(const QString &categoryId) const Q_DECL_OVERRIDE; + QPlaceCategory category(const QString &categoryId) const Q_DECL_OVERRIDE; + + QList childCategories(const QString &parentId) const Q_DECL_OVERRIDE; + + QList locales() const Q_DECL_OVERRIDE; + void setLocales(const QList &locales) Q_DECL_OVERRIDE; + +private slots: + void categoryReplyFinished(); + void categoryReplyError(); + void replyFinished(); + void replyError(QPlaceReply::Error errorCode, const QString &errorString); + +private: + void fetchNextCategoryLocale(); + + QNetworkAccessManager *m_networkManager; + QByteArray m_userAgent; + QString m_urlPrefix; + QList m_locales; + + QNetworkReply *m_categoriesReply; + QList m_pendingCategoriesReply; + QHash m_categories; + QHash m_subcategories; + + QList m_categoryLocales; +}; + +QT_END_NAMESPACE + +#endif // QPLACEMANAGERENGINEOSM_H diff --git a/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp b/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp new file mode 100644 index 0000000..3cb0ab6 --- /dev/null +++ b/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtFoo module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplacesearchreplyosm.h" +#include "qplacemanagerengineosm.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QPlaceSearchReplyOsm::QPlaceSearchReplyOsm(const QPlaceSearchRequest &request, + QNetworkReply *reply, QPlaceManagerEngineOsm *parent) +: QPlaceSearchReply(parent), m_reply(reply) +{ + Q_ASSERT(parent); + + setRequest(request); + + if (!m_reply) + return; + + m_reply->setParent(this); + connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); +} + +QPlaceSearchReplyOsm::~QPlaceSearchReplyOsm() +{ +} + +void QPlaceSearchReplyOsm::abort() +{ + if (m_reply) + m_reply->abort(); +} + +void QPlaceSearchReplyOsm::setError(QPlaceReply::Error errorCode, const QString &errorString) +{ + QPlaceReply::setError(errorCode, errorString); + emit error(errorCode, errorString); + setFinished(true); + emit finished(); +} + +static QGeoRectangle parseBoundingBox(const QJsonArray &coordinates) +{ + if (coordinates.count() != 4) + return QGeoRectangle(); + + double bottom = coordinates.at(0).toString().toDouble(); + double top = coordinates.at(1).toString().toDouble(); + double left = coordinates.at(2).toString().toDouble(); + double right = coordinates.at(3).toString().toDouble(); + + return QGeoRectangle(QGeoCoordinate(top, left), QGeoCoordinate(bottom, right)); +} + +void QPlaceSearchReplyOsm::replyFinished() +{ + QNetworkReply *reply = m_reply; + m_reply->deleteLater(); + m_reply = 0; + + if (reply->error() != QNetworkReply::NoError) { + setError(CommunicationError, tr("Communication error")); + return; + } + + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + if (!document.isArray()) { + setError(ParseError, tr("Response parse error")); + return; + } + + QJsonArray resultsArray = document.array(); + + QGeoCoordinate searchCenter = request().searchArea().center(); + + QStringList placeIds; + + QList results; + for (int i = 0; i < resultsArray.count(); ++i) { + QJsonObject item = resultsArray.at(i).toObject(); + QPlaceResult pr = parsePlaceResult(item); + pr.setDistance(searchCenter.distanceTo(pr.place().location().coordinate())); + placeIds.append(pr.place().placeId()); + results.append(pr); + } + + QVariantMap searchContext = request().searchContext().toMap(); + QStringList excludePlaceIds = + searchContext.value(QStringLiteral("ExcludePlaceIds")).toStringList(); + + if (!excludePlaceIds.isEmpty()) { + QPlaceSearchRequest r = request(); + QVariantMap parameters = searchContext; + + QStringList epi = excludePlaceIds; + epi.removeLast(); + + parameters.insert(QStringLiteral("ExcludePlaceIds"), epi); + r.setSearchContext(parameters); + setPreviousPageRequest(r); + } + + if (!placeIds.isEmpty()) { + QPlaceSearchRequest r = request(); + QVariantMap parameters = searchContext; + + QStringList epi = excludePlaceIds; + epi.append(placeIds.join(QLatin1Char(','))); + + parameters.insert(QStringLiteral("ExcludePlaceIds"), epi); + r.setSearchContext(parameters); + setNextPageRequest(r); + } + + setResults(results); + + setFinished(true); + emit finished(); +} + +QPlaceResult QPlaceSearchReplyOsm::parsePlaceResult(const QJsonObject &item) const +{ + QPlace place; + + QGeoCoordinate coordinate = QGeoCoordinate(item.value(QStringLiteral("lat")).toString().toDouble(), + item.value(QStringLiteral("lon")).toString().toDouble()); + + //const QString placeRank = item.value(QStringLiteral("place_rank")).toString(); + //const QString category = item.value(QStringLiteral("category")).toString(); + const QString type = item.value(QStringLiteral("type")).toString(); + //double importance = item.value(QStringLiteral("importance")).toDouble(); + + place.setAttribution(item.value(QStringLiteral("licence")).toString()); + place.setPlaceId(item.value(QStringLiteral("place_id")).toString()); + + QVariantMap iconParameters; + iconParameters.insert(QPlaceIcon::SingleUrl, + QUrl(item.value(QStringLiteral("icon")).toString())); + QPlaceIcon icon; + icon.setParameters(iconParameters); + place.setIcon(icon); + + QJsonObject addressDetails = item.value(QStringLiteral("address")).toObject(); + + const QString title = addressDetails.value(type).toString(); + + place.setName(title); + + QGeoAddress address; + address.setCity(addressDetails.value(QStringLiteral("city")).toString()); + address.setCountry(addressDetails.value(QStringLiteral("country")).toString()); + // FIXME: country_code is alpha-2 setCountryCode takes alpha-3 + //address.setCountryCode(addressDetails.value(QStringLiteral("country_code")).toString()); + address.setPostalCode(addressDetails.value(QStringLiteral("postcode")).toString()); + address.setStreet(addressDetails.value(QStringLiteral("road")).toString()); + address.setState(addressDetails.value(QStringLiteral("state")).toString()); + address.setDistrict(addressDetails.value(QStringLiteral("suburb")).toString()); + + QGeoLocation location; + location.setCoordinate(coordinate); + location.setAddress(address); + location.setBoundingBox(parseBoundingBox(item.value(QStringLiteral("boundingbox")).toArray())); + + place.setLocation(location); + + QPlaceResult result; + result.setIcon(icon); + result.setPlace(place); + result.setTitle(title); + + return result; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qplacesearchreplyosm.h b/src/plugins/geoservices/osm/qplacesearchreplyosm.h new file mode 100644 index 0000000..e495d4f --- /dev/null +++ b/src/plugins/geoservices/osm/qplacesearchreplyosm.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtFoo module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACESEARCHREPLYOSM_H +#define QPLACESEARCHREPLYOSM_H + +#include + +QT_BEGIN_NAMESPACE + +class QNetworkReply; +class QPlaceManagerEngineOsm; +class QPlaceResult; + +class QPlaceSearchReplyOsm : public QPlaceSearchReply +{ + Q_OBJECT + +public: + QPlaceSearchReplyOsm(const QPlaceSearchRequest &request, QNetworkReply *reply, + QPlaceManagerEngineOsm *parent); + ~QPlaceSearchReplyOsm(); + + void abort(); + +private slots: + void setError(QPlaceReply::Error errorCode, const QString &errorString); + void replyFinished(); + +private: + QPlaceResult parsePlaceResult(const QJsonObject &item) const; + + QNetworkReply *m_reply; +}; + +QT_END_NAMESPACE + +#endif // QPLACESEARCHREPLYOSM_H diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro new file mode 100644 index 0000000..35b462d --- /dev/null +++ b/src/plugins/plugins.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +qtHaveModule(positioning): SUBDIRS += position +qtHaveModule(location): SUBDIRS += geoservices diff --git a/src/plugins/position/android/android.pro b/src/plugins/position/android/android.pro new file mode 100644 index 0000000..0dc6a3f --- /dev/null +++ b/src/plugins/position/android/android.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += jar src diff --git a/src/plugins/position/android/jar/AndroidManifest.xml b/src/plugins/position/android/jar/AndroidManifest.xml new file mode 100644 index 0000000..2d066db --- /dev/null +++ b/src/plugins/position/android/jar/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + diff --git a/src/plugins/position/android/jar/bundledjar.pro b/src/plugins/position/android/jar/bundledjar.pro new file mode 100644 index 0000000..e7bd106 --- /dev/null +++ b/src/plugins/position/android/jar/bundledjar.pro @@ -0,0 +1,3 @@ +TARGET = QtPositioning-bundled +CONFIG += bundled_jar_file +include(jar.pri) diff --git a/src/plugins/position/android/jar/distributedjar.pro b/src/plugins/position/android/jar/distributedjar.pro new file mode 100644 index 0000000..4a5faaa --- /dev/null +++ b/src/plugins/position/android/jar/distributedjar.pro @@ -0,0 +1,3 @@ +TARGET = QtPositioning +include(jar.pri) + diff --git a/src/plugins/position/android/jar/jar.pri b/src/plugins/position/android/jar/jar.pri new file mode 100644 index 0000000..9fa548f --- /dev/null +++ b/src/plugins/position/android/jar/jar.pri @@ -0,0 +1,14 @@ +load(qt_build_paths) + +CONFIG += java +DESTDIR = $$MODULE_BASE_OUTDIR/jar + +JAVACLASSPATH += $$PWD/src + +JAVASOURCES += \ + $$PWD/src/org/qtproject/qt5/android/positioning/QtPositioning.java + +# install +target.path = $$[QT_INSTALL_PREFIX]/jar +INSTALLS += target + diff --git a/src/plugins/position/android/jar/jar.pro b/src/plugins/position/android/jar/jar.pro new file mode 100644 index 0000000..8d19c1b --- /dev/null +++ b/src/plugins/position/android/jar/jar.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += bundledjar.pro distributedjar.pro diff --git a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java new file mode 100644 index 0000000..b55a90d --- /dev/null +++ b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java @@ -0,0 +1,582 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt5.android.positioning; + +import android.content.Context; +import android.location.GpsSatellite; +import android.location.GpsStatus; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import android.util.Log; + +public class QtPositioning implements LocationListener +{ + + private static final String TAG = "QtPositioning"; + static LocationManager locationManager = null; + static Object m_syncObject = new Object(); + static HashMap runningListeners = new HashMap(); + + /* + The positionInfo instance to which this + QtPositioning instance is attached to. + */ + private int nativeClassReference = 0; + + /* + The provider type requested by Qt + */ + private int expectedProviders = 0; + + public static final int QT_GPS_PROVIDER = 1; + public static final int QT_NETWORK_PROVIDER = 2; + + /* The following values must match the corresponding error enums in the Qt API*/ + public static final int QT_ACCESS_ERROR = 0; + public static final int QT_CLOSED_ERROR = 1; + public static final int QT_POSITION_UNKNOWN_SOURCE_ERROR = 2; + public static final int QT_POSITION_NO_ERROR = 3; + public static final int QT_SATELLITE_NO_ERROR = 2; + public static final int QT_SATELLITE_UNKNOWN_SOURCE_ERROR = -1; + + /* True, if updates were caused by requestUpdate() */ + private boolean isSingleUpdate = false; + /* The length requested for regular intervals in msec. */ + private int updateIntervalTime = 0; + + /* The last received GPS update */ + private Location lastGps = null; + /* The last received network update */ + private Location lastNetwork = null; + /* If true this class acts as satellite signal monitor rather than location monitor */ + private boolean isSatelliteUpdate = false; + + private PositioningLooper looperThread; + + static public void setContext(Context context) + { + try { + locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE); + } catch(Exception e) { + e.printStackTrace(); + } + } + + static private int[] providerList() + { + List providers = locationManager.getAllProviders(); + int retList[] = new int[providers.size()]; + for (int i = 0; i < providers.size(); i++) { + if (providers.get(i).equals(LocationManager.GPS_PROVIDER)) { + //must be in sync with AndroidPositioning::PositionProvider::PROVIDER_GPS + retList[i] = 0; + } else if (providers.get(i).equals(LocationManager.NETWORK_PROVIDER)) { + //must be in sync with AndroidPositioning::PositionProvider::PROVIDER_NETWORK + retList[i] = 1; + } else if (providers.get(i).equals(LocationManager.PASSIVE_PROVIDER)) { + //must be in sync with AndroidPositioning::PositionProvider::PROVIDER_PASSIVE + retList[i] = 2; + } else { + retList[i] = -1; + } + } + return retList; + } + + static public Location lastKnownPosition(boolean fromSatelliteOnly) + { + Location gps = null; + Location network = null; + try { + gps = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + if (!fromSatelliteOnly) + network = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); + } catch(Exception e) { + e.printStackTrace(); + gps = network = null; + } + + if (gps != null && network != null) { + //we return the most recent location but slightly prefer GPS + //prefer GPS if it is max 4 hrs older than network + long delta = network.getTime() - gps.getTime(); + if (delta < 4*60*60*1000) { + return gps; + } else { + return network; + } + } else if (gps != null ) { + return gps; + } else if (network != null) { + return network; + } + + return null; + } + + /* Returns true if at least on of the given providers is enabled. */ + static private boolean expectedProvidersAvailable(int desiredProviders) + { + List enabledProviders = locationManager.getProviders(true); + if ((desiredProviders & QT_GPS_PROVIDER) > 0) { //gps desired + if (enabledProviders.contains(LocationManager.GPS_PROVIDER)) { + return true; + } + } + if ((desiredProviders & QT_NETWORK_PROVIDER) > 0) { //network desired + if (enabledProviders.contains(LocationManager.NETWORK_PROVIDER)) { + return true; + } + } + + return false; + } + + + static private void addActiveListener(QtPositioning listener, String provider) + { + int androidClassKey = listener.nativeClassReference; + //start update thread + listener.setActiveLooper(true); + + if (runningListeners.containsKey(androidClassKey) && runningListeners.get(androidClassKey) != listener) { + removeActiveListener(androidClassKey); + } + + locationManager.requestSingleUpdate(provider, + listener, + listener.looper()); + + runningListeners.put(androidClassKey, listener); + } + + + static private void addActiveListener(QtPositioning listener, String provider, long minTime, float minDistance) + { + int androidClassKey = listener.nativeClassReference; + //start update thread + listener.setActiveLooper(true); + + if (runningListeners.containsKey(androidClassKey) && runningListeners.get(androidClassKey) != listener) { + removeActiveListener(androidClassKey); + } + + locationManager.requestLocationUpdates(provider, + minTime, minDistance, + listener, + listener.looper()); + + runningListeners.put(androidClassKey, listener); + } + + + static private void removeActiveListener(QtPositioning listener) + { + removeActiveListener(listener.nativeClassReference); + } + + + static private void removeActiveListener(int androidClassKey) + { + QtPositioning listener = runningListeners.remove(androidClassKey); + locationManager.removeUpdates(listener); + listener.setActiveLooper(false); + } + + + static public int startUpdates(int androidClassKey, int locationProvider, int updateInterval) + { + synchronized (m_syncObject) { + try { + boolean exceptionOccurred = false; + QtPositioning positioningListener = new QtPositioning(); + positioningListener.nativeClassReference = androidClassKey; + positioningListener.expectedProviders = locationProvider; + positioningListener.isSatelliteUpdate = false; + + if (updateInterval == 0) + updateInterval = 50; //don't update more often than once per 50ms + + positioningListener.updateIntervalTime = updateInterval; + if ((locationProvider & QT_GPS_PROVIDER) > 0) { + Log.d(TAG, "Regular updates using GPS " + updateInterval); + try { + addActiveListener(positioningListener, + LocationManager.GPS_PROVIDER, + updateInterval, 0); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + } + + if ((locationProvider & QT_NETWORK_PROVIDER) > 0) { + Log.d(TAG, "Regular updates using network " + updateInterval); + try { + addActiveListener(positioningListener, + LocationManager.NETWORK_PROVIDER, + updateInterval, 0); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + } + if (exceptionOccurred) { + removeActiveListener(positioningListener); + return QT_ACCESS_ERROR; + } + + if (!expectedProvidersAvailable(locationProvider)) { + //all location providers unavailbe -> when they come back we resume automatically + return QT_CLOSED_ERROR; + } + + } catch(Exception e) { + e.printStackTrace(); + return QT_POSITION_UNKNOWN_SOURCE_ERROR; + } + + return QT_POSITION_NO_ERROR; + } + } + + static public void stopUpdates(int androidClassKey) + { + synchronized (m_syncObject) { + try { + Log.d(TAG, "Stopping updates"); + removeActiveListener(androidClassKey); + } catch(Exception e) { + e.printStackTrace(); + return; + } + } + } + + static public int requestUpdate(int androidClassKey, int locationProvider) + { + synchronized (m_syncObject) { + try { + boolean exceptionOccurred = false; + QtPositioning positioningListener = new QtPositioning(); + positioningListener.nativeClassReference = androidClassKey; + positioningListener.isSingleUpdate = true; + positioningListener.expectedProviders = locationProvider; + positioningListener.isSatelliteUpdate = false; + + if ((locationProvider & QT_GPS_PROVIDER) > 0) { + Log.d(TAG, "Single update using GPS"); + try { + addActiveListener(positioningListener, LocationManager.GPS_PROVIDER); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + } + + if ((locationProvider & QT_NETWORK_PROVIDER) > 0) { + Log.d(TAG, "Single update using network"); + try { + addActiveListener(positioningListener, LocationManager.NETWORK_PROVIDER); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + } + if (exceptionOccurred) { + removeActiveListener(positioningListener); + return QT_ACCESS_ERROR; + } + + if (!expectedProvidersAvailable(locationProvider)) { + //all location providers unavailable -> when they come back we resume automatically + //in the mean time return ClosedError + return QT_CLOSED_ERROR; + } + + } catch(Exception e) { + e.printStackTrace(); + return QT_POSITION_UNKNOWN_SOURCE_ERROR; + } + + return QT_POSITION_NO_ERROR; + } + } + + static public int startSatelliteUpdates(int androidClassKey, int updateInterval, boolean isSingleRequest) + { + synchronized (m_syncObject) { + try { + boolean exceptionOccurred = false; + QtPositioning positioningListener = new QtPositioning(); + positioningListener.isSatelliteUpdate = true; + positioningListener.nativeClassReference = androidClassKey; + positioningListener.expectedProviders = 1; //always satellite provider + positioningListener.isSingleUpdate = isSingleRequest; + + if (updateInterval == 0) + updateInterval = 50; //don't update more often than once per 50ms + + if (isSingleRequest) + Log.d(TAG, "Single update for Satellites " + updateInterval); + else + Log.d(TAG, "Regular updates for Satellites " + updateInterval); + try { + addActiveListener(positioningListener, LocationManager.GPS_PROVIDER, + updateInterval, 0); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + + if (exceptionOccurred) { + removeActiveListener(positioningListener); + return QT_ACCESS_ERROR; + } + + if (!expectedProvidersAvailable(positioningListener.expectedProviders)) { + //all location providers unavailable -> when they come back we resume automatically + //in the mean time return ClosedError + return QT_CLOSED_ERROR; + } + + } catch(Exception e) { + e.printStackTrace(); + return QT_SATELLITE_UNKNOWN_SOURCE_ERROR; + } + + return QT_SATELLITE_NO_ERROR; + } + } + + public QtPositioning() + { + looperThread = new PositioningLooper(); + } + + public Looper looper() + { + return looperThread.looper(); + } + + private void setActiveLooper(boolean setActive) + { + try{ + if (setActive) { + if (looperThread.isAlive()) + return; + + if (isSatelliteUpdate) + looperThread.isSatelliteListener(true); + + long start = System.currentTimeMillis(); + looperThread.start(); + + //busy wait but lasts ~20-30 ms only + while (!looperThread.isReady()); + + long stop = System.currentTimeMillis(); + Log.d(TAG, "Looper Thread startup time in ms: " + (stop-start)); + } else { + looperThread.quitLooper(); + } + } catch(Exception e) { + e.printStackTrace(); + } + } + + private class PositioningLooper extends Thread implements GpsStatus.Listener{ + private boolean looperRunning; + private Looper posLooper; + private boolean isSatelliteLooper = false; + private LocationManager locManager = null; + + private PositioningLooper() + { + looperRunning = false; + } + + public void run() + { + Looper.prepare(); + Handler handler = new Handler(); + + if (isSatelliteLooper) { + try { + locationManager.addGpsStatusListener(this); + } catch(Exception e) { + e.printStackTrace(); + } + } + + posLooper = Looper.myLooper(); + synchronized (this) { + looperRunning = true; + } + Looper.loop(); + synchronized (this) { + looperRunning = false; + } + } + + public void quitLooper() + { + if (isSatelliteLooper) + locationManager.removeGpsStatusListener(this); + looper().quit(); + } + + public synchronized boolean isReady() + { + return looperRunning; + } + + public void isSatelliteListener(boolean isListener) + { + isSatelliteLooper = isListener; + } + + public Looper looper() + { + return posLooper; + } + + @Override + public void onGpsStatusChanged(int event) { + switch (event) { + case GpsStatus.GPS_EVENT_FIRST_FIX: + break; + case GpsStatus.GPS_EVENT_SATELLITE_STATUS: + GpsStatus status = locationManager.getGpsStatus(null); + Iterable iterable = status.getSatellites(); + Iterator it = iterable.iterator(); + + ArrayList list = new ArrayList(); + while (it.hasNext()) { + GpsSatellite sat = (GpsSatellite) it.next(); + list.add(sat); + } + GpsSatellite[] sats = list.toArray(new GpsSatellite[list.size()]); + satelliteUpdated(sats, nativeClassReference, isSingleUpdate); + + break; + case GpsStatus.GPS_EVENT_STARTED: + break; + case GpsStatus.GPS_EVENT_STOPPED: + break; + } + } + } + + + + public static native void positionUpdated(Location update, int androidClassKey, boolean isSingleUpdate); + public static native void locationProvidersDisabled(int androidClassKey); + public static native void satelliteUpdated(GpsSatellite[] update, int androidClassKey, boolean isSingleUpdate); + + @Override + public void onLocationChanged(Location location) { + //Log.d(TAG, "**** Position Update ****: " + location.toString() + " " + isSingleUpdate); + if (location == null) + return; + + if (isSatelliteUpdate) //we are a QGeoSatelliteInfoSource -> ignore + return; + + if (isSingleUpdate || expectedProviders < 3) { + positionUpdated(location, nativeClassReference, isSingleUpdate); + return; + } + + /* + We can use GPS and Network, pick the better location provider. + Generally we prefer GPS data due to their higher accurancy but we + let Network data pass until GPS fix is available + */ + + if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) { + lastGps = location; + + // assumption: GPS always better -> pass it on + positionUpdated(location, nativeClassReference, isSingleUpdate); + } else if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) { + lastNetwork = location; + + if (lastGps == null) { //no GPS fix yet use network location + positionUpdated(location, nativeClassReference, isSingleUpdate); + return; + } + + long delta = location.getTime() - lastGps.getTime(); + + // Ignore if network update is older than last GPS (delta < 0) + // Ignore if gps update still has time to provide next location (delta < updateInterval) + if (delta < updateIntervalTime) + return; + + // Use network data -> GPS has timed out on updateInterval + positionUpdated(location, nativeClassReference, isSingleUpdate); + } + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) {} + + @Override + public void onProviderEnabled(String provider) { + Log.d(TAG, "Enabled provider: " + provider); + } + + @Override + public void onProviderDisabled(String provider) { + Log.d(TAG, "Disabled provider: " + provider); + if (!expectedProvidersAvailable(expectedProviders)) + locationProvidersDisabled(nativeClassReference); + } +} diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp new file mode 100644 index 0000000..e0124eb --- /dev/null +++ b/src/plugins/position/android/src/jnipositioning.cpp @@ -0,0 +1,577 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "qgeopositioninfosource_android_p.h" +#include "qgeosatelliteinfosource_android_p.h" + +#include "jnipositioning.h" + +static JavaVM *javaVM = 0; +jclass positioningClass; + +static jmethodID providerListMethodId; +static jmethodID lastKnownPositionMethodId; +static jmethodID startUpdatesMethodId; +static jmethodID stopUpdatesMethodId; +static jmethodID requestUpdateMethodId; +static jmethodID startSatelliteUpdatesMethodId; + +static const char logTag[] = "QtPositioning"; +static const char classErrorMsg[] = "Can't find class \"%s\""; +static const char methodErrorMsg[] = "Can't find method \"%s%s\""; + +namespace AndroidPositioning { + typedef QMap PositionSourceMap; + typedef QMap SatelliteSourceMap; + + Q_GLOBAL_STATIC(PositionSourceMap, idToPosSource) + + Q_GLOBAL_STATIC(SatelliteSourceMap, idToSatSource) + + struct AttachedJNIEnv + { + AttachedJNIEnv() + { + attached = false; + if (javaVM->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) < 0) { + if (javaVM->AttachCurrentThread(&jniEnv, NULL) < 0) { + __android_log_print(ANDROID_LOG_ERROR, logTag, "AttachCurrentThread failed"); + jniEnv = 0; + return; + } + attached = true; + } + } + + ~AttachedJNIEnv() + { + if (attached) + javaVM->DetachCurrentThread(); + } + bool attached; + JNIEnv *jniEnv; + }; + + int registerPositionInfoSource(QObject *obj) + { + static bool firstInit = true; + if (firstInit) { + qsrand( QDateTime::currentDateTime().toTime_t() ); + firstInit = false; + } + + int key = -1; + if (obj->inherits("QGeoPositionInfoSource")) { + QGeoPositionInfoSourceAndroid *src = qobject_cast(obj); + Q_ASSERT(src); + do { + key = qrand(); + } while (idToPosSource()->contains(key)); + + idToPosSource()->insert(key, src); + } else if (obj->inherits("QGeoSatelliteInfoSource")) { + QGeoSatelliteInfoSourceAndroid *src = qobject_cast(obj); + Q_ASSERT(src); + do { + key = qrand(); + } while (idToSatSource()->contains(key)); + + idToSatSource()->insert(key, src); + } + + return key; + } + + void unregisterPositionInfoSource(int key) + { + idToPosSource()->remove(key); + idToSatSource()->remove(key); + } + + enum PositionProvider + { + PROVIDER_GPS = 0, + PROVIDER_NETWORK = 1, + PROVIDER_PASSIVE = 2 + }; + + + QGeoPositionInfoSource::PositioningMethods availableProviders() + { + QGeoPositionInfoSource::PositioningMethods ret = + static_cast(0); + AttachedJNIEnv env; + if (!env.jniEnv) + return ret; + jintArray jProviders = static_cast(env.jniEnv->CallStaticObjectMethod( + positioningClass, providerListMethodId)); + jint *providers = env.jniEnv->GetIntArrayElements(jProviders, 0); + const uint size = env.jniEnv->GetArrayLength(jProviders); + for (uint i = 0; i < size; i++) { + switch (providers[i]) { + case PROVIDER_GPS: + ret |= QGeoPositionInfoSource::SatellitePositioningMethods; + break; + case PROVIDER_NETWORK: + ret |= QGeoPositionInfoSource::NonSatellitePositioningMethods; + break; + case PROVIDER_PASSIVE: + //we ignore as Qt doesn't have interface for it right now + break; + default: + __android_log_print(ANDROID_LOG_INFO, logTag, "Unknown positioningMethod"); + } + } + + env.jniEnv->ReleaseIntArrayElements(jProviders, providers, 0); + env.jniEnv->DeleteLocalRef(jProviders); + + return ret; + } + + //caching originally taken from corelib/kernel/qjni.cpp + typedef QHash JMethodIDHash; + Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID) + + static jmethodID getCachedMethodID(JNIEnv *env, + jclass clazz, + const char *name, + const char *sig) + { + jmethodID id = 0; + int offset_name = qstrlen(name); + int offset_signal = qstrlen(sig); + QByteArray key(offset_name + offset_signal, Qt::Uninitialized); + memcpy(key.data(), name, offset_name); + memcpy(key.data()+offset_name, sig, offset_signal); + QHash::iterator it = cachedMethodID->find(key); + if (it == cachedMethodID->end()) { + id = env->GetMethodID(clazz, name, sig); + if (env->ExceptionCheck()) { + id = 0; + #ifdef QT_DEBUG + env->ExceptionDescribe(); + #endif // QT_DEBUG + env->ExceptionClear(); + } + + cachedMethodID->insert(key, id); + } else { + id = it.value(); + } + return id; + } + + QGeoPositionInfo positionInfoFromJavaLocation(JNIEnv * jniEnv, const jobject &location) + { + QGeoPositionInfo info; + jclass thisClass = jniEnv->GetObjectClass(location); + if (!thisClass) + return QGeoPositionInfo(); + + jmethodID mid = getCachedMethodID(jniEnv, thisClass, "getLatitude", "()D"); + jdouble latitude = jniEnv->CallDoubleMethod(location, mid); + mid = getCachedMethodID(jniEnv, thisClass, "getLongitude", "()D"); + jdouble longitude = jniEnv->CallDoubleMethod(location, mid); + QGeoCoordinate coordinate(latitude, longitude); + + //altitude + mid = getCachedMethodID(jniEnv, thisClass, "hasAltitude", "()Z"); + jboolean attributeExists = jniEnv->CallBooleanMethod(location, mid); + if (attributeExists) { + mid = getCachedMethodID(jniEnv, thisClass, "getAltitude", "()D"); + jdouble value = jniEnv->CallDoubleMethod(location, mid); + coordinate.setAltitude(value); + } + + info.setCoordinate(coordinate); + + //time stamp + mid = getCachedMethodID(jniEnv, thisClass, "getTime", "()J"); + jlong timestamp = jniEnv->CallLongMethod(location, mid); + info.setTimestamp(QDateTime::fromMSecsSinceEpoch(timestamp)); + + //accuracy + mid = getCachedMethodID(jniEnv, thisClass, "hasAccuracy", "()Z"); + attributeExists = jniEnv->CallBooleanMethod(location, mid); + if (attributeExists) { + mid = getCachedMethodID(jniEnv, thisClass, "getAccuracy", "()F"); + jfloat accuracy = jniEnv->CallFloatMethod(location, mid); + info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, accuracy); + } + + //ground speed + mid = getCachedMethodID(jniEnv, thisClass, "hasSpeed", "()Z"); + attributeExists = jniEnv->CallBooleanMethod(location, mid); + if (attributeExists) { + mid = getCachedMethodID(jniEnv, thisClass, "getSpeed", "()F"); + jfloat speed = jniEnv->CallFloatMethod(location, mid); + info.setAttribute(QGeoPositionInfo::GroundSpeed, speed); + } + + //bearing + mid = getCachedMethodID(jniEnv, thisClass, "hasBearing", "()Z"); + attributeExists = jniEnv->CallBooleanMethod(location, mid); + if (attributeExists) { + mid = getCachedMethodID(jniEnv, thisClass, "getBearing", "()F"); + jfloat bearing = jniEnv->CallFloatMethod(location, mid); + info.setAttribute(QGeoPositionInfo::Direction, bearing); + } + + jniEnv->DeleteLocalRef(thisClass); + return info; + } + + QList satelliteInfoFromJavaLocation(JNIEnv *jniEnv, + jobjectArray satellites, + QList* usedInFix) + { + QList sats; + jsize length = jniEnv->GetArrayLength(satellites); + for (int i = 0; iGetObjectArrayElement(satellites, i); + if (jniEnv->ExceptionOccurred()) { + qWarning() << "Cannot process all satellite data due to exception."; + break; + } + + jclass thisClass = jniEnv->GetObjectClass(element); + if (!thisClass) + continue; + + QGeoSatelliteInfo info; + + //signal strength + jmethodID mid = getCachedMethodID(jniEnv, thisClass, "getSnr", "()F"); + jfloat snr = jniEnv->CallFloatMethod(element, mid); + info.setSignalStrength((int)snr); + + //ignore any satellite with no signal whatsoever + if (qFuzzyIsNull(snr)) + continue; + + //prn + mid = getCachedMethodID(jniEnv, thisClass, "getPrn", "()I"); + jint prn = jniEnv->CallIntMethod(element, mid); + info.setSatelliteIdentifier(prn); + + if (prn >= 1 && prn <= 32) + info.setSatelliteSystem(QGeoSatelliteInfo::GPS); + else if (prn >= 65 && prn <= 96) + info.setSatelliteSystem(QGeoSatelliteInfo::GLONASS); + + //azimuth + mid = getCachedMethodID(jniEnv, thisClass, "getAzimuth", "()F"); + jfloat azimuth = jniEnv->CallFloatMethod(element, mid); + info.setAttribute(QGeoSatelliteInfo::Azimuth, azimuth); + + //elevation + mid = getCachedMethodID(jniEnv, thisClass, "getElevation", "()F"); + jfloat elevation = jniEnv->CallFloatMethod(element, mid); + info.setAttribute(QGeoSatelliteInfo::Elevation, elevation); + + //used in a fix + mid = getCachedMethodID(jniEnv, thisClass, "usedInFix", "()Z"); + jboolean inFix = jniEnv->CallBooleanMethod(element, mid); + + sats.append(info); + + if (inFix) + usedInFix->append(info); + + jniEnv->DeleteLocalRef(thisClass); + jniEnv->DeleteLocalRef(element); + } + + return sats; + } + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return QGeoPositionInfo(); + + jobject location = env.jniEnv->CallStaticObjectMethod(positioningClass, + lastKnownPositionMethodId, + fromSatellitePositioningMethodsOnly); + if (location == 0) + return QGeoPositionInfo(); + + const QGeoPositionInfo info = positionInfoFromJavaLocation(env.jniEnv, location); + env.jniEnv->DeleteLocalRef(location); + + return info; + } + + inline int positioningMethodToInt(QGeoPositionInfoSource::PositioningMethods m) + { + int providerSelection = 0; + if (m & QGeoPositionInfoSource::SatellitePositioningMethods) + providerSelection |= 1; + if (m & QGeoPositionInfoSource::NonSatellitePositioningMethods) + providerSelection |= 2; + + return providerSelection; + } + + QGeoPositionInfoSource::Error startUpdates(int androidClassKey) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return QGeoPositionInfoSource::UnknownSourceError; + + QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey); + + if (source) { + int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startUpdatesMethodId, + androidClassKey, + positioningMethodToInt(source->preferredPositioningMethods()), + source->updateInterval()); + switch (errorCode) { + case 0: + case 1: + case 2: + case 3: + return static_cast(errorCode); + default: + break; + } + } + + return QGeoPositionInfoSource::UnknownSourceError; + } + + //used for stopping regular and single updates + void stopUpdates(int androidClassKey) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return; + + env.jniEnv->CallStaticVoidMethod(positioningClass, stopUpdatesMethodId, androidClassKey); + } + + QGeoPositionInfoSource::Error requestUpdate(int androidClassKey) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return QGeoPositionInfoSource::UnknownSourceError; + + QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey); + + if (source) { + int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, requestUpdateMethodId, + androidClassKey, + positioningMethodToInt(source->preferredPositioningMethods())); + switch (errorCode) { + case 0: + case 1: + case 2: + case 3: + return static_cast(errorCode); + default: + break; + } + } + return QGeoPositionInfoSource::UnknownSourceError; + } + + QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey, bool isSingleRequest, int requestTimeout) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return QGeoSatelliteInfoSource::UnknownSourceError; + + QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey); + + if (source) { + int interval = source->updateInterval(); + if (isSingleRequest) + interval = requestTimeout; + int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startSatelliteUpdatesMethodId, + androidClassKey, + interval, isSingleRequest); + switch (errorCode) { + case -1: + case 0: + case 1: + case 2: + return static_cast(errorCode); + default: + qWarning() << "startSatelliteUpdates: Unknown error code " << errorCode; + break; + } + } + return QGeoSatelliteInfoSource::UnknownSourceError; + } +} + + +static void positionUpdated(JNIEnv *env, jobject /*thiz*/, jobject location, jint androidClassKey, jboolean isSingleUpdate) +{ + QGeoPositionInfo info = AndroidPositioning::positionInfoFromJavaLocation(env, location); + + QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey); + if (!source) { + qWarning("positionUpdated: source == 0"); + return; + } + + //we need to invoke indirectly as the Looper thread is likely to be not the same thread + if (!isSingleUpdate) + QMetaObject::invokeMethod(source, "processPositionUpdate", Qt::AutoConnection, + Q_ARG(QGeoPositionInfo, info)); + else + QMetaObject::invokeMethod(source, "processSinglePositionUpdate", Qt::AutoConnection, + Q_ARG(QGeoPositionInfo, info)); +} + +static void locationProvidersDisabled(JNIEnv *env, jobject /*thiz*/, jint androidClassKey) +{ + Q_UNUSED(env); + QObject *source = AndroidPositioning::idToPosSource()->value(androidClassKey); + if (!source) + source = AndroidPositioning::idToSatSource()->value(androidClassKey); + if (!source) { + qWarning("locationProvidersDisabled: source == 0"); + return; + } + + QMetaObject::invokeMethod(source, "locationProviderDisabled", Qt::AutoConnection); +} + +static void satelliteUpdated(JNIEnv *env, jobject /*thiz*/, jobjectArray satellites, jint androidClassKey, jboolean isSingleUpdate) +{ + QList inUse; + QList sats = AndroidPositioning::satelliteInfoFromJavaLocation(env, satellites, &inUse); + + QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey); + if (!source) { + qFatal("satelliteUpdated: source == 0"); + return; + } + + QMetaObject::invokeMethod(source, "processSatelliteUpdateInView", Qt::AutoConnection, + Q_ARG(QList, sats), Q_ARG(bool, isSingleUpdate)); + + QMetaObject::invokeMethod(source, "processSatelliteUpdateInUse", Qt::AutoConnection, + Q_ARG(QList, inUse), Q_ARG(bool, isSingleUpdate)); +} + + +#define FIND_AND_CHECK_CLASS(CLASS_NAME) \ +clazz = env->FindClass(CLASS_NAME); \ +if (!clazz) { \ + __android_log_print(ANDROID_LOG_FATAL, logTag, classErrorMsg, CLASS_NAME); \ + return JNI_FALSE; \ +} + +#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ +VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \ +if (!VAR) { \ + __android_log_print(ANDROID_LOG_FATAL, logTag, methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \ + return JNI_FALSE; \ +} + +static JNINativeMethod methods[] = { + {"positionUpdated", "(Landroid/location/Location;IZ)V", (void *)positionUpdated}, + {"locationProvidersDisabled", "(I)V", (void *) locationProvidersDisabled}, + {"satelliteUpdated", "([Landroid/location/GpsSatellite;IZ)V", (void *)satelliteUpdated} +}; + +static bool registerNatives(JNIEnv *env) +{ + jclass clazz; + FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/positioning/QtPositioning"); + positioningClass = static_cast(env->NewGlobalRef(clazz)); + + if (env->RegisterNatives(positioningClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives failed"); + return JNI_FALSE; + } + + GET_AND_CHECK_STATIC_METHOD(providerListMethodId, positioningClass, "providerList", "()[I"); + GET_AND_CHECK_STATIC_METHOD(lastKnownPositionMethodId, positioningClass, "lastKnownPosition", "(Z)Landroid/location/Location;"); + GET_AND_CHECK_STATIC_METHOD(startUpdatesMethodId, positioningClass, "startUpdates", "(III)I"); + GET_AND_CHECK_STATIC_METHOD(stopUpdatesMethodId, positioningClass, "stopUpdates", "(I)V"); + GET_AND_CHECK_STATIC_METHOD(requestUpdateMethodId, positioningClass, "requestUpdate", "(II)I"); + GET_AND_CHECK_STATIC_METHOD(startSatelliteUpdatesMethodId, positioningClass, "startSatelliteUpdates", "(IIZ)I"); + + return true; +} + +Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) +{ + static bool initialized = false; + if (initialized) + return JNI_VERSION_1_6; + initialized = true; + + typedef union { + JNIEnv *nativeEnvironment; + void *venv; + } UnionJNIEnvToVoid; + + __android_log_print(ANDROID_LOG_INFO, logTag, "Positioning start"); + UnionJNIEnvToVoid uenv; + uenv.venv = NULL; + javaVM = 0; + + if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed"); + return -1; + } + JNIEnv *env = uenv.nativeEnvironment; + if (!registerNatives(env)) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "registerNatives failed"); + return -1; + } + + javaVM = vm; + return JNI_VERSION_1_4; +} + diff --git a/src/plugins/position/android/src/jnipositioning.h b/src/plugins/position/android/src/jnipositioning.h new file mode 100644 index 0000000..0de6a5a --- /dev/null +++ b/src/plugins/position/android/src/jnipositioning.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef JNIPOSITIONING_H +#define JNIPOSITIONING_H + +#include +#include + +namespace AndroidPositioning +{ + int registerPositionInfoSource(QObject *obj); + void unregisterPositionInfoSource(int key); + + QGeoPositionInfoSource::PositioningMethods availableProviders(); + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly); + + QGeoPositionInfoSource::Error startUpdates(int androidClassKey); + void stopUpdates(int androidClassKey); + QGeoPositionInfoSource::Error requestUpdate(int androidClassKey); + + QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey, + bool isSingleRequest, + int updateRequestTimeout); +} + +#endif // JNIPOSITIONING_H diff --git a/src/plugins/position/android/src/plugin.json b/src/plugins/position/android/src/plugin.json new file mode 100644 index 0000000..4fd8789 --- /dev/null +++ b/src/plugins/position/android/src/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["android"], + "Provider": "android", + "Position": true, + "Satellite": true, + "Monitor": false, + "Priority": 1000, + "Testable": false +} diff --git a/src/plugins/position/android/src/positionfactory_android.cpp b/src/plugins/position/android/src/positionfactory_android.cpp new file mode 100644 index 0000000..25d6ed0 --- /dev/null +++ b/src/plugins/position/android/src/positionfactory_android.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "positionfactory_android.h" +#include "qgeopositioninfosource_android_p.h" +#include "qgeosatelliteinfosource_android_p.h" + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryAndroid::positionInfoSource(QObject *parent) +{ + QGeoPositionInfoSourceAndroid *src = new QGeoPositionInfoSourceAndroid(parent); + return src; +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryAndroid::satelliteInfoSource(QObject *parent) +{ + QGeoSatelliteInfoSourceAndroid *src = new QGeoSatelliteInfoSourceAndroid(parent); + return src; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryAndroid::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} diff --git a/src/plugins/position/android/src/positionfactory_android.h b/src/plugins/position/android/src/positionfactory_android.h new file mode 100644 index 0000000..cdab6f1 --- /dev/null +++ b/src/plugins/position/android/src/positionfactory_android.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef POSITIONPOLLFACTORY_H +#define POSITIONPOLLFACTORY_H + +#include +#include + +class QGeoPositionInfoSourceFactoryAndroid : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +#endif // POSITIONPOLLFACTORY_H diff --git a/src/plugins/position/android/src/qgeopositioninfosource_android.cpp b/src/plugins/position/android/src/qgeopositioninfosource_android.cpp new file mode 100644 index 0000000..2c30196 --- /dev/null +++ b/src/plugins/position/android/src/qgeopositioninfosource_android.cpp @@ -0,0 +1,264 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosource_android_p.h" +#include "jnipositioning.h" +//#include +#include + +Q_DECLARE_METATYPE(QGeoPositionInfo) +#define UPDATE_FROM_COLD_START 2*60*1000 + + +QGeoPositionInfoSourceAndroid::QGeoPositionInfoSourceAndroid(QObject *parent) : + QGeoPositionInfoSource(parent), updatesRunning(false), m_error(NoError) +{ + qRegisterMetaType< QGeoPositionInfo >(); + androidClassKeyForUpdate = AndroidPositioning::registerPositionInfoSource(this); + androidClassKeyForSingleRequest = AndroidPositioning::registerPositionInfoSource(this); + + //qDebug() << "androidClassKey: " << androidClassKeyForUpdate << androidClassKeyForSingleRequest; + //by default use all methods + setPreferredPositioningMethods(AllPositioningMethods); + + m_requestTimer.setSingleShot(true); + QObject::connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestTimeout())); +} + +QGeoPositionInfoSourceAndroid::~QGeoPositionInfoSourceAndroid() +{ + stopUpdates(); + + if (m_requestTimer.isActive()) { + m_requestTimer.stop(); + AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest); + } + + AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForUpdate); + AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForSingleRequest); +} + +void QGeoPositionInfoSourceAndroid::setUpdateInterval(int msec) +{ + int previousInterval = updateInterval(); + msec = (((msec > 0) && (msec < minimumUpdateInterval())) || msec < 0)? minimumUpdateInterval() : msec; + + if (msec == previousInterval) + return; + + QGeoPositionInfoSource::setUpdateInterval(msec); + + if (updatesRunning) + reconfigureRunningSystem(); +} + +QGeoPositionInfo QGeoPositionInfoSourceAndroid::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +{ + return AndroidPositioning::lastKnownPosition(fromSatellitePositioningMethodsOnly); +} + +QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceAndroid::supportedPositioningMethods() const +{ + return AndroidPositioning::availableProviders(); +} + +void QGeoPositionInfoSourceAndroid::setPreferredPositioningMethods(QGeoPositionInfoSource::PositioningMethods methods) +{ + PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods(); + QGeoPositionInfoSource::setPreferredPositioningMethods(methods); + if (previousPreferredPositioningMethods == preferredPositioningMethods()) + return; + + if (updatesRunning) + reconfigureRunningSystem(); +} + +int QGeoPositionInfoSourceAndroid::minimumUpdateInterval() const +{ + return 50; +} + +QGeoPositionInfoSource::Error QGeoPositionInfoSourceAndroid::error() const +{ + return m_error; +} + +void QGeoPositionInfoSourceAndroid::setError(Error error) +{ + // qDebug() << "setError: " << error; + if (error != QGeoPositionInfoSource::NoError) + { + m_error = error; + emit QGeoPositionInfoSource::error(m_error); + } +} + +void QGeoPositionInfoSourceAndroid::startUpdates() +{ + if (updatesRunning) + return; + + if (preferredPositioningMethods() == 0) { + setError(UnknownSourceError); + return; + } + + updatesRunning = true; + QGeoPositionInfoSource::Error error = AndroidPositioning::startUpdates(androidClassKeyForUpdate); + if (error != QGeoPositionInfoSource::NoError) + updatesRunning = false; + + setError(error); +} + +void QGeoPositionInfoSourceAndroid::stopUpdates() +{ + if (!updatesRunning) + return; + + updatesRunning = false; + AndroidPositioning::stopUpdates(androidClassKeyForUpdate); +} + +void QGeoPositionInfoSourceAndroid::requestUpdate(int timeout) +{ + if (m_requestTimer.isActive()) + return; + + if (timeout != 0 && timeout < minimumUpdateInterval()) { + emit updateTimeout(); + return; + } + + if (timeout == 0) + timeout = UPDATE_FROM_COLD_START; + + m_requestTimer.start(timeout); + + // if updates already running with interval equal to timeout + // then we wait for next update coming through + // assume that a single update will not be quicker than regular updates anyway + if (updatesRunning && updateInterval() <= timeout) + return; + + QGeoPositionInfoSource::Error error = AndroidPositioning::requestUpdate(androidClassKeyForSingleRequest); + if (error != QGeoPositionInfoSource::NoError) + m_requestTimer.stop(); + + setError(error); +} + +void QGeoPositionInfoSourceAndroid::processPositionUpdate(const QGeoPositionInfo &pInfo) +{ + //single update request and served as part of regular update + if (m_requestTimer.isActive()) + m_requestTimer.stop(); + + emit positionUpdated(pInfo); +} + +// Might still be called multiple times (once for each provider) +void QGeoPositionInfoSourceAndroid::processSinglePositionUpdate(const QGeoPositionInfo &pInfo) +{ + //timeout but we received a late update -> ignore + if (!m_requestTimer.isActive()) + return; + + queuedSingleUpdates.append(pInfo); +} + +void QGeoPositionInfoSourceAndroid::locationProviderDisabled() +{ + setError(QGeoPositionInfoSource::ClosedError); +} + +void QGeoPositionInfoSourceAndroid::requestTimeout() +{ + AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest); + //no queued update to process -> timeout + const int count = queuedSingleUpdates.count(); + + if (!count) { + emit updateTimeout(); + return; + } + + //pick best + QGeoPositionInfo best = queuedSingleUpdates[0]; + for (int i = 1; i < count; i++) { + const QGeoPositionInfo info = queuedSingleUpdates[i]; + + //anything newer by 20s is always better + const int timeDelta = best.timestamp().secsTo(info.timestamp()); + if (abs(timeDelta) > 20) { + if (timeDelta > 0) + best = info; + continue; + } + + //compare accuracy + if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) && + info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + { + best = info.attribute(QGeoPositionInfo::HorizontalAccuracy) < + best.attribute(QGeoPositionInfo::HorizontalAccuracy) ? info : best; + continue; + } + + //prefer info with accuracy information + if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + best = info; + } + + queuedSingleUpdates.clear(); + emit positionUpdated(best); +} + +/* + Updates the system assuming that updateInterval + and/or preferredPositioningMethod have changed. + */ +void QGeoPositionInfoSourceAndroid::reconfigureRunningSystem() +{ + if (!updatesRunning) + return; + + stopUpdates(); + startUpdates(); +} diff --git a/src/plugins/position/android/src/qgeopositioninfosource_android_p.h b/src/plugins/position/android/src/qgeopositioninfosource_android_p.h new file mode 100644 index 0000000..dbb27f8 --- /dev/null +++ b/src/plugins/position/android/src/qgeopositioninfosource_android_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCE_ANDROID_P_H +#define QGEOPOSITIONINFOSOURCE_ANDROID_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +class QGeoPositionInfoSourceAndroid : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + QGeoPositionInfoSourceAndroid(QObject *parent = 0); + ~QGeoPositionInfoSourceAndroid(); + + // From QGeoPositionInfoSource + void setUpdateInterval(int msec); + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + PositioningMethods supportedPositioningMethods() const; + void setPreferredPositioningMethods(PositioningMethods methods); + int minimumUpdateInterval() const; + Error error() const; + +public Q_SLOTS: + virtual void startUpdates(); + virtual void stopUpdates(); + + virtual void requestUpdate(int timeout = 0); + + void processPositionUpdate(const QGeoPositionInfo& pInfo); + void processSinglePositionUpdate(const QGeoPositionInfo& pInfo); + + void locationProviderDisabled(); +private Q_SLOTS: + void requestTimeout(); + +private: + void reconfigureRunningSystem(); + void setError(Error error); + + bool updatesRunning; + int androidClassKeyForUpdate; + int androidClassKeyForSingleRequest; + QList queuedSingleUpdates; + Error m_error; + QTimer m_requestTimer; +}; + +#endif // QGEOPOSITIONINFOSOURCE_ANDROID_P_H diff --git a/src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp b/src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp new file mode 100644 index 0000000..f89f666 --- /dev/null +++ b/src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "qgeosatelliteinfosource_android_p.h" +#include "jnipositioning.h" + +Q_DECLARE_METATYPE(QGeoSatelliteInfo) +Q_DECLARE_METATYPE(QList) + +#define UPDATE_FROM_COLD_START 2*60*1000 + +QGeoSatelliteInfoSourceAndroid::QGeoSatelliteInfoSourceAndroid(QObject *parent) : + QGeoSatelliteInfoSource(parent), m_error(NoError), updatesRunning(false) +{ + qRegisterMetaType< QGeoSatelliteInfo >(); + qRegisterMetaType< QList >(); + androidClassKeyForUpdate = AndroidPositioning::registerPositionInfoSource(this); + androidClassKeyForSingleRequest = AndroidPositioning::registerPositionInfoSource(this); + + requestTimer.setSingleShot(true); + QObject::connect(&requestTimer, SIGNAL(timeout()), + this, SLOT(requestTimeout())); +} + +QGeoSatelliteInfoSourceAndroid::~QGeoSatelliteInfoSourceAndroid() +{ + stopUpdates(); + + if (requestTimer.isActive()) { + requestTimer.stop(); + AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest); + } + + AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForUpdate); + AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForSingleRequest); +} + + +void QGeoSatelliteInfoSourceAndroid::setUpdateInterval(int msec) +{ + int previousInterval = updateInterval(); + msec = (((msec > 0) && (msec < minimumUpdateInterval())) || msec < 0)? minimumUpdateInterval() : msec; + + if (msec == previousInterval) + return; + + QGeoSatelliteInfoSource::setUpdateInterval(msec); + + if (updatesRunning) + reconfigureRunningSystem(); +} + +int QGeoSatelliteInfoSourceAndroid::minimumUpdateInterval() const +{ + return 50; +} + +QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceAndroid::error() const +{ + return m_error; +} + +void QGeoSatelliteInfoSourceAndroid::startUpdates() +{ + if (updatesRunning) + return; + + updatesRunning = true; + + QGeoSatelliteInfoSource::Error error = AndroidPositioning::startSatelliteUpdates( + androidClassKeyForUpdate, false, updateInterval()); + if (error != QGeoSatelliteInfoSource::NoError) { + updatesRunning = false; + m_error = error; + emit QGeoSatelliteInfoSource::error(m_error); + } +} + +void QGeoSatelliteInfoSourceAndroid::stopUpdates() +{ + if (!updatesRunning) + return; + + updatesRunning = false; + AndroidPositioning::stopUpdates(androidClassKeyForUpdate); +} + +void QGeoSatelliteInfoSourceAndroid::requestUpdate(int timeout) +{ + if (requestTimer.isActive()) + return; + + if (timeout != 0 && timeout < minimumUpdateInterval()) { + emit requestTimeout(); + return; + } + + if (timeout == 0) + timeout = UPDATE_FROM_COLD_START; + + requestTimer.start(timeout); + + // if updates already running with interval equal or less then timeout + // then we wait for next update coming through + // assume that a single update will not be quicker than regular updates anyway + if (updatesRunning && updateInterval() <= timeout) + return; + + QGeoSatelliteInfoSource::Error error = AndroidPositioning::startSatelliteUpdates( + androidClassKeyForSingleRequest, true, timeout); + if (error != QGeoSatelliteInfoSource::NoError) { + requestTimer.stop(); + m_error = error; + emit QGeoSatelliteInfoSource::error(m_error); + } +} + +void QGeoSatelliteInfoSourceAndroid::processSatelliteUpdateInView(const QList &satsInView, bool isSingleUpdate) +{ + if (!isSingleUpdate) { + //if requested while regular updates were running + if (requestTimer.isActive()) + requestTimer.stop(); + emit QGeoSatelliteInfoSource::satellitesInViewUpdated(satsInView); + return; + } + + m_satsInView = satsInView; +} + +void QGeoSatelliteInfoSourceAndroid::processSatelliteUpdateInUse(const QList &satsInUse, bool isSingleUpdate) +{ + if (!isSingleUpdate) { + //if requested while regular updates were running + if (requestTimer.isActive()) + requestTimer.stop(); + emit QGeoSatelliteInfoSource::satellitesInUseUpdated(satsInUse); + return; + } + + m_satsInUse = satsInUse; +} + +void QGeoSatelliteInfoSourceAndroid::requestTimeout() +{ + AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest); + + const int count = m_satsInView.count(); + if (!count) { + emit requestTimeout(); + return; + } + + emit QGeoSatelliteInfoSource::satellitesInViewUpdated(m_satsInView); + emit QGeoSatelliteInfoSource::satellitesInUseUpdated(m_satsInUse); + + m_satsInUse.clear(); + m_satsInView.clear(); +} + +/* + Updates the system assuming that updateInterval + and/or preferredPositioningMethod have changed. + */ +void QGeoSatelliteInfoSourceAndroid::reconfigureRunningSystem() +{ + if (!updatesRunning) + return; + + stopUpdates(); + startUpdates(); +} + +void QGeoSatelliteInfoSourceAndroid::locationProviderDisabled() +{ + m_error = QGeoSatelliteInfoSource::ClosedError; + emit QGeoSatelliteInfoSource::error(m_error); +} diff --git a/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h b/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h new file mode 100644 index 0000000..37c64ad --- /dev/null +++ b/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QGEOSATELLITEINFOSOURCEANDROID_H +#define QGEOSATELLITEINFOSOURCEANDROID_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +class QGeoSatelliteInfoSourceAndroid : public QGeoSatelliteInfoSource +{ + Q_OBJECT +public: + explicit QGeoSatelliteInfoSourceAndroid(QObject *parent = 0); + ~QGeoSatelliteInfoSourceAndroid(); + + //From QGeoSatelliteInfoSource + void setUpdateInterval(int msec); + int minimumUpdateInterval() const; + + Error error() const; + +public Q_SLOTS: + void startUpdates(); + void stopUpdates(); + void requestUpdate(int timeout = 0); + + void processSatelliteUpdateInView(const QList &satsInView, bool isSingleUpdate); + void processSatelliteUpdateInUse(const QList &satsInUse, bool isSingleUpdate); + + void locationProviderDisabled(); +private Q_SLOTS: + void requestTimeout(); + +private: + void reconfigureRunningSystem(); + + Error m_error; + int androidClassKeyForUpdate; + int androidClassKeyForSingleRequest; + bool updatesRunning; + + QTimer requestTimer; + QList m_satsInUse; + QList m_satsInView; + +}; + +#endif // QGEOSATELLITEINFOSOURCEANDROID_H diff --git a/src/plugins/position/android/src/src.pro b/src/plugins/position/android/src/src.pro new file mode 100644 index 0000000..3a19c85 --- /dev/null +++ b/src/plugins/position/android/src/src.pro @@ -0,0 +1,21 @@ +TARGET = qtposition_android + +QT = core positioning + +HEADERS = \ + positionfactory_android.h \ + qgeopositioninfosource_android_p.h \ + jnipositioning.h \ + qgeosatelliteinfosource_android_p.h + +SOURCES = \ + positionfactory_android.cpp \ + qgeopositioninfosource_android.cpp \ + jnipositioning.cpp \ + qgeosatelliteinfosource_android.cpp + +OTHER_FILES = plugin.json + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryAndroid +load(qt_plugin) diff --git a/src/plugins/position/corelocation/corelocation.pro b/src/plugins/position/corelocation/corelocation.pro new file mode 100644 index 0000000..dbb5b6b --- /dev/null +++ b/src/plugins/position/corelocation/corelocation.pro @@ -0,0 +1,22 @@ +TARGET = qtposition_cl + +QT = core positioning + +OBJECTIVE_SOURCES += \ + qgeopositioninfosource_cl.mm \ + qgeopositioninfosourcefactory_cl.mm + +HEADERS += \ + qgeopositioninfosource_cl_p.h \ + qgeopositioninfosourcefactory_cl.h + +OTHER_FILES += \ + plugin.json + +osx: LIBS += -framework Foundation +else: ios|tvos: LIBS += -framework CoreFoundation +LIBS += -framework CoreLocation + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryCL +load(qt_plugin) diff --git a/src/plugins/position/corelocation/plugin.json b/src/plugins/position/corelocation/plugin.json new file mode 100644 index 0000000..58e3acd --- /dev/null +++ b/src/plugins/position/corelocation/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["corelocation"], + "Provider": "corelocation", + "Position": true, + "Satellite": false, + "Monitor" : false, + "Priority": 1000, + "Testable": false +} diff --git a/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm new file mode 100644 index 0000000..54a079a --- /dev/null +++ b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm @@ -0,0 +1,266 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "qgeopositioninfosource_cl_p.h" + +#define MINIMUM_UPDATE_INTERVAL 1000 + +@interface PositionLocationDelegate : NSObject +{ + QGeoPositionInfoSourceCL *m_positionInfoSource; +} +@end + +@implementation PositionLocationDelegate +- (id)initWithInfoSource:(QGeoPositionInfoSourceCL*) positionInfoSource +{ + self = [super init]; + if (self) { + m_positionInfoSource = positionInfoSource; + } + return self; +} + +- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation +{ + Q_UNUSED(manager) + Q_UNUSED(oldLocation) + + // Convert location timestamp to QDateTime + QDateTime timeStamp; + NSTimeInterval locationTimeStamp = [newLocation.timestamp timeIntervalSince1970]; + timeStamp.setTime_t((uint) locationTimeStamp); + timeStamp.setTime(timeStamp.time().addMSecs((uint)(locationTimeStamp * 1000) % 1000)); + + // Construct position info from location data + QGeoPositionInfo location(QGeoCoordinate(newLocation.coordinate.latitude, + newLocation.coordinate.longitude, + newLocation.altitude), + timeStamp); + if (newLocation.horizontalAccuracy >= 0) + location.setAttribute(QGeoPositionInfo::HorizontalAccuracy, newLocation.horizontalAccuracy); + if (newLocation.verticalAccuracy >= 0) + location.setAttribute(QGeoPositionInfo::VerticalAccuracy, newLocation.verticalAccuracy); +#ifndef Q_OS_TVOS + if (newLocation.course >= 0) + location.setAttribute(QGeoPositionInfo::Direction, newLocation.course); + if (newLocation.speed >= 0) + location.setAttribute(QGeoPositionInfo::GroundSpeed, newLocation.speed); +#endif + + m_positionInfoSource->locationDataAvailable(location); +} + +- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error +{ + Q_UNUSED(manager) + m_positionInfoSource->setError(QGeoPositionInfoSource::AccessError); + + qWarning() << QString::fromNSString([error localizedDescription]); + + if ([error code] == 0 + && QString::fromNSString([error domain]) == QStringLiteral("kCLErrorDomain")) + qWarning() << "(is Wi-Fi turned on?)"; +} +@end + +QT_BEGIN_NAMESPACE + +QGeoPositionInfoSourceCL::QGeoPositionInfoSourceCL(QObject *parent) + : QGeoPositionInfoSource(parent) + , m_locationManager(0) + , m_started(false) + , m_updateTimer(0) + , m_updateTimeout(0) + , m_positionError(QGeoPositionInfoSource::NoError) +{ +} + +QGeoPositionInfoSourceCL::~QGeoPositionInfoSourceCL() +{ + stopUpdates(); + [m_locationManager release]; +} + +void QGeoPositionInfoSourceCL::setUpdateInterval(int msec) +{ + // If msec is 0 we send updates as data becomes available, otherwise we force msec to be equal + // to or larger than the minimum update interval. + if (msec != 0 && msec < minimumUpdateInterval()) + msec = minimumUpdateInterval(); + + QGeoPositionInfoSource::setUpdateInterval(msec); + + // Must timeout if update takes longer than specified interval + m_updateTimeout = msec; + if (m_started) setTimeoutInterval(m_updateTimeout); +} + +bool QGeoPositionInfoSourceCL::enableLocationManager() +{ + if (!m_locationManager) { + m_locationManager = [[CLLocationManager alloc] init]; + m_locationManager.desiredAccuracy = kCLLocationAccuracyBest; + m_locationManager.delegate = [[PositionLocationDelegate alloc] initWithInfoSource:this]; + + // These two methods are new in iOS 8. They require NSLocationAlwaysUsageDescription + // and NSLocationWhenInUseUsageDescription to be set in Info.plist to work (methods are + // noop if there are no such entries in plist). + if ([m_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) + [m_locationManager performSelector:@selector(requestAlwaysAuthorization)]; + if ([m_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) + [m_locationManager performSelector:@selector(requestWhenInUseAuthorization)]; + } + + return (m_locationManager != 0); +} + +void QGeoPositionInfoSourceCL::setTimeoutInterval(int msec) +{ + // Start timeout timer + if (m_updateTimer) killTimer(m_updateTimer); + if (msec > 0) m_updateTimer = startTimer(msec); + else m_updateTimer = 0; +} + +void QGeoPositionInfoSourceCL::startUpdates() +{ + if (enableLocationManager()) { +#ifdef Q_OS_TVOS + [m_locationManager requestLocation]; // service will run long enough for one location update +#else + [m_locationManager startUpdatingLocation]; +#endif + m_started = true; + + setTimeoutInterval(m_updateTimeout); + } else setError(QGeoPositionInfoSource::AccessError); +} + +void QGeoPositionInfoSourceCL::stopUpdates() +{ + if (m_locationManager) { + [m_locationManager stopUpdatingLocation]; + m_started = false; + + // Stop timeout timer + setTimeoutInterval(0); + } else setError(QGeoPositionInfoSource::AccessError); +} + +void QGeoPositionInfoSourceCL::requestUpdate(int timeout) +{ + // Get a single update within timeframe + if (timeout < minimumUpdateInterval() && timeout != 0) + emit updateTimeout(); + else if (enableLocationManager()) { + // This will force LM to generate a new update + [m_locationManager stopUpdatingLocation]; +#ifdef Q_OS_TVOS + [m_locationManager requestLocation]; // service will run long enough for one location update +#else + [m_locationManager startUpdatingLocation]; +#endif + + setTimeoutInterval(timeout); + } else setError(QGeoPositionInfoSource::AccessError); +} + +void QGeoPositionInfoSourceCL::timerEvent( QTimerEvent * event ) +{ + // Update timed out? + if (event->timerId() == m_updateTimer) { + emit updateTimeout(); + + // Only timeout once since last data + setTimeoutInterval(0); + + // Started for single update? + if (!m_started) stopUpdates(); + } +} + +QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceCL::supportedPositioningMethods() const +{ + // CoreLocation doesn't say which positioning method(s) it used + return QGeoPositionInfoSource::AllPositioningMethods; +} + +int QGeoPositionInfoSourceCL::minimumUpdateInterval() const +{ + return MINIMUM_UPDATE_INTERVAL; +} + +void QGeoPositionInfoSourceCL::locationDataAvailable(QGeoPositionInfo location) +{ + // Signal position data available + m_lastUpdate = location; + emit positionUpdated(location); + + // Started for single update? + if (!m_started) stopUpdates(); + // ...otherwise restart timeout timer + else setTimeoutInterval(m_updateTimeout); +} + +QGeoPositionInfo QGeoPositionInfoSourceCL::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +{ + Q_UNUSED(fromSatellitePositioningMethodsOnly) + + return m_lastUpdate; +} + +QGeoPositionInfoSource::Error QGeoPositionInfoSourceCL::error() const +{ + return m_positionError; +} + +void QGeoPositionInfoSourceCL::setError(QGeoPositionInfoSource::Error positionError) +{ + m_positionError = positionError; + emit QGeoPositionInfoSource::error(positionError); +} + +#include "moc_qgeopositioninfosource_cl_p.cpp" + +QT_END_NAMESPACE diff --git a/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h b/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h new file mode 100644 index 0000000..cfd66bf --- /dev/null +++ b/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCECL_H +#define QGEOPOSITIONINFOSOURCECL_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#import + +#include "qgeopositioninfosource.h" +#include "qgeopositioninfo.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGeoPositionInfoSourceCL : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + QGeoPositionInfoSourceCL(QObject *parent = 0); + ~QGeoPositionInfoSourceCL(); + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + PositioningMethods supportedPositioningMethods() const; + + void setUpdateInterval(int msec); + int minimumUpdateInterval() const; + Error error() const; + + void locationDataAvailable(QGeoPositionInfo location); + void setError(QGeoPositionInfoSource::Error positionError); + +private: + bool enableLocationManager(); + void setTimeoutInterval(int msec); + +public Q_SLOTS: + void startUpdates(); + void stopUpdates(); + + void requestUpdate(int timeout = 0); + +protected: + virtual void timerEvent(QTimerEvent *event); + +private: + Q_DISABLE_COPY(QGeoPositionInfoSourceCL); + CLLocationManager *m_locationManager; + bool m_started; + + QGeoPositionInfo m_lastUpdate; + + int m_updateTimer; + int m_updateTimeout; + + QGeoPositionInfoSource::Error m_positionError; +}; + +QT_END_NAMESPACE + +#endif // QGEOPOSITIONINFOSOURCECL_H diff --git a/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.h b/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.h new file mode 100644 index 0000000..5ab1ce6 --- /dev/null +++ b/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCEFACTORY_CL_H +#define QGEOPOSITIONINFOSOURCEFACTORY_CL_H + +#include +#include + +class QGeoPositionInfoSourceFactoryCL : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +#endif // QGEOPOSITIONINFOSOURCEFACTORY_CL_H diff --git a/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.mm b/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.mm new file mode 100644 index 0000000..06a3ad3 --- /dev/null +++ b/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.mm @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosource_cl_p.h" +#include "qgeopositioninfosourcefactory_cl.h" + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryCL::positionInfoSource(QObject *parent) +{ + return new QGeoPositionInfoSourceCL(parent); +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryCL::satelliteInfoSource(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryCL::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} diff --git a/src/plugins/position/geoclue/geoclue.pro b/src/plugins/position/geoclue/geoclue.pro new file mode 100644 index 0000000..3f75cbf --- /dev/null +++ b/src/plugins/position/geoclue/geoclue.pro @@ -0,0 +1,38 @@ +TARGET = qtposition_geoclue + +QT = core positioning dbus + +HEADERS += \ + qgeopositioninfosource_geocluemaster.h \ + qgeosatelliteinfosource_geocluemaster.h \ + qgeopositioninfosourcefactory_geoclue.h \ + qgeocluemaster.h \ + geocluetypes.h + +SOURCES += \ + qgeopositioninfosource_geocluemaster.cpp \ + qgeosatelliteinfosource_geocluemaster.cpp \ + qgeopositioninfosourcefactory_geoclue.cpp \ + qgeocluemaster.cpp \ + geocluetypes.cpp + +QDBUSXML2CPP_INTERFACE_HEADER_FLAGS += "-N -i geocluetypes.h" +DBUS_INTERFACES += \ + org.freedesktop.Geoclue.MasterClient.xml \ + org.freedesktop.Geoclue.Master.xml \ + org.freedesktop.Geoclue.Position.xml \ + org.freedesktop.Geoclue.Velocity.xml \ + org.freedesktop.Geoclue.Satellite.xml \ + org.freedesktop.Geoclue.xml + +OTHER_FILES += \ + $$DBUS_INTERFACES + +INCLUDEPATH += $$QT.location.includes $$OUT_PWD + +OTHER_FILES += \ + plugin.json + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryGeoclue +load(qt_plugin) diff --git a/src/plugins/position/geoclue/geocluetypes.cpp b/src/plugins/position/geoclue/geocluetypes.cpp new file mode 100644 index 0000000..d50e624 --- /dev/null +++ b/src/plugins/position/geoclue/geocluetypes.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "geocluetypes.h" + +const QDBusArgument &dbus_argument_helper(const QDBusArgument &arg, Accuracy &accuracy) +{ + arg.beginStructure(); + qint32 level; + arg >> level; + accuracy.m_level = static_cast(level); + arg >> accuracy.m_horizontal; + arg >> accuracy.m_vertical; + arg.endStructure(); + + return arg; +} + +QT_BEGIN_NAMESPACE + +QDBusArgument &operator<<(QDBusArgument &arg, const Accuracy &accuracy) +{ + arg.beginStructure(); + arg << qint32(accuracy.level()); + arg << accuracy.horizontal(); + arg << accuracy.vertical(); + arg.endStructure(); + + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, Accuracy &accuracy) +{ + return dbus_argument_helper(arg, accuracy); +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, QGeoSatelliteInfo &si) +{ + qint32 a; + + argument.beginStructure(); + argument >> a; + si.setSatelliteIdentifier(a); + argument >> a; + si.setAttribute(QGeoSatelliteInfo::Elevation, a); + argument >> a; + si.setAttribute(QGeoSatelliteInfo::Azimuth, a); + argument >> a; + si.setSignalStrength(a); + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, QList &sis) +{ + sis.clear(); + + argument.beginArray(); + while (!argument.atEnd()) { + QGeoSatelliteInfo si; + argument >> si; + sis.append(si); + } + argument.endArray(); + + return argument; +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/geocluetypes.h b/src/plugins/position/geoclue/geocluetypes.h new file mode 100644 index 0000000..0e87b73 --- /dev/null +++ b/src/plugins/position/geoclue/geocluetypes.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GEOCLUETYPES_H +#define GEOCLUETYPES_H + +#include +#include + +class Accuracy +{ +public: + enum Level { + None = 0, + Country, + Region, + Locality, + PostalCode, + Street, + Detailed + }; + + Accuracy() + : m_level(None), m_horizontal(0), m_vertical(0) + { + } + + inline Level level() const { return m_level; } + inline double horizontal() const { return m_horizontal; } + inline double vertical() const { return m_vertical; } + +private: + Level m_level; + double m_horizontal; + double m_vertical; + + friend const QDBusArgument &dbus_argument_helper(const QDBusArgument &arg, Accuracy &accuracy); +}; + +Q_DECLARE_METATYPE(Accuracy) +Q_DECLARE_METATYPE(QList) + + +QT_BEGIN_NAMESPACE + +Q_DECLARE_TYPEINFO(Accuracy, Q_MOVABLE_TYPE); + +QDBusArgument &operator<<(QDBusArgument &arg, const Accuracy &accuracy); +const QDBusArgument &operator>>(const QDBusArgument &arg, Accuracy &accuracy); + +const QDBusArgument &operator>>(const QDBusArgument &arg, QGeoSatelliteInfo &si); +const QDBusArgument &operator>>(const QDBusArgument &arg, QList &sis); + +QT_END_NAMESPACE + +#endif // GEOCLUETYPES_H + diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Master.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Master.xml new file mode 100644 index 0000000..e7df140 --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Master.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.MasterClient.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.MasterClient.xml new file mode 100644 index 0000000..29c9588 --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.MasterClient.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml new file mode 100644 index 0000000..ce5c80d --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml new file mode 100644 index 0000000..2ed112c --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + ' + + + + + diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Velocity.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Velocity.xml new file mode 100644 index 0000000..a1be122 --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Velocity.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.xml new file mode 100644 index 0000000..c9b6f63 --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/position/geoclue/plugin.json b/src/plugins/position/geoclue/plugin.json new file mode 100644 index 0000000..82f8afc --- /dev/null +++ b/src/plugins/position/geoclue/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["geoclue"], + "Provider": "geoclue", + "Position": true, + "Satellite": true, + "Monitor": false, + "Priority": 999, + "Testable": false +} diff --git a/src/plugins/position/geoclue/qgeocluemaster.cpp b/src/plugins/position/geoclue/qgeocluemaster.cpp new file mode 100644 index 0000000..962cc7f --- /dev/null +++ b/src/plugins/position/geoclue/qgeocluemaster.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd, author: Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocluemaster.h" + +#include +#include +#include + +#include + +Q_DECLARE_LOGGING_CATEGORY(lcPositioningGeoclue) + +QT_BEGIN_NAMESPACE + +QGeoclueMaster::QGeoclueMaster(QObject *parent) +: QObject(parent), m_master(0), m_provider(0), m_client(0) +{ +} + +QGeoclueMaster::~QGeoclueMaster() +{ + releaseMasterClient(); + + delete m_master; +} + +bool QGeoclueMaster::hasMasterClient() const +{ + return m_client; +} + +bool QGeoclueMaster::createMasterClient(Accuracy::Level accuracyLevel, ResourceFlags resourceFlags) +{ + Q_ASSERT(!m_provider || !m_client); + + if (!m_master) { + qCDebug(lcPositioningGeoclue) << "creating master interface"; + m_master = new OrgFreedesktopGeoclueMasterInterface(QStringLiteral("org.freedesktop.Geoclue.Master"), + QStringLiteral("/org/freedesktop/Geoclue/Master"), + QDBusConnection::sessionBus()); + } + + qCDebug(lcPositioningGeoclue) << "creating client"; + QDBusPendingReply client = m_master->Create(); + if (client.isError()) { + QDBusError e = client.error(); + qCritical("Failed to create Geoclue client interface. Geoclue error: %s", + qPrintable(e.errorString(e.type()))); + return false; + } + + qCDebug(lcPositioningGeoclue) << "Geoclue client path:" << client.value().path(); + + m_provider = new OrgFreedesktopGeoclueInterface(QStringLiteral("org.freedesktop.Geoclue.Master"), + client.value().path(), QDBusConnection::sessionBus()); + m_provider->AddReference(); + + m_client = new OrgFreedesktopGeoclueMasterClientInterface(QStringLiteral("org.freedesktop.Geoclue.Master"), + client.value().path(), + QDBusConnection::sessionBus()); + + connect(m_client, SIGNAL(PositionProviderChanged(QString,QString,QString,QString)), + this, SIGNAL(positionProviderChanged(QString,QString,QString,QString))); + + QDBusPendingReply<> reply = m_client->SetRequirements(accuracyLevel, 0, true, resourceFlags); + if (reply.isError()) { + QDBusError e = reply.error(); + qCritical("Failed to set Geoclue positioning requirements. Geoclue error: %s", + qPrintable(e.errorString(e.type()))); + + releaseMasterClient(); + return false; + } + + // Need to create the master position interface even though it will not be used, otherwise + // GetPositionProvider always returns empty strings. + reply = m_client->PositionStart(); + if (reply.isError()) { + QDBusError e = reply.error(); + qCritical("Failed to start positioning. Geoclue error: %s", + qPrintable(e.errorString(e.type()))); + + releaseMasterClient(); + return false; + } + + return true; +} + +void QGeoclueMaster::releaseMasterClient() +{ + if (m_provider) + m_provider->RemoveReference(); + delete m_provider; + m_provider = 0; + delete m_client; + m_client = 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeocluemaster.h b/src/plugins/position/geoclue/qgeocluemaster.h new file mode 100644 index 0000000..c623dbd --- /dev/null +++ b/src/plugins/position/geoclue/qgeocluemaster.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd, author: Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCLUEMASTER_H +#define QGEOCLUEMASTER_H + +#include "geocluetypes.h" + +#include + +class OrgFreedesktopGeoclueMasterInterface; +class OrgFreedesktopGeoclueInterface; +class OrgFreedesktopGeoclueMasterClientInterface; + +QT_BEGIN_NAMESPACE + +class QGeoclueMaster : public QObject +{ + Q_OBJECT + +public: + QGeoclueMaster(QObject *parent = 0); + ~QGeoclueMaster(); + + enum ResourceFlag + { + ResourceNone = 0, + ResourceNetwork = 1 << 0, + ResourceCell = 1 << 1, + ResourceGps = 1 << 2, + ResourceAll = (1 << 10) - 1 + }; + + Q_DECLARE_FLAGS(ResourceFlags, ResourceFlag) + + bool hasMasterClient() const; + bool createMasterClient(Accuracy::Level accuracyLevel, ResourceFlags resourceFlags); + void releaseMasterClient(); + +signals: + void positionProviderChanged(const QString &name, const QString &description, + const QString &service, const QString &path); + +private: + OrgFreedesktopGeoclueMasterInterface *m_master; + OrgFreedesktopGeoclueInterface *m_provider; + OrgFreedesktopGeoclueMasterClientInterface *m_client; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoclueMaster::ResourceFlags) + +QT_END_NAMESPACE + +#endif // QGEOCLUEMASTER_H diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp new file mode 100644 index 0000000..1fba2e9 --- /dev/null +++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp @@ -0,0 +1,495 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosource_geocluemaster.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_DATASTREAM +#include +#endif + +Q_DECLARE_LOGGING_CATEGORY(lcPositioningGeoclue) + +#define MINIMUM_UPDATE_INTERVAL 1000 +#define UPDATE_TIMEOUT_COLD_START 120000 + +QT_BEGIN_NAMESPACE + +namespace +{ + +double knotsToMetersPerSecond(double knots) +{ + return knots * 1852.0 / 3600.0; +} + +} + +QGeoPositionInfoSourceGeoclueMaster::QGeoPositionInfoSourceGeoclueMaster(QObject *parent) +: QGeoPositionInfoSource(parent), m_master(new QGeoclueMaster(this)), m_provider(0), m_pos(0), + m_vel(0), m_lastVelocityIsFresh(false), m_regularUpdateTimedOut(false), m_lastVelocity(qQNaN()), + m_lastDirection(qQNaN()), m_lastClimb(qQNaN()), m_lastPositionFromSatellite(false), + m_running(false), m_error(NoError) +{ + qDBusRegisterMetaType(); + +#ifndef QT_NO_DATASTREAM + // Load the last known location + QFile file(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + + QStringLiteral("/qtposition-geoclue")); + if (file.open(QIODevice::ReadOnly)) { + QDataStream out(&file); + out >> m_lastPosition; + } +#endif + + connect(m_master, SIGNAL(positionProviderChanged(QString,QString,QString,QString)), + this, SLOT(positionProviderChanged(QString,QString,QString,QString))); + + m_requestTimer.setSingleShot(true); + connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout())); + + setPreferredPositioningMethods(AllPositioningMethods); +} + +QGeoPositionInfoSourceGeoclueMaster::~QGeoPositionInfoSourceGeoclueMaster() +{ +#ifndef QT_NO_DATASTREAM + if (m_lastPosition.isValid()) { + QSaveFile file(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + + QStringLiteral("/qtposition-geoclue")); + if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + QDataStream out(&file); + // Only save position and timestamp. + out << QGeoPositionInfo(m_lastPosition.coordinate(), m_lastPosition.timestamp()); + file.commit(); + } + } +#endif + + cleanupPositionSource(); +} + +void QGeoPositionInfoSourceGeoclueMaster::positionUpdateFailed() +{ + qCDebug(lcPositioningGeoclue) << "position update failed."; + + m_lastVelocityIsFresh = false; + if (m_running && !m_regularUpdateTimedOut) { + m_regularUpdateTimedOut = true; + emit updateTimeout(); + } +} + +void QGeoPositionInfoSourceGeoclueMaster::updatePosition(PositionFields fields, int timestamp, + double latitude, double longitude, + double altitude, Accuracy accuracy) +{ + if (m_requestTimer.isActive()) + m_requestTimer.stop(); + + QGeoCoordinate coordinate(latitude, longitude); + if (fields & Altitude) + coordinate.setAltitude(altitude); + + m_lastPosition = QGeoPositionInfo(coordinate, QDateTime::fromTime_t(timestamp)); + + m_lastPositionFromSatellite = accuracy.level() == Accuracy::Detailed; + + if (!qIsNaN(accuracy.horizontal())) + m_lastPosition.setAttribute(QGeoPositionInfo::HorizontalAccuracy, accuracy.horizontal()); + if (!qIsNaN(accuracy.vertical())) + m_lastPosition.setAttribute(QGeoPositionInfo::VerticalAccuracy, accuracy.vertical()); + + if (m_lastVelocityIsFresh) { + if (!qIsNaN(m_lastVelocity)) + m_lastPosition.setAttribute(QGeoPositionInfo::GroundSpeed, m_lastVelocity); + if (!qIsNaN(m_lastDirection)) + m_lastPosition.setAttribute(QGeoPositionInfo::Direction, m_lastDirection); + if (!qIsNaN(m_lastClimb)) + m_lastPosition.setAttribute(QGeoPositionInfo::VerticalSpeed, m_lastClimb); + m_lastVelocityIsFresh = false; + } + + m_regularUpdateTimedOut = false; + + emit positionUpdated(m_lastPosition); + + qCDebug(lcPositioningGeoclue) << m_lastPosition; + + // Only stop positioning if regular updates not active. + if (!m_running) { + cleanupPositionSource(); + m_master->releaseMasterClient(); + } +} + +void QGeoPositionInfoSourceGeoclueMaster::velocityUpdateFailed() +{ + qCDebug(lcPositioningGeoclue) << "velocity update failed."; + + // Set the velocitydata non-fresh. + m_lastVelocityIsFresh = false; +} + +void QGeoPositionInfoSourceGeoclueMaster::updateVelocity(VelocityFields fields, int timestamp, + double speed, double direction, + double climb) +{ + Q_UNUSED(timestamp) + + // Store the velocity and mark it as fresh. Simple but hopefully adequate. + m_lastVelocity = (fields & Speed) ? knotsToMetersPerSecond(speed) : qQNaN(); + m_lastDirection = (fields & Direction) ? direction : qQNaN(); + m_lastClimb = (fields & Climb) ? climb : qQNaN(); + m_lastVelocityIsFresh = true; + + qCDebug(lcPositioningGeoclue) << m_lastVelocity << m_lastDirection << m_lastClimb; +} + +void QGeoPositionInfoSourceGeoclueMaster::cleanupPositionSource() +{ + qCDebug(lcPositioningGeoclue) << "cleaning up position source"; + + if (m_provider) + m_provider->RemoveReference(); + delete m_provider; + m_provider = 0; + delete m_pos; + m_pos = 0; + delete m_vel; + m_vel = 0; +} + +void QGeoPositionInfoSourceGeoclueMaster::setOptions() +{ + if (!m_provider) + return; + + QVariantMap options; + options.insert(QStringLiteral("UpdateInterval"), updateInterval()); + + m_provider->SetOptions(options); +} + +void QGeoPositionInfoSourceGeoclueMaster::setUpdateInterval(int msec) +{ + QGeoPositionInfoSource::setUpdateInterval(qMax(minimumUpdateInterval(), msec)); + setOptions(); +} + +void QGeoPositionInfoSourceGeoclueMaster::setPreferredPositioningMethods(PositioningMethods methods) +{ + PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods(); + QGeoPositionInfoSource::setPreferredPositioningMethods(methods); + if (previousPreferredPositioningMethods == preferredPositioningMethods()) + return; + + qCDebug(lcPositioningGeoclue) << "requested to set methods to" << methods + << ", and set them to:" << preferredPositioningMethods(); + + m_lastVelocityIsFresh = false; + m_regularUpdateTimedOut = false; + + // Don't start Geoclue provider until necessary. Don't currently have a master client, no need + // no recreate one. + if (!m_master->hasMasterClient()) + return; + + // Free potential previous sources, because new requirements can't be set for the client + // (creating a position object after changing requirements seems to fail). + cleanupPositionSource(); + m_master->releaseMasterClient(); + + // Restart Geoclue provider with new requirements. + configurePositionSource(); + setOptions(); +} + +QGeoPositionInfo QGeoPositionInfoSourceGeoclueMaster::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +{ + if (fromSatellitePositioningMethodsOnly && !m_lastPositionFromSatellite) + return QGeoPositionInfo(); + + return m_lastPosition; +} + +QGeoPositionInfoSourceGeoclueMaster::PositioningMethods QGeoPositionInfoSourceGeoclueMaster::supportedPositioningMethods() const +{ + return AllPositioningMethods; +} + +void QGeoPositionInfoSourceGeoclueMaster::startUpdates() +{ + if (m_running) { + qCDebug(lcPositioningGeoclue) << "already running."; + return; + } + + m_running = true; + + qCDebug(lcPositioningGeoclue) << "starting updates"; + + // Start Geoclue provider. + if (!m_master->hasMasterClient()) { + configurePositionSource(); + setOptions(); + } + + // Emit last known position on start. + if (m_lastPosition.isValid()) { + QMetaObject::invokeMethod(this, "positionUpdated", Qt::QueuedConnection, + Q_ARG(QGeoPositionInfo, m_lastPosition)); + } +} + +int QGeoPositionInfoSourceGeoclueMaster::minimumUpdateInterval() const +{ + return MINIMUM_UPDATE_INTERVAL; +} + +void QGeoPositionInfoSourceGeoclueMaster::stopUpdates() +{ + if (!m_running) { + qCDebug(lcPositioningGeoclue) << "already stopped."; + return; + } + + qCDebug(lcPositioningGeoclue) << "stopping updates"; + + if (m_pos) { + disconnect(m_pos, SIGNAL(PositionChanged(qint32,qint32,double,double,double,Accuracy)), + this, SLOT(positionChanged(qint32,qint32,double,double,double,Accuracy))); + } + + if (m_vel) { + disconnect(m_vel, SIGNAL(VelocityChanged(qint32,qint32,double,double,double)), + this, SLOT(velocityChanged(qint32,qint32,double,double,double))); + } + + m_running = false; + + // Only stop positioning if single update not requested. + if (!m_requestTimer.isActive()) { + cleanupPositionSource(); + m_master->releaseMasterClient(); + } +} + +void QGeoPositionInfoSourceGeoclueMaster::requestUpdate(int timeout) +{ + if (timeout < minimumUpdateInterval() && timeout != 0) { + emit updateTimeout(); + return; + } + if (m_requestTimer.isActive()) { + qCDebug(lcPositioningGeoclue) << "request timer was active, ignoring startUpdates."; + return; + } + + if (!m_master->hasMasterClient()) { + configurePositionSource(); + setOptions(); + } + + // Create better logic for timeout value (specs leave it impl dependant). + // Especially if there are active updates ongoing, there is no point of waiting + // for whole cold start time. + m_requestTimer.start(timeout ? timeout : UPDATE_TIMEOUT_COLD_START); + + if (m_pos) { + QDBusPendingReply reply = m_pos->GetPosition(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(getPositionFinished(QDBusPendingCallWatcher*))); + } +} + +void QGeoPositionInfoSourceGeoclueMaster::positionProviderChanged(const QString &name, + const QString &description, + const QString &service, + const QString &path) +{ + Q_UNUSED(name) + Q_UNUSED(description) + + cleanupPositionSource(); + + if (service.isEmpty() || path.isEmpty()) { + if (!m_regularUpdateTimedOut) { + m_regularUpdateTimedOut = true; + emit updateTimeout(); + } + return; + } + + qCDebug(lcPositioningGeoclue) << "position provider changed to" << name; + + m_provider = new OrgFreedesktopGeoclueInterface(service, path, QDBusConnection::sessionBus()); + m_provider->AddReference(); + + m_pos = new OrgFreedesktopGeocluePositionInterface(service, path, QDBusConnection::sessionBus()); + + if (m_running) { + connect(m_pos, SIGNAL(PositionChanged(qint32,qint32,double,double,double,Accuracy)), + this, SLOT(positionChanged(qint32,qint32,double,double,double,Accuracy))); + } + + // Get the current position immediately. + QDBusPendingReply reply = m_pos->GetPosition(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(getPositionFinished(QDBusPendingCallWatcher*))); + + setOptions(); + + m_vel = new OrgFreedesktopGeoclueVelocityInterface(service, path, QDBusConnection::sessionBus()); + if (m_vel->isValid() && m_running) { + connect(m_vel, SIGNAL(VelocityChanged(qint32,qint32,double,double,double)), + this, SLOT(velocityChanged(qint32,qint32,double,double,double))); + } +} + +void QGeoPositionInfoSourceGeoclueMaster::requestUpdateTimeout() +{ + qCDebug(lcPositioningGeoclue) << "request update timeout occurred."; + + // If we end up here, there has not been valid position update. + emit updateTimeout(); + + // Only stop positioning if regular updates not active. + if (!m_running) { + cleanupPositionSource(); + m_master->releaseMasterClient(); + } +} + +void QGeoPositionInfoSourceGeoclueMaster::getPositionFinished(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply reply = *watcher; + watcher->deleteLater(); + + if (reply.isError()) + return; + + PositionFields fields = static_cast(reply.argumentAt<0>()); + + qCDebug(lcPositioningGeoclue) << "got position update with fields" << int(fields); + + if (fields & Latitude && fields & Longitude) { + qint32 timestamp = reply.argumentAt<1>(); + double latitude = reply.argumentAt<2>(); + double longitude = reply.argumentAt<3>(); + double altitude = reply.argumentAt<4>(); + Accuracy accuracy = reply.argumentAt<5>(); + updatePosition(fields, timestamp, latitude, longitude, altitude, accuracy); + } +} + +void QGeoPositionInfoSourceGeoclueMaster::positionChanged(qint32 fields, qint32 timestamp, double latitude, double longitude, double altitude, const Accuracy &accuracy) +{ + PositionFields pFields = static_cast(fields); + + qCDebug(lcPositioningGeoclue) << "position changed with fields" << fields; + + if (pFields & Latitude && pFields & Longitude) + updatePosition(pFields, timestamp, latitude, longitude, altitude, accuracy); + else + positionUpdateFailed(); +} + +void QGeoPositionInfoSourceGeoclueMaster::velocityChanged(qint32 fields, qint32 timestamp, double speed, double direction, double climb) +{ + VelocityFields vFields = static_cast(fields); + + if (vFields == NoVelocityFields) + velocityUpdateFailed(); + else + updateVelocity(vFields, timestamp, speed, direction, climb); +} + +void QGeoPositionInfoSourceGeoclueMaster::configurePositionSource() +{ + qCDebug(lcPositioningGeoclue); + + bool created = false; + + switch (preferredPositioningMethods()) { + case SatellitePositioningMethods: + created = m_master->createMasterClient(Accuracy::Detailed, QGeoclueMaster::ResourceGps); + break; + case NonSatellitePositioningMethods: + created = m_master->createMasterClient(Accuracy::None, QGeoclueMaster::ResourceCell | QGeoclueMaster::ResourceNetwork); + break; + case AllPositioningMethods: + created = m_master->createMasterClient(Accuracy::None, QGeoclueMaster::ResourceAll); + break; + default: + qWarning("QGeoPositionInfoSourceGeoclueMaster unknown preferred method."); + m_error = UnknownSourceError; + emit QGeoPositionInfoSource::error(m_error); + return; + } + + if (!created) { + m_error = UnknownSourceError; + emit QGeoPositionInfoSource::error(m_error); + } +} + +QGeoPositionInfoSource::Error QGeoPositionInfoSourceGeoclueMaster::error() const +{ + return m_error; +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h new file mode 100644 index 0000000..f2d817b --- /dev/null +++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCE_GEOCLUEMASTER_H +#define QGEOPOSITIONINFOSOURCE_GEOCLUEMASTER_H + +#include "qgeocluemaster.h" +#include "geocluetypes.h" + +#include +#include + +class OrgFreedesktopGeoclueInterface; +class OrgFreedesktopGeocluePositionInterface; +class OrgFreedesktopGeoclueVelocityInterface; + +QT_BEGIN_NAMESPACE + +class QDBusPendingCallWatcher; + +class QGeoPositionInfoSourceGeoclueMaster : public QGeoPositionInfoSource +{ + Q_OBJECT + +public: + explicit QGeoPositionInfoSourceGeoclueMaster(QObject *parent = 0); + ~QGeoPositionInfoSourceGeoclueMaster(); + + // From QGeoPositionInfoSource + void setUpdateInterval(int msec); + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + PositioningMethods supportedPositioningMethods() const; + void setPreferredPositioningMethods(PositioningMethods methods); + int minimumUpdateInterval() const; + + Error error() const; + + virtual void startUpdates() Q_DECL_OVERRIDE; + virtual void stopUpdates() Q_DECL_OVERRIDE; + virtual void requestUpdate(int timeout = 5000) Q_DECL_OVERRIDE; + +private slots: + void positionProviderChanged(const QString &name, const QString &description, + const QString &service, const QString &path); + void requestUpdateTimeout(); + + void getPositionFinished(QDBusPendingCallWatcher *watcher); + void positionChanged(qint32 fields, qint32 timestamp, double latitude, double longitude, + double altitude, const Accuracy &accuracy); + void velocityChanged(qint32 fields, qint32 timestamp, double speed, double direction, + double climb); + +private: + void configurePositionSource(); + void cleanupPositionSource(); + void setOptions(); + + enum PositionField + { + NoPositionFields = 0, + Latitude = 1 << 0, + Longitude = 1 << 1, + Altitude = 1 << 2 + }; + Q_DECLARE_FLAGS(PositionFields, PositionField) + + void updatePosition(PositionFields fields, int timestamp, double latitude, + double longitude, double altitude, Accuracy accuracy); + void positionUpdateFailed(); + + enum VelocityField + { + NoVelocityFields = 0, + Speed = 1 << 0, + Direction = 1 << 1, + Climb = 1 << 2 + }; + Q_DECLARE_FLAGS(VelocityFields, VelocityField) + + void updateVelocity(VelocityFields fields, int timestamp, double speed, double direction, + double climb); + void velocityUpdateFailed(); + +private: + QGeoclueMaster *m_master; + + OrgFreedesktopGeoclueInterface *m_provider; + OrgFreedesktopGeocluePositionInterface *m_pos; + OrgFreedesktopGeoclueVelocityInterface *m_vel; + + QTimer m_requestTimer; + bool m_lastVelocityIsFresh; + bool m_regularUpdateTimedOut; + double m_lastVelocity; + double m_lastDirection; + double m_lastClimb; + bool m_lastPositionFromSatellite; + QGeoPositionInfo m_lastPosition; + bool m_running; + QGeoPositionInfoSource::Error m_error; +}; + +QT_END_NAMESPACE + +#endif // QGEOPOSITIONINFOSOURCE_GEOCLUEMASTER_H diff --git a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp new file mode 100644 index 0000000..9b39bfb --- /dev/null +++ b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosourcefactory_geoclue.h" +#include "qgeopositioninfosource_geocluemaster.h" +#include "qgeosatelliteinfosource_geocluemaster.h" + +#include + +Q_DECLARE_METATYPE(QGeoPositionInfo) + +Q_LOGGING_CATEGORY(lcPositioningGeoclue, "qt.positioning.geoclue") + +QT_BEGIN_NAMESPACE + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryGeoclue::positionInfoSource(QObject *parent) +{ + qRegisterMetaType(); + return new QGeoPositionInfoSourceGeoclueMaster(parent); +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryGeoclue::satelliteInfoSource(QObject *parent) +{ + return new QGeoSatelliteInfoSourceGeoclueMaster(parent); +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryGeoclue::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent) + return 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h new file mode 100644 index 0000000..6125cb4 --- /dev/null +++ b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE_H +#define QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE_H + +#include +#include + +QT_BEGIN_NAMESPACE + +/* + Qt Positioning plugin for Geoclue. This plugin supports Geoclue version 0.12.99. +*/ +class QGeoPositionInfoSourceFactoryGeoclue : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + + Q_INTERFACES(QGeoPositionInfoSourceFactory) + +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent) Q_DECL_OVERRIDE; + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent) Q_DECL_OVERRIDE; + QGeoAreaMonitorSource *areaMonitor(QObject *parent) Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp new file mode 100644 index 0000000..3d70ea3 --- /dev/null +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp @@ -0,0 +1,310 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd, author: Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeosatelliteinfosource_geocluemaster.h" + +#include +#include + +#include +#include + +Q_DECLARE_LOGGING_CATEGORY(lcPositioningGeoclue) + +#define MINIMUM_UPDATE_INTERVAL 1000 + +QT_BEGIN_NAMESPACE + +QGeoSatelliteInfoSourceGeoclueMaster::QGeoSatelliteInfoSourceGeoclueMaster(QObject *parent) +: QGeoSatelliteInfoSource(parent), m_master(new QGeoclueMaster(this)), m_provider(0), m_sat(0), + m_error(NoError), m_satellitesChangedConnected(false), m_running(false) +{ + connect(m_master, SIGNAL(positionProviderChanged(QString,QString,QString,QString)), + this, SLOT(positionProviderChanged(QString,QString,QString,QString))); + + m_requestTimer.setSingleShot(true); + connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout())); +} + +QGeoSatelliteInfoSourceGeoclueMaster::~QGeoSatelliteInfoSourceGeoclueMaster() +{ + cleanupSatelliteSource(); +} + +int QGeoSatelliteInfoSourceGeoclueMaster::minimumUpdateInterval() const +{ + return MINIMUM_UPDATE_INTERVAL; +} + +void QGeoSatelliteInfoSourceGeoclueMaster::setUpdateInterval(int msec) +{ + if (msec < 0 || (msec > 0 && msec < MINIMUM_UPDATE_INTERVAL)) + msec = MINIMUM_UPDATE_INTERVAL; + + QGeoSatelliteInfoSource::setUpdateInterval(msec); +} + +QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceGeoclueMaster::error() const +{ + return m_error; +} + +void QGeoSatelliteInfoSourceGeoclueMaster::startUpdates() +{ + if (m_running) + return; + + m_running = true; + + // Start Geoclue provider. + if (!m_master->hasMasterClient()) + configureSatelliteSource(); + + m_requestTimer.start(updateInterval()); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::stopUpdates() +{ + if (!m_running) + return; + + if (m_sat) { + disconnect(m_sat, SIGNAL(SatelliteChanged(qint32,qint32,qint32,QList,QList)), + this, SLOT(satelliteChanged(qint32,qint32,qint32,QList,QList))); + } + + m_running = false; + + // Only stop positioning if single update not requested. + if (!m_requestTimer.isActive()) { + cleanupSatelliteSource(); + m_master->releaseMasterClient(); + } +} + +void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdate(int timeout) +{ + if (timeout < minimumUpdateInterval() && timeout != 0) { + emit requestTimeout(); + return; + } + + if (m_requestTimer.isActive()) + return; + + if (!m_master->hasMasterClient()) + configureSatelliteSource(); + + m_requestTimer.start(qMax(timeout, minimumUpdateInterval())); + + if (m_sat) { + QDBusPendingReply, QList > reply = + m_sat->GetSatellite(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(getSatelliteFinished(QDBusPendingCallWatcher*))); + } +} + +void QGeoSatelliteInfoSourceGeoclueMaster::updateSatelliteInfo(int timestamp, int satellitesUsed, + int satellitesVisible, + const QList &usedPrn, + const QList &satInfos) +{ + Q_UNUSED(timestamp) + + QList inUse; + + foreach (const QGeoSatelliteInfo &si, satInfos) + if (usedPrn.contains(si.satelliteIdentifier())) + inUse.append(si); + + if (satInfos.length() != satellitesVisible) { + qWarning("QGeoSatelliteInfoSourceGeoclueMaster number of in view QGeoSatelliteInfos (%d) " + "does not match expected number of in view satellites (%d).", satInfos.length(), + satellitesVisible); + } + + if (inUse.length() != satellitesUsed) { + qWarning("QGeoSatelliteInfoSourceGeoclueMaster number of in use QGeoSatelliteInfos (%d) " + "does not match expected number of in use satellites (%d).", inUse.length(), + satellitesUsed); + } + + m_inView = satInfos; + emit satellitesInViewUpdated(m_inView); + + m_inUse = inUse; + emit satellitesInUseUpdated(m_inUse); + + m_requestTimer.start(updateInterval()); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdateTimeout() +{ + // If we end up here, there has not been a valid satellite info update. + if (m_running) { + m_inView.clear(); + m_inUse.clear(); + emit satellitesInViewUpdated(m_inView); + emit satellitesInUseUpdated(m_inUse); + } else { + emit requestTimeout(); + + // Only stop satellite info if regular updates not active. + cleanupSatelliteSource(); + m_master->releaseMasterClient(); + } +} + +void QGeoSatelliteInfoSourceGeoclueMaster::getSatelliteFinished(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply, QList > reply = *watcher; + watcher->deleteLater(); + + if (reply.isError()) + return; + + m_requestTimer.stop(); + updateSatelliteInfo(reply.argumentAt<0>(), reply.argumentAt<1>(), reply.argumentAt<2>(), + reply.argumentAt<3>(), reply.argumentAt<4>()); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::satelliteChanged(int timestamp, int satellitesUsed, int satellitesVisible, const QList &usedPrn, const QList &satInfos) +{ + updateSatelliteInfo(timestamp, satellitesUsed, satellitesVisible, usedPrn, satInfos); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::positionProviderChanged(const QString &name, + const QString &description, + const QString &service, + const QString &path) +{ + Q_UNUSED(name) + Q_UNUSED(description) + + cleanupSatelliteSource(); + + QString providerService; + QString providerPath; + + if (service.isEmpty() || path.isEmpty()) { + // No valid position provider has been selected. This probably means that the GPS provider + // has not yet obtained a position fix. It can still provide satellite information though. + if (!m_satellitesChangedConnected) { + QDBusConnection conn = QDBusConnection::sessionBus(); + conn.connect(QString(), QString(), QStringLiteral("org.freedesktop.Geoclue.Satellite"), + QStringLiteral("SatelliteChanged"), this, + SLOT(satelliteChanged(QDBusMessage))); + m_satellitesChangedConnected = true; + return; + } + } else { + if (m_satellitesChangedConnected) { + QDBusConnection conn = QDBusConnection::sessionBus(); + conn.disconnect(QString(), QString(), + QStringLiteral("org.freedesktop.Geoclue.Satellite"), + QStringLiteral("SatelliteChanged"), this, + SLOT(satelliteChanged(QDBusMessage))); + m_satellitesChangedConnected = false; + } + + providerService = service; + providerPath = path; + } + + if (providerService.isEmpty() || providerPath.isEmpty()) { + m_error = AccessError; + emit QGeoSatelliteInfoSource::error(m_error); + return; + } + + m_provider = new OrgFreedesktopGeoclueInterface(providerService, providerPath, QDBusConnection::sessionBus()); + m_provider->AddReference(); + + m_sat = new OrgFreedesktopGeoclueSatelliteInterface(providerService, providerPath, QDBusConnection::sessionBus()); + + if (m_running) { + connect(m_sat, SIGNAL(SatelliteChanged(qint32,qint32,qint32,QList,QList)), + this, SLOT(satelliteChanged(qint32,qint32,qint32,QList,QList))); + } +} + +void QGeoSatelliteInfoSourceGeoclueMaster::satelliteChanged(const QDBusMessage &message) +{ + QVariantList arguments = message.arguments(); + if (arguments.length() != 5) + return; + + int timestamp = arguments.at(0).toInt(); + int usedSatellites = arguments.at(1).toInt(); + int visibleSatellites = arguments.at(2).toInt(); + + QDBusArgument dbusArgument = arguments.at(3).value(); + + QList usedPrn; + dbusArgument >> usedPrn; + + dbusArgument = arguments.at(4).value(); + + QList satelliteInfos; + dbusArgument >> satelliteInfos; + + satelliteChanged(timestamp, usedSatellites, visibleSatellites, usedPrn, satelliteInfos); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::configureSatelliteSource() +{ + if (!m_master->createMasterClient(Accuracy::Detailed, QGeoclueMaster::ResourceGps)) { + m_error = UnknownSourceError; + emit QGeoSatelliteInfoSource::error(m_error); + } +} + +void QGeoSatelliteInfoSourceGeoclueMaster::cleanupSatelliteSource() +{ + if (m_provider) + m_provider->RemoveReference(); + delete m_provider; + m_provider = 0; + delete m_sat; + m_sat = 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h new file mode 100644 index 0000000..45a0ed7 --- /dev/null +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd, author: Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSATELLITEINFOSOURCE_GEOCLUEMASTER_H +#define QGEOSATELLITEINFOSOURCE_GEOCLUEMASTER_H + +#include "qgeocluemaster.h" + +#include +#include + +class OrgFreedesktopGeoclueInterface; +class OrgFreedesktopGeoclueSatelliteInterface; + +QT_BEGIN_NAMESPACE + +class QDBusMessage; +class QDBusPendingCallWatcher; + +class QGeoSatelliteInfoSourceGeoclueMaster : public QGeoSatelliteInfoSource +{ + Q_OBJECT + +public: + explicit QGeoSatelliteInfoSourceGeoclueMaster(QObject *parent = 0); + ~QGeoSatelliteInfoSourceGeoclueMaster(); + + int minimumUpdateInterval() const Q_DECL_OVERRIDE; + void setUpdateInterval(int msec) Q_DECL_OVERRIDE; + + Error error() const Q_DECL_OVERRIDE; + + void startUpdates() Q_DECL_OVERRIDE; + void stopUpdates() Q_DECL_OVERRIDE; + void requestUpdate(int timeout = 0) Q_DECL_OVERRIDE; + +private slots: + void positionProviderChanged(const QString &name, const QString &description, + const QString &service, const QString &path); + void requestUpdateTimeout(); + + void getSatelliteFinished(QDBusPendingCallWatcher *watcher); + void satelliteChanged(int timestamp, int satellitesUsed, int satellitesVisible, + const QList &usedPrn, const QList &satInfos); + void satelliteChanged(const QDBusMessage &message); + +private: + void configureSatelliteSource(); + void cleanupSatelliteSource(); + + void updateSatelliteInfo(int timestamp, int satellitesUsed, int satellitesVisible, + const QList &usedPrn, const QList &satInfos); + + QGeoclueMaster *m_master; + + OrgFreedesktopGeoclueInterface *m_provider; + OrgFreedesktopGeoclueSatelliteInterface *m_sat; + + QTimer m_requestTimer; + QList m_inView; + QList m_inUse; + Error m_error; + bool m_satellitesChangedConnected; + bool m_running; +}; + +QT_END_NAMESPACE + +#endif // QGEOSATELLITEINFOSOURCE_GEOCLUEMASTER_H diff --git a/src/plugins/position/gypsy/gypsy.pro b/src/plugins/position/gypsy/gypsy.pro new file mode 100644 index 0000000..be65f18 --- /dev/null +++ b/src/plugins/position/gypsy/gypsy.pro @@ -0,0 +1,21 @@ +TARGET = qtposition_gypsy + +QT = core positioning + +HEADERS += \ + qgeosatelliteinfosource_gypsy_p.h \ + qgeopositioninfosourcefactory_gypsy.h + +SOURCES += \ + qgeosatelliteinfosource_gypsy.cpp \ + qgeopositioninfosourcefactory_gypsy.cpp + +CONFIG += link_pkgconfig +PKGCONFIG += gypsy gconf-2.0 + +OTHER_FILES += \ + plugin.json + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryGypsy +load(qt_plugin) diff --git a/src/plugins/position/gypsy/plugin.json b/src/plugins/position/gypsy/plugin.json new file mode 100644 index 0000000..9cef03f --- /dev/null +++ b/src/plugins/position/gypsy/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["gypsy"], + "Provider": "gypsy", + "Position": false, + "Satellite": true, + "Monitor" : false, + "Priority": 1000, + "Testable": false +} diff --git a/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.cpp b/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.cpp new file mode 100644 index 0000000..ecb1b2e --- /dev/null +++ b/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosourcefactory_gypsy.h" +#include "qgeosatelliteinfosource_gypsy_p.h" + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryGypsy::positionInfoSource(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryGypsy::satelliteInfoSource(QObject *parent) +{ + QGeoSatelliteInfoSourceGypsy *src = new QGeoSatelliteInfoSourceGypsy(parent); + if (src->init() < 0) { + delete src; + src = 0; + } + return src; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryGypsy::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} diff --git a/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.h b/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.h new file mode 100644 index 0000000..fa18822 --- /dev/null +++ b/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCEFACTORY_GYPSY_H +#define QGEOPOSITIONINFOSOURCEFACTORY_GYPSY_H + +#include +#include + +class QGeoPositionInfoSourceFactoryGypsy : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) + +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +#endif diff --git a/src/plugins/position/gypsy/qgeosatelliteinfosource_gypsy.cpp b/src/plugins/position/gypsy/qgeosatelliteinfosource_gypsy.cpp new file mode 100644 index 0000000..4e78265 --- /dev/null +++ b/src/plugins/position/gypsy/qgeosatelliteinfosource_gypsy.cpp @@ -0,0 +1,374 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeosatelliteinfosource_gypsy_p.h" + +#ifdef Q_LOCATION_GYPSY_DEBUG +#include +#endif +#include + +QT_BEGIN_NAMESPACE + +#define UPDATE_TIMEOUT_COLD_START 120000 + + +// Callback function for 'satellites-changed' -signal +static void satellites_changed (GypsySatellite *satellite, + GPtrArray *satellites, + gpointer userdata) +{ +#ifdef Q_LOCATION_GYPSY_DEBUG + qDebug() << "QGeoSatelliteInfoSourceGypsy Gypsy satellites-changed -signal received."; +#endif + ((QGeoSatelliteInfoSourceGypsy *)userdata)->satellitesChanged(satellite, satellites); +} + +SatelliteGypsyEngine::SatelliteGypsyEngine(QGeoSatelliteInfoSource *parent) : + m_owner(parent) +{ +} +SatelliteGypsyEngine::~SatelliteGypsyEngine() +{ +} + +// Glib symbols +gulong SatelliteGypsyEngine::eng_g_signal_connect(gpointer instance, + const gchar *detailed_signal, + GCallback c_handler, + gpointer data) +{ + return ::g_signal_connect(instance, detailed_signal, c_handler, data); +} +guint SatelliteGypsyEngine::eng_g_signal_handlers_disconnect_by_func (gpointer instance, + gpointer func, + gpointer data) +{ + return ::g_signal_handlers_disconnect_by_func(instance, func, data); +} + +void SatelliteGypsyEngine::eng_g_free(gpointer mem) +{ + return ::g_free(mem); +} +// Gypsy symbols +GypsyControl *SatelliteGypsyEngine::eng_gypsy_control_get_default (void) +{ + return ::gypsy_control_get_default(); +} +char *SatelliteGypsyEngine::eng_gypsy_control_create (GypsyControl *control, const char *device_name, GError **error) +{ + return ::gypsy_control_create(control, device_name, error); +} +GypsyDevice *SatelliteGypsyEngine::eng_gypsy_device_new (const char *object_path) +{ + return ::gypsy_device_new(object_path); +} +GypsySatellite *SatelliteGypsyEngine::eng_gypsy_satellite_new (const char *object_path) +{ + return ::gypsy_satellite_new (object_path); +} +gboolean SatelliteGypsyEngine::eng_gypsy_device_start (GypsyDevice *device, GError **error) +{ + return ::gypsy_device_start(device, error); +} +gboolean SatelliteGypsyEngine::eng_gypsy_device_stop (GypsyDevice *device, GError **error) +{ + // Unfortunately this cannot be done; calling this will stop the GPS device + // (basically makes gypsy-daemon unusable for anyone), regardless of applications + // using it (see bug http://bugs.meego.com/show_bug.cgi?id=11707). + Q_UNUSED(device); + Q_UNUSED(error); + return true; + //return ::gypsy_device_stop (device, error); +} +GypsyDeviceFixStatus SatelliteGypsyEngine::eng_gypsy_device_get_fix_status (GypsyDevice *device, GError **error) +{ + return ::gypsy_device_get_fix_status (device, error); +} +GPtrArray *SatelliteGypsyEngine::eng_gypsy_satellite_get_satellites (GypsySatellite *satellite, GError **error) +{ + return ::gypsy_satellite_get_satellites (satellite, error); +} +void SatelliteGypsyEngine::eng_gypsy_satellite_free_satellite_array (GPtrArray *satellites) +{ + return ::gypsy_satellite_free_satellite_array(satellites); +} +// GConf symbols (mockability due to X11 requirement) +GConfClient *SatelliteGypsyEngine::eng_gconf_client_get_default(void) +{ + return ::gconf_client_get_default(); +} +gchar *SatelliteGypsyEngine::eng_gconf_client_get_string(GConfClient *client, const gchar *key, GError** err) +{ + return ::gconf_client_get_string(client, key, err); +} + +QGeoSatelliteInfoSourceGypsy::QGeoSatelliteInfoSourceGypsy(QObject *parent) : QGeoSatelliteInfoSource(parent), + m_engine(0), m_satellite(0), m_device(0), m_updatesOngoing(false), m_requestOngoing(false) +{ + m_requestTimer.setSingleShot(true); + QObject::connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout())); +} + +void QGeoSatelliteInfoSourceGypsy::createEngine() +{ + delete m_engine; + m_engine = new SatelliteGypsyEngine(this); +} + +QGeoSatelliteInfoSourceGypsy::~QGeoSatelliteInfoSourceGypsy() +{ + GError *error = NULL; + if (m_device) { + m_engine->eng_gypsy_device_stop (m_device, &error); + g_object_unref(m_device); + } + if (m_satellite) + g_object_unref(m_satellite); + if (error) + g_error_free(error); + delete m_engine; +} + +void QGeoSatelliteInfoSourceGypsy::satellitesChanged(GypsySatellite *satellite, + GPtrArray *satellites) +{ + if (!satellite || !satellites) + return; + // We have satellite data and assume it is valid. + // If a single updateRequest was active, send signals right away. + // If a periodic timer was running (meaning that the client wishes + // to have updates at defined intervals), store the data for later sending. + QList lastSatellitesInView; + QList lastSatellitesInUse; + + unsigned int i; + for (i = 0; i < satellites->len; i++) { + GypsySatelliteDetails *details = (GypsySatelliteDetails *)satellites->pdata[i]; + QGeoSatelliteInfo info; + info.setAttribute(QGeoSatelliteInfo::Elevation, details->elevation); + info.setAttribute(QGeoSatelliteInfo::Azimuth, details->azimuth); + info.setSignalStrength(details->snr); + if (details->in_use) + lastSatellitesInUse.append(info); + lastSatellitesInView.append(info); + } + bool sendUpdates(false); + // If a single updateRequest() has been issued: + if (m_requestOngoing) { + sendUpdates = true; + m_requestTimer.stop(); + m_requestOngoing = false; + // If there is no regular updates ongoing, disconnect now. + if (!m_updatesOngoing) { + m_engine->eng_g_signal_handlers_disconnect_by_func(G_OBJECT(m_satellite), (void *)satellites_changed, this); + } + } + // If regular updates are to be delivered as they come: + if (m_updatesOngoing) + sendUpdates = true; + + if (sendUpdates) { + emit satellitesInUseUpdated(lastSatellitesInUse); + emit satellitesInViewUpdated(lastSatellitesInView); + } +} + +int QGeoSatelliteInfoSourceGypsy::init() +{ + GError *error = NULL; + char *path; + GConfClient *client; + gchar *device_name; + + g_type_init (); + createEngine(); + + client = m_engine->eng_gconf_client_get_default(); + if (!client) { + qWarning ("QGeoSatelliteInfoSourceGypsy client creation failed."); + return -1; + } + device_name = m_engine->eng_gconf_client_get_string(client, "/apps/geoclue/master/org.freedesktop.Geoclue.GPSDevice", NULL); + g_object_unref(client); + QString deviceName(QString::fromLatin1(device_name)); + if (deviceName.isEmpty() || + (deviceName.trimmed().at(0) == '/' && !QFile::exists(deviceName.trimmed()))) { + qWarning ("QGeoSatelliteInfoSourceGypsy Empty/nonexistent GPS device name detected."); + qWarning ("Use gconftool-2 to set it, e.g. on terminal: "); + qWarning ("gconftool-2 -t string -s /apps/geoclue/master/org.freedesktop.Geoclue.GPSDevice /dev/ttyUSB0"); + m_engine->eng_g_free(device_name); + return -1; + } + GypsyControl *control = NULL; + control = m_engine->eng_gypsy_control_get_default(); + if (!control) { + qWarning("QGeoSatelliteInfoSourceGypsy unable to create Gypsy control."); + m_engine->eng_g_free(device_name); + return -1; + } + // (path is the DBus path) + path = m_engine->eng_gypsy_control_create (control, device_name, &error); + m_engine->eng_g_free(device_name); + g_object_unref(control); + if (!path) { + qWarning ("QGeoSatelliteInfoSourceGypsy error creating client."); + if (error) { + qWarning ("error message: %s", error->message); + g_error_free (error); + } + return -1; + } + m_device = m_engine->eng_gypsy_device_new (path); + m_satellite = m_engine->eng_gypsy_satellite_new (path); + m_engine->eng_g_free(path); + if (!m_device || !m_satellite) { + qWarning ("QGeoSatelliteInfoSourceGypsy error creating satellite device."); + qWarning ("Is GPS device set correctly? If not, use gconftool-2 to set it, e.g.: "); + qWarning ("gconftool-2 -t string -s /apps/geoclue/master/org.freedesktop.Geoclue.GPSDevice /dev/ttyUSB0"); + if (m_device) + g_object_unref(m_device); + if (m_satellite) + g_object_unref(m_satellite); + return -1; + } + m_engine->eng_gypsy_device_start (m_device, &error); + if (error) { + qWarning ("QGeoSatelliteInfoSourceGypsy error starting device: %s ", + error->message); + g_error_free(error); + g_object_unref(m_device); + g_object_unref(m_satellite); + return -1; + } + return 0; +} + +int QGeoSatelliteInfoSourceGypsy::minimumUpdateInterval() const +{ + return 1; +} + +QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceGypsy::error() const +{ + return NoError; +} + +void QGeoSatelliteInfoSourceGypsy::startUpdates() +{ + if (m_updatesOngoing) + return; + // If there is a request timer ongoing, we've connected to the signal already + if (!m_requestTimer.isActive()) { + m_engine->eng_g_signal_connect (m_satellite, "satellites-changed", + G_CALLBACK (satellites_changed), this); + } + m_updatesOngoing = true; +} + +void QGeoSatelliteInfoSourceGypsy::stopUpdates() +{ + if (!m_updatesOngoing) + return; + m_updatesOngoing = false; + // Disconnect only if there is no single update request ongoing. Once single update request + // is completed and it notices that there is no active update ongoing, it will disconnect + // the signal. + if (!m_requestTimer.isActive()) + m_engine->eng_g_signal_handlers_disconnect_by_func(G_OBJECT(m_satellite), (void *)satellites_changed, this); +} + +void QGeoSatelliteInfoSourceGypsy::requestUpdate(int timeout) +{ + if (m_requestOngoing) + return; + if (timeout < 0) { + emit requestTimeout(); + return; + } + m_requestOngoing = true; + GError *error = 0; + // If GPS has a fix a already, request current data. + GypsyDeviceFixStatus fixStatus = m_engine->eng_gypsy_device_get_fix_status(m_device, &error); + if (!error && (fixStatus != GYPSY_DEVICE_FIX_STATUS_INVALID && + fixStatus != GYPSY_DEVICE_FIX_STATUS_NONE)) { +#ifdef Q_LOCATION_GYPSY_DEBUG + qDebug() << "QGeoSatelliteInfoSourceGypsy fix available, requesting current satellite data"; +#endif + GPtrArray *satelliteData = m_engine->eng_gypsy_satellite_get_satellites(m_satellite, &error); + if (!error) { + // The fix was available and we have satellite data to deliver right away. + satellitesChanged(m_satellite, satelliteData); + m_engine->eng_gypsy_satellite_free_satellite_array(satelliteData); + return; + } + } + // No fix is available. If updates are not ongoing already, start them. + m_requestTimer.setInterval(timeout == 0? UPDATE_TIMEOUT_COLD_START: timeout); + if (!m_updatesOngoing) { + m_engine->eng_g_signal_connect (m_satellite, "satellites-changed", + G_CALLBACK (satellites_changed), this); + } + m_requestTimer.start(); + if (error) { +#ifdef Q_LOCATION_GYPSY_DEBUG + qDebug() << "QGeoSatelliteInfoSourceGypsy error asking fix status or satellite data: " << error->message; +#endif + g_error_free(error); + } +} + +void QGeoSatelliteInfoSourceGypsy::requestUpdateTimeout() +{ +#ifdef Q_LOCATION_GYPSY_DEBUG + qDebug("QGeoSatelliteInfoSourceGypsy request update timeout occurred."); +#endif + // If we end up here, there has not been valid satellite update. + // Emit timeout and disconnect from signal if regular updates are not + // ongoing (as we were listening just for one single requestUpdate). + if (!m_updatesOngoing) { + m_engine->eng_g_signal_handlers_disconnect_by_func(G_OBJECT(m_satellite), (void *)satellites_changed, this); + } + m_requestOngoing = false; + emit requestTimeout(); +} + +#include "moc_qgeosatelliteinfosource_gypsy_p.cpp" +QT_END_NAMESPACE diff --git a/src/plugins/position/gypsy/qgeosatelliteinfosource_gypsy_p.h b/src/plugins/position/gypsy/qgeosatelliteinfosource_gypsy_p.h new file mode 100644 index 0000000..ea6b6bc --- /dev/null +++ b/src/plugins/position/gypsy/qgeosatelliteinfosource_gypsy_p.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSATELLITEINFOSOURCE_GYPSY_H +#define QGEOSATELLITEINFOSOURCE_GYPSY_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeosatelliteinfosource.h" +#include "qgeosatelliteinfo.h" +#include +#include +#include +#include +#include + +// #define Q_LOCATION_GYPSY_DEBUG + +QT_BEGIN_NAMESPACE + +// An engine that encapsulates all symbols we want +// to be able to mock (for unit/autotest purposes). +class SatelliteGypsyEngine +{ +public: + SatelliteGypsyEngine(QGeoSatelliteInfoSource *parent = 0); + virtual ~SatelliteGypsyEngine(); + // Glib symbols + virtual gulong eng_g_signal_connect(gpointer instance, + const gchar *detailed_signal, + GCallback c_handler, + gpointer data); + virtual guint eng_g_signal_handlers_disconnect_by_func(gpointer instance, + gpointer func, + gpointer data); + virtual void eng_g_free(gpointer mem); + // Gypsy symbols + virtual GypsyControl *eng_gypsy_control_get_default (void); + virtual char *eng_gypsy_control_create (GypsyControl *control, const char *device_name, GError **error); + virtual GypsyDevice *eng_gypsy_device_new (const char *object_path); + virtual GypsySatellite *eng_gypsy_satellite_new (const char *object_path); + virtual gboolean eng_gypsy_device_start (GypsyDevice *device, GError **error); + virtual gboolean eng_gypsy_device_stop (GypsyDevice *device, GError **error); + virtual GypsyDeviceFixStatus eng_gypsy_device_get_fix_status (GypsyDevice *device, GError **error); + virtual GPtrArray *eng_gypsy_satellite_get_satellites (GypsySatellite *satellite, GError **error); + virtual void eng_gypsy_satellite_free_satellite_array (GPtrArray *satellites); + // GConf symbols (mockability due to X11 requirement) + virtual GConfClient *eng_gconf_client_get_default(void); + virtual gchar *eng_gconf_client_get_string(GConfClient *client, const gchar *key, GError** err); +protected: + QGeoSatelliteInfoSource *m_owner; +}; + +class QGeoSatelliteInfoSourceGypsy : public QGeoSatelliteInfoSource + { + Q_OBJECT + +public: + explicit QGeoSatelliteInfoSourceGypsy(QObject *parent = 0); + ~QGeoSatelliteInfoSourceGypsy(); + int init(); + + int minimumUpdateInterval() const; + Error error() const; + +public slots: + virtual void startUpdates(); + void stopUpdates(); + void requestUpdate(int timeout = 5000); + void satellitesChanged(GypsySatellite *satellite, GPtrArray *satellites); + +signals: + void satellitesInViewUpdated(const QList &satellites); + void satellitesInUseUpdated(const QList &satellites); + +private slots: + void requestUpdateTimeout(); + +protected: + // Creates an engine which encapsulates all used symbols + // that we want to be also able to mock. + virtual void createEngine(); + SatelliteGypsyEngine *m_engine; + +private: + Q_DISABLE_COPY(QGeoSatelliteInfoSourceGypsy) + GypsySatellite *m_satellite; + GypsyDevice *m_device; + QTimer m_requestTimer; + bool m_updatesOngoing; + bool m_requestOngoing; + }; + +QT_END_NAMESPACE + +#endif // QGEOSATELLITEINFOSOURCE_GYPSY_H diff --git a/src/plugins/position/position.pro b/src/plugins/position/position.pro new file mode 100644 index 0000000..df1930b --- /dev/null +++ b/src/plugins/position/position.pro @@ -0,0 +1,12 @@ +TEMPLATE = subdirs + +qtHaveModule(dbus):SUBDIRS += geoclue +config_gypsy:SUBDIRS += gypsy +qtHaveModule(simulator):SUBDIRS += simulator +osx|ios|tvos:SUBDIRS += corelocation +android:SUBDIRS += android +winrt:SUBDIRS += winrt +win32:qtHaveModule(serialport):SUBDIRS += serialnmea + +SUBDIRS += \ + positionpoll diff --git a/src/plugins/position/positionpoll/plugin.json b/src/plugins/position/positionpoll/plugin.json new file mode 100644 index 0000000..df1f47d --- /dev/null +++ b/src/plugins/position/positionpoll/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["positionpoll"], + "Provider": "positionpoll", + "Position": false, + "Satellite": false, + "Monitor": true, + "Priority": 1000, + "Testable": true +} diff --git a/src/plugins/position/positionpoll/positionpoll.pro b/src/plugins/position/positionpoll/positionpoll.pro new file mode 100644 index 0000000..be60bf4 --- /dev/null +++ b/src/plugins/position/positionpoll/positionpoll.pro @@ -0,0 +1,18 @@ +TARGET = qtposition_positionpoll + +QT = core positioning + +SOURCES += \ + qgeoareamonitor_polling.cpp \ + positionpollfactory.cpp + +HEADERS += \ + qgeoareamonitor_polling.h \ + positionpollfactory.h + +OTHER_FILES += \ + plugin.json + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryPoll +load(qt_plugin) diff --git a/src/plugins/position/positionpoll/positionpollfactory.cpp b/src/plugins/position/positionpoll/positionpollfactory.cpp new file mode 100644 index 0000000..20e2774 --- /dev/null +++ b/src/plugins/position/positionpoll/positionpollfactory.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "positionpollfactory.h" +#include "qgeoareamonitor_polling.h" + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryPoll::positionInfoSource(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryPoll::satelliteInfoSource(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryPoll::areaMonitor(QObject *parent) +{ + QGeoAreaMonitorPolling *ret = new QGeoAreaMonitorPolling(parent); + if (ret && ret->isValid()) + return ret; + delete ret; + return 0; +} diff --git a/src/plugins/position/positionpoll/positionpollfactory.h b/src/plugins/position/positionpoll/positionpollfactory.h new file mode 100644 index 0000000..6841fd0 --- /dev/null +++ b/src/plugins/position/positionpoll/positionpollfactory.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef POSITIONPOLLFACTORY_H +#define POSITIONPOLLFACTORY_H + +#include +#include + +class QGeoPositionInfoSourceFactoryPoll : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +#endif // POSITIONPOLLFACTORY_H diff --git a/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp b/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp new file mode 100644 index 0000000..e39a621 --- /dev/null +++ b/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp @@ -0,0 +1,497 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoareamonitor_polling.h" +#include +#include +#include + +#include +#include +#include +#include + +#define UPDATE_INTERVAL_5S 5000 + +typedef QHash MonitorTable; + + +static QMetaMethod areaEnteredSignal() +{ + static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaEntered); + return signal; +} + +static QMetaMethod areaExitedSignal() +{ + static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaExited); + return signal; +} + +static QMetaMethod monitorExpiredSignal() +{ + static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::monitorExpired); + return signal; +} + +class QGeoAreaMonitorPollingPrivate : public QObject +{ + Q_OBJECT +public: + QGeoAreaMonitorPollingPrivate() : source(0), mutex(QMutex::Recursive) + { + nextExpiryTimer = new QTimer(this); + nextExpiryTimer->setSingleShot(true); + connect(nextExpiryTimer, SIGNAL(timeout()), + this, SLOT(timeout())); + } + + void startMonitoring(const QGeoAreaMonitorInfo &monitor) + { + QMutexLocker locker(&mutex); + + activeMonitorAreas.insert(monitor.identifier(), monitor); + singleShotTrigger.remove(monitor.identifier()); + + checkStartStop(); + setupNextExpiryTimeout(); + } + + void requestUpdate(const QGeoAreaMonitorInfo &monitor, int signalId) + { + QMutexLocker locker(&mutex); + + activeMonitorAreas.insert(monitor.identifier(), monitor); + singleShotTrigger.insert(monitor.identifier(), signalId); + + checkStartStop(); + setupNextExpiryTimeout(); + } + + QGeoAreaMonitorInfo stopMonitoring(const QGeoAreaMonitorInfo &monitor) + { + QMutexLocker locker(&mutex); + + QGeoAreaMonitorInfo mon = activeMonitorAreas.take(monitor.identifier()); + + checkStartStop(); + setupNextExpiryTimeout(); + + return mon; + } + + void registerClient(QGeoAreaMonitorPolling *client) + { + QMutexLocker locker(&mutex); + + connect(this, SIGNAL(timeout(QGeoAreaMonitorInfo)), + client, SLOT(timeout(QGeoAreaMonitorInfo))); + + connect(this, SIGNAL(positionError(QGeoPositionInfoSource::Error)), + client, SLOT(positionError(QGeoPositionInfoSource::Error))); + + connect(this, SIGNAL(areaEventDetected(QGeoAreaMonitorInfo,QGeoPositionInfo,bool)), + client, SLOT(processAreaEvent(QGeoAreaMonitorInfo,QGeoPositionInfo,bool))); + + registeredClients.append(client); + } + + void deregisterClient(QGeoAreaMonitorPolling *client) + { + QMutexLocker locker(&mutex); + + registeredClients.removeAll(client); + if (registeredClients.isEmpty()) + checkStartStop(); + } + + void setPositionSource(QGeoPositionInfoSource *newSource) + { + QMutexLocker locker(&mutex); + + if (newSource == source) + return; + + if (source) + delete source; + + source = newSource; + + if (source) { + source->setParent(this); + source->moveToThread(this->thread()); + if (source->updateInterval() == 0) + source->setUpdateInterval(UPDATE_INTERVAL_5S); + disconnect(source, 0, 0, 0); //disconnect all + connect(source, SIGNAL(positionUpdated(QGeoPositionInfo)), + this, SLOT(positionUpdated(QGeoPositionInfo))); + connect(source, SIGNAL(error(QGeoPositionInfoSource::Error)), + this, SIGNAL(positionError(QGeoPositionInfoSource::Error))); + checkStartStop(); + } + } + + QGeoPositionInfoSource* positionSource() const + { + QMutexLocker locker(&mutex); + return source; + } + + MonitorTable activeMonitors() const + { + QMutexLocker locker(&mutex); + + return activeMonitorAreas; + } + + void checkStartStop() + { + QMutexLocker locker(&mutex); + + bool signalsConnected = false; + foreach (const QGeoAreaMonitorPolling *client, registeredClients) { + if (client->signalsAreConnected) { + signalsConnected = true; + break; + } + } + + if (signalsConnected && !activeMonitorAreas.isEmpty()) { + if (source) + source->startUpdates(); + else + //translated to InsufficientPositionInfo + emit positionError(QGeoPositionInfoSource::ClosedError); + } else { + if (source) + source->stopUpdates(); + } + } + +private: + void setupNextExpiryTimeout() + { + nextExpiryTimer->stop(); + activeExpiry.first = QDateTime(); + activeExpiry.second = QString(); + + foreach (const QGeoAreaMonitorInfo &info, activeMonitors()) { + if (info.expiration().isValid()) { + if (!activeExpiry.first.isValid()) { + activeExpiry.first = info.expiration(); + activeExpiry.second = info.identifier(); + continue; + } + if (info.expiration() < activeExpiry.first) { + activeExpiry.first = info.expiration(); + activeExpiry.second = info.identifier(); + } + } + } + + if (activeExpiry.first.isValid()) + nextExpiryTimer->start(QDateTime::currentDateTime().msecsTo(activeExpiry.first)); + } + + + //returns true if areaEntered should be emitted + bool processInsideArea(const QString &monitorIdent) + { + if (!insideArea.contains(monitorIdent)) { + if (singleShotTrigger.value(monitorIdent, -1) == areaEnteredSignal().methodIndex()) { + //this is the finishing singleshot event + singleShotTrigger.remove(monitorIdent); + activeMonitorAreas.remove(monitorIdent); + setupNextExpiryTimeout(); + } else { + insideArea.insert(monitorIdent); + } + return true; + } + + return false; + } + + //returns true if areaExited should be emitted + bool processOutsideArea(const QString &monitorIdent) + { + if (insideArea.contains(monitorIdent)) { + if (singleShotTrigger.value(monitorIdent, -1) == areaExitedSignal().methodIndex()) { + //this is the finishing singleShot event + singleShotTrigger.remove(monitorIdent); + activeMonitorAreas.remove(monitorIdent); + setupNextExpiryTimeout(); + } else { + insideArea.remove(monitorIdent); + } + return true; + } + return false; + } + + + +Q_SIGNALS: + void timeout(const QGeoAreaMonitorInfo &info); + void positionError(const QGeoPositionInfoSource::Error error); + void areaEventDetected(const QGeoAreaMonitorInfo &minfo, + const QGeoPositionInfo &pinfo, bool isEnteredEvent); +private Q_SLOTS: + void timeout() + { + /* + * Don't block timer firing even if monitorExpiredSignal is not connected. + * This allows us to continue to remove the existing monitors as they expire. + **/ + const QGeoAreaMonitorInfo info = activeMonitorAreas.take(activeExpiry.second); + setupNextExpiryTimeout(); + emit timeout(info); + + } + + void positionUpdated(const QGeoPositionInfo &info) + { + foreach (const QGeoAreaMonitorInfo &monInfo, activeMonitors()) { + const QString identifier = monInfo.identifier(); + if (monInfo.area().contains(info.coordinate())) { + if (processInsideArea(identifier)) + emit areaEventDetected(monInfo, info, true); + } else { + if (processOutsideArea(identifier)) + emit areaEventDetected(monInfo, info, false); + } + } + } + +private: + QPair activeExpiry; + QHash singleShotTrigger; + QTimer* nextExpiryTimer; + QSet insideArea; + + MonitorTable activeMonitorAreas; + + QGeoPositionInfoSource* source; + QList registeredClients; + mutable QMutex mutex; +}; + +Q_GLOBAL_STATIC(QGeoAreaMonitorPollingPrivate, pollingPrivate) + + +QGeoAreaMonitorPolling::QGeoAreaMonitorPolling(QObject *parent) + : QGeoAreaMonitorSource(parent), signalsAreConnected(false) +{ + d = pollingPrivate(); + lastError = QGeoAreaMonitorSource::NoError; + d->registerClient(this); + //hookup to default source if existing + if (!positionInfoSource()) + setPositionInfoSource(QGeoPositionInfoSource::createDefaultSource(this)); +} + +QGeoAreaMonitorPolling::~QGeoAreaMonitorPolling() +{ + d->deregisterClient(this); +} + +QGeoPositionInfoSource* QGeoAreaMonitorPolling::positionInfoSource() const +{ + return d->positionSource(); +} + +void QGeoAreaMonitorPolling::setPositionInfoSource(QGeoPositionInfoSource *source) +{ + d->setPositionSource(source); +} + +QGeoAreaMonitorSource::Error QGeoAreaMonitorPolling::error() const +{ + return lastError; +} + +bool QGeoAreaMonitorPolling::startMonitoring(const QGeoAreaMonitorInfo &monitor) +{ + if (!monitor.isValid()) + return false; + + //reject an expiry in the past + if (monitor.expiration().isValid() && + (monitor.expiration() < QDateTime::currentDateTime())) + return false; + + //don't accept persistent monitor since we don't support it + if (monitor.isPersistent()) + return false; + + //update or insert + d->startMonitoring(monitor); + + return true; +} + +int QGeoAreaMonitorPolling::idForSignal(const char *signal) +{ + const QByteArray sig = QMetaObject::normalizedSignature(signal + 1); + const QMetaObject * const mo = metaObject(); + + return mo->indexOfSignal(sig.constData()); +} + +bool QGeoAreaMonitorPolling::requestUpdate(const QGeoAreaMonitorInfo &monitor, const char *signal) +{ + if (!monitor.isValid()) + return false; + //reject an expiry in the past + if (monitor.expiration().isValid() && + (monitor.expiration() < QDateTime::currentDateTime())) + return false; + + //don't accept persistent monitor since we don't support it + if (monitor.isPersistent()) + return false; + + if (!signal) + return false; + + const int signalId = idForSignal(signal); + if (signalId < 0) + return false; + + //only accept area entered or exit signal + if (signalId != areaEnteredSignal().methodIndex() && + signalId != areaExitedSignal().methodIndex()) + { + return false; + } + + d->requestUpdate(monitor, signalId); + + return true; +} + +bool QGeoAreaMonitorPolling::stopMonitoring(const QGeoAreaMonitorInfo &monitor) +{ + QGeoAreaMonitorInfo info = d->stopMonitoring(monitor); + + return info.isValid(); +} + +QList QGeoAreaMonitorPolling::activeMonitors() const +{ + return d->activeMonitors().values(); +} + +QList QGeoAreaMonitorPolling::activeMonitors(const QGeoShape ®ion) const +{ + QList results; + if (region.isEmpty()) + return results; + + const MonitorTable list = d->activeMonitors(); + foreach (const QGeoAreaMonitorInfo &monitor, list) { + if (region.contains(monitor.area().center())) + results.append(monitor); + } + + return results; +} + +QGeoAreaMonitorSource::AreaMonitorFeatures QGeoAreaMonitorPolling::supportedAreaMonitorFeatures() const +{ + return 0; +} + +void QGeoAreaMonitorPolling::connectNotify(const QMetaMethod &/*signal*/) +{ + if (!signalsAreConnected && + (isSignalConnected(areaEnteredSignal()) || + isSignalConnected(areaExitedSignal())) ) + { + signalsAreConnected = true; + d->checkStartStop(); + } +} + +void QGeoAreaMonitorPolling::disconnectNotify(const QMetaMethod &/*signal*/) +{ + if (!isSignalConnected(areaEnteredSignal()) && + !isSignalConnected(areaExitedSignal())) + { + signalsAreConnected = false; + d->checkStartStop(); + } +} + +void QGeoAreaMonitorPolling::positionError(const QGeoPositionInfoSource::Error error) +{ + switch (error) { + case QGeoPositionInfoSource::AccessError: + lastError = QGeoAreaMonitorSource::AccessError; + break; + case QGeoPositionInfoSource::UnknownSourceError: + lastError = QGeoAreaMonitorSource::UnknownSourceError; + break; + case QGeoPositionInfoSource::ClosedError: + lastError = QGeoAreaMonitorSource::InsufficientPositionInfo; + break; + case QGeoPositionInfoSource::NoError: + return; + } + + emit QGeoAreaMonitorSource::error(lastError); +} + +void QGeoAreaMonitorPolling::timeout(const QGeoAreaMonitorInfo& monitor) +{ + if (isSignalConnected(monitorExpiredSignal())) + emit monitorExpired(monitor); +} + +void QGeoAreaMonitorPolling::processAreaEvent(const QGeoAreaMonitorInfo &minfo, + const QGeoPositionInfo &pinfo, bool isEnteredEvent) +{ + if (isEnteredEvent) + emit areaEntered(minfo, pinfo); + else + emit areaExited(minfo, pinfo); +} + +#include "qgeoareamonitor_polling.moc" +#include "moc_qgeoareamonitor_polling.cpp" diff --git a/src/plugins/position/positionpoll/qgeoareamonitor_polling.h b/src/plugins/position/positionpoll/qgeoareamonitor_polling.h new file mode 100644 index 0000000..c40d424 --- /dev/null +++ b/src/plugins/position/positionpoll/qgeoareamonitor_polling.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOAREAMONITORPOLLING_H +#define QGEOAREAMONITORPOLLING_H + +#include +#include + + +/** + * QGeoAreaMonitorPolling + * + */ + +class QGeoAreaMonitorPollingPrivate; +class QGeoAreaMonitorPolling : public QGeoAreaMonitorSource +{ + Q_OBJECT +public : + explicit QGeoAreaMonitorPolling(QObject *parent = 0); + ~QGeoAreaMonitorPolling(); + + void setPositionInfoSource(QGeoPositionInfoSource *source) Q_DECL_OVERRIDE; + QGeoPositionInfoSource* positionInfoSource() const Q_DECL_OVERRIDE; + + Error error() const Q_DECL_OVERRIDE; + + bool startMonitoring(const QGeoAreaMonitorInfo &monitor) Q_DECL_OVERRIDE; + bool requestUpdate(const QGeoAreaMonitorInfo &monitor, + const char *signal) Q_DECL_OVERRIDE; + bool stopMonitoring(const QGeoAreaMonitorInfo &monitor) Q_DECL_OVERRIDE; + + QList activeMonitors() const Q_DECL_OVERRIDE; + QList activeMonitors(const QGeoShape ®ion) const Q_DECL_OVERRIDE; + + QGeoAreaMonitorSource::AreaMonitorFeatures supportedAreaMonitorFeatures() const Q_DECL_OVERRIDE; + + inline bool isValid() { return positionInfoSource(); } + + bool signalsAreConnected; + +private Q_SLOTS: + void positionError(QGeoPositionInfoSource::Error error); + void timeout(const QGeoAreaMonitorInfo &monitor); + void processAreaEvent(const QGeoAreaMonitorInfo &minfo, const QGeoPositionInfo &pinfo, bool isEnteredEvent); + +private: + QGeoAreaMonitorPollingPrivate* d; + QGeoAreaMonitorSource::Error lastError; + + void connectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; + void disconnectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; + + int idForSignal(const char *signal); +}; + +#endif // QGEOAREAMONITORPOLLING_H diff --git a/src/plugins/position/serialnmea/plugin.json b/src/plugins/position/serialnmea/plugin.json new file mode 100644 index 0000000..826836c --- /dev/null +++ b/src/plugins/position/serialnmea/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["serialnmea"], + "Provider": "serialnmea", + "Position": true, + "Satellite": false, + "Monitor" : false, + "Priority": 1000, + "Testable": false +} diff --git a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp new file mode 100644 index 0000000..1d1a6f4 --- /dev/null +++ b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosourcefactory_serialnmea.h" +#include +#include +#include +#include +#include + +Q_LOGGING_CATEGORY(lcSerial, "qt.positioning.serialnmea") + +class NmeaSource : public QNmeaPositionInfoSource +{ +public: + NmeaSource(QObject *parent); + bool isValid() const { return !m_port.isNull(); } + +private: + QScopedPointer m_port; +}; + +NmeaSource::NmeaSource(QObject *parent) + : QNmeaPositionInfoSource(RealTimeMode, parent), + m_port(new QSerialPort) +{ + QByteArray requestedPort = qgetenv("QT_NMEA_SERIAL_PORT"); + if (requestedPort.isEmpty()) { + const QList ports = QSerialPortInfo::availablePorts(); + qCDebug(lcSerial) << "Found" << ports.count() << "serial ports"; + if (ports.isEmpty()) { + qWarning("serialnmea: No serial ports found"); + m_port.reset(); + return; + } + + // Try to find a well-known device. + QSet supportedDevices; + supportedDevices << 0x67b; // GlobalSat (BU-353S4 and probably others) + supportedDevices << 0xe8d; // Qstarz MTK II + QString portName; + foreach (const QSerialPortInfo& port, ports) { + if (port.hasVendorIdentifier() && supportedDevices.contains(port.vendorIdentifier())) { + portName = port.portName(); + break; + } + } + + if (portName.isEmpty()) { + qWarning("serialnmea: No known GPS device found. Specify the COM port via QT_NMEA_SERIAL_PORT."); + m_port.reset(); + return; + } + + m_port->setPortName(portName); + } else { + m_port->setPortName(QString::fromUtf8(requestedPort)); + } + + m_port->setBaudRate(4800); + + qCDebug(lcSerial) << "Opening serial port" << m_port->portName(); + + if (!m_port->open(QIODevice::ReadOnly)) { + qWarning("serialnmea: Failed to open %s", qPrintable(m_port->portName())); + m_port.reset(); + return; + } + + setDevice(m_port.data()); + + qCDebug(lcSerial) << "Opened successfully"; +} + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactorySerialNmea::positionInfoSource(QObject *parent) +{ + QScopedPointer src(new NmeaSource(parent)); + return src->isValid() ? src.take() : Q_NULLPTR; +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactorySerialNmea::satelliteInfoSource(QObject *parent) +{ + Q_UNUSED(parent); + return Q_NULLPTR; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactorySerialNmea::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent); + return Q_NULLPTR; +} diff --git a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h new file mode 100644 index 0000000..e372d56 --- /dev/null +++ b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCEFACTORY_SERIALNMEA_H +#define QGEOPOSITIONINFOSOURCEFACTORY_SERIALNMEA_H + +#include +#include + +class QGeoPositionInfoSourceFactorySerialNmea : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) + +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +#endif diff --git a/src/plugins/position/serialnmea/serialnmea.pro b/src/plugins/position/serialnmea/serialnmea.pro new file mode 100644 index 0000000..bdeb3f1 --- /dev/null +++ b/src/plugins/position/serialnmea/serialnmea.pro @@ -0,0 +1,16 @@ +TARGET = qtposition_serialnmea + +QT = core positioning serialport + +HEADERS += \ + qgeopositioninfosourcefactory_serialnmea.h + +SOURCES += \ + qgeopositioninfosourcefactory_serialnmea.cpp + +OTHER_FILES += \ + plugin.json + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactorySerialNmea +load(qt_plugin) diff --git a/src/plugins/position/simulator/plugin.json b/src/plugins/position/simulator/plugin.json new file mode 100644 index 0000000..0935f4d --- /dev/null +++ b/src/plugins/position/simulator/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["simulator"], + "Provider": "simulator", + "Position": true, + "Satellite": true, + "Monitor" : false, + "Priority": 1000, + "Testable": true +} diff --git a/src/plugins/position/simulator/qgeopositioninfosource_simulator.cpp b/src/plugins/position/simulator/qgeopositioninfosource_simulator.cpp new file mode 100644 index 0000000..2942442 --- /dev/null +++ b/src/plugins/position/simulator/qgeopositioninfosource_simulator.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosource_simulator_p.h" +#include "qlocationdata_simulator_p.h" +#include "qlocationconnection_simulator_p.h" + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace Simulator +{ + QGeoPositionInfo toPositionInfo(const QGeoPositionInfoData &data) + { + QDateTime timestamp; + if (data.dateTime.isValid()) + timestamp = data.dateTime; + else + timestamp = QDateTime::currentDateTime(); + QGeoCoordinate coord(data.latitude, data.longitude, data.altitude); + QGeoPositionInfo info(coord, timestamp); + info.setAttribute(QGeoPositionInfo::Direction, data.direction); + info.setAttribute(QGeoPositionInfo::GroundSpeed, data.groundSpeed); + info.setAttribute(QGeoPositionInfo::VerticalSpeed, data.verticalSpeed); + info.setAttribute(QGeoPositionInfo::MagneticVariation, data.magneticVariation); + info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, data.horizontalAccuracy); + info.setAttribute(QGeoPositionInfo::VerticalAccuracy, data.verticalAccuracy); + return info; + } +} //namespace + +// Location API + +QGeoPositionInfoSourceSimulator::QGeoPositionInfoSourceSimulator(QObject *parent) + : QGeoPositionInfoSource(parent) + , timer(new QTimer(this)) + , requestTimer(new QTimer(this)) + , m_positionError(QGeoPositionInfoSource::NoError) +{ + Simulator::LocationConnection::ensureSimulatorConnection(); + + connect(timer, SIGNAL(timeout()), this, SLOT(updatePosition())); + requestTimer->setSingleShot(true); + connect(requestTimer, SIGNAL(timeout()), this, SLOT(updatePosition())); +} + +QGeoPositionInfoSourceSimulator::~QGeoPositionInfoSourceSimulator() +{ +} + +QGeoPositionInfo QGeoPositionInfoSourceSimulator::lastKnownPosition(bool /*fromSatellitePositioningMethodsOnly*/) const +{ + return lastPosition; +} + +QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceSimulator::supportedPositioningMethods() const +{ + // Is GPS now Satelite or not? Guessing so... + return QGeoPositionInfoSource::SatellitePositioningMethods; +} + +void QGeoPositionInfoSourceSimulator::setUpdateInterval(int msec) +{ + // If msec is 0 we send updates as data becomes available, otherwise we force msec to be equal + // to or larger than the minimum update interval. + if (msec != 0 && msec < minimumUpdateInterval()) + msec = minimumUpdateInterval(); + + QGeoPositionInfoSource::setUpdateInterval(msec); + if (timer->isActive()) { + timer->setInterval(msec); + timer->start(); + } +} + +int QGeoPositionInfoSourceSimulator::minimumUpdateInterval() const +{ + return qtPositionInfo()->minimumInterval; +} + +void QGeoPositionInfoSourceSimulator::startUpdates() +{ + int interval = updateInterval(); + if (interval < minimumUpdateInterval()) + interval = minimumUpdateInterval(); + timer->setInterval(interval); + timer->start(); +} + +void QGeoPositionInfoSourceSimulator::stopUpdates() +{ + timer->stop(); +} + +void QGeoPositionInfoSourceSimulator::requestUpdate(int timeout) +{ + if (!requestTimer->isActive()) { + // Get a single update within timeframe + if (timeout < minimumUpdateInterval() && timeout != 0) + emit updateTimeout(); + else { + requestTimer->start(timeout * qreal(0.75)); + } + } +} + +void QGeoPositionInfoSourceSimulator::updatePosition() +{ + if (qtPositionInfo()->enabled) { + lastPosition = Simulator::toPositionInfo(*qtPositionInfo()); + emit positionUpdated(lastPosition); + } else { + emit updateTimeout(); + } +} + +QGeoPositionInfoSource::Error QGeoPositionInfoSourceSimulator::error() const +{ + return m_positionError; +} + + +void QGeoPositionInfoSourceSimulator::setError(QGeoPositionInfoSource::Error positionError) +{ + m_positionError = positionError; + emit QGeoPositionInfoSource::error(positionError); +} + +#include "moc_qgeopositioninfosource_simulator_p.cpp" + +QT_END_NAMESPACE diff --git a/src/plugins/position/simulator/qgeopositioninfosource_simulator_p.h b/src/plugins/position/simulator/qgeopositioninfosource_simulator_p.h new file mode 100644 index 0000000..6b1acfc --- /dev/null +++ b/src/plugins/position/simulator/qgeopositioninfosource_simulator_p.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCESIMULATOR_H +#define QGEOPOSITIONINFOSOURCESIMULATOR_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeopositioninfosource.h" +#include "qgeopositioninfo.h" +#include "qlocationdata_simulator_p.h" + +QT_BEGIN_NAMESPACE + +class QTimer; + +class QGeoPositionInfoSourceSimulator : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + QGeoPositionInfoSourceSimulator(QObject *parent = 0); + ~QGeoPositionInfoSourceSimulator(); + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + PositioningMethods supportedPositioningMethods() const; + + void setUpdateInterval(int msec); + int minimumUpdateInterval() const; + Error error() const; + +public Q_SLOTS: + void startUpdates(); + void stopUpdates(); + + void requestUpdate(int timeout = 0); + +private slots: + void updatePosition(); +private: + Q_DISABLE_COPY(QGeoPositionInfoSourceSimulator); + QTimer *timer; + QTimer *requestTimer; + QGeoPositionInfo lastPosition; + QGeoPositionInfoSource::Error m_positionError; + void setError(QGeoPositionInfoSource::Error positionError); +}; + +QT_END_NAMESPACE + +#endif // QGEOPOSITIONINFOSOURCESIMULATOR_H diff --git a/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.cpp b/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.cpp new file mode 100644 index 0000000..9ddc2b9 --- /dev/null +++ b/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosourcefactory_simulator.h" + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactorySimulator::positionInfoSource(QObject *parent) +{ + return new QGeoPositionInfoSourceSimulator(parent); +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactorySimulator::satelliteInfoSource(QObject *parent) +{ + QGeoSatelliteInfoSourceSimulator *src = new QGeoSatelliteInfoSourceSimulator(parent); + if (!src->isConnected()) { + delete src; + src = 0; + } + return src; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactorySimulator::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} diff --git a/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.h b/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.h new file mode 100644 index 0000000..2d3146e --- /dev/null +++ b/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCEFACTORY_SIMULATOR_H +#define QGEOPOSITIONINFOSOURCEFACTORY_SIMULATOR_H + +#include +#include + +#include "qgeopositioninfosource_simulator_p.h" +#include "qgeosatelliteinfosource_simulator_p.h" + +class QGeoPositionInfoSourceFactorySimulator : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +#endif // QGEOPOSITIONINFOSOURCEFACTORY_SIMULATOR_H diff --git a/src/plugins/position/simulator/qgeosatelliteinfosource_simulator.cpp b/src/plugins/position/simulator/qgeosatelliteinfosource_simulator.cpp new file mode 100644 index 0000000..1ec62a7 --- /dev/null +++ b/src/plugins/position/simulator/qgeosatelliteinfosource_simulator.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeosatelliteinfosource_simulator_p.h" +#include "qlocationconnection_simulator_p.h" +#include "qlocationdata_simulator_p.h" + +QT_BEGIN_NAMESPACE + +QGeoSatelliteInfoSourceSimulator::QGeoSatelliteInfoSourceSimulator(QObject *parent) + : QGeoSatelliteInfoSource(parent) + , timer(new QTimer(this)) + , requestTimer(new QTimer(this)) +{ + Simulator::LocationConnection::ensureSimulatorConnection(); + + connect(timer, SIGNAL(timeout()), this, SLOT(updateData())); + requestTimer->setSingleShot(true); + connect(requestTimer, SIGNAL(timeout()), this, SLOT(updateData())); +} + +bool QGeoSatelliteInfoSourceSimulator::isConnected() const +{ + return Simulator::LocationConnection::ensureSimulatorConnection(); +} + +void QGeoSatelliteInfoSourceSimulator::startUpdates() +{ + int interval = updateInterval(); + if (interval < minimumUpdateInterval()) + interval = minimumUpdateInterval(); + timer->setInterval(interval); + timer->start(); +} + +void QGeoSatelliteInfoSourceSimulator::stopUpdates() +{ + timer->stop(); +} + +void QGeoSatelliteInfoSourceSimulator::requestUpdate(int timeout) +{ + if (!requestTimer->isActive()) { + // Get a single update within timeframe + if (timeout == 0) + timeout = minimumUpdateInterval(); + + if (timeout < minimumUpdateInterval()) + emit requestTimeout(); + else + requestTimer->start(timeout); + } +} + +void QGeoSatelliteInfoSourceSimulator::setUpdateInterval(int msec) +{ + // msec should be equal to or larger than the minimum update interval; 0 is a special case + // that currently behaves as if the interval is set to the minimum update interval + if (msec != 0 && msec < minimumUpdateInterval()) + msec = minimumUpdateInterval(); + + QGeoSatelliteInfoSource::setUpdateInterval(msec); + if (timer->isActive()) { + timer->setInterval(msec); + timer->start(); + } +} + +int QGeoSatelliteInfoSourceSimulator::minimumUpdateInterval() const +{ + return qtPositionInfo()->minimumInterval; +} + +void QGeoSatelliteInfoSourceSimulator::updateData() +{ + QList satellitesInUse; + QList satellitesInView; + + QGeoSatelliteInfoData *data = qtSatelliteInfo(); + for(int i = 0; i < data->satellites.count(); i++) { + QGeoSatelliteInfoData::SatelliteInfo info = data->satellites.at(i); + QGeoSatelliteInfo satInfo; + satInfo.setAttribute(QGeoSatelliteInfo::Azimuth, info.azimuth); + satInfo.setAttribute(QGeoSatelliteInfo::Elevation, info.elevation); + satInfo.setSignalStrength(info.signalStrength); + satInfo.setSatelliteSystem(static_cast(info.satelliteSystem)); + satInfo.setSatelliteIdentifier(info.satelliteIdentifier); + satellitesInView.append(satInfo); + if (info.inUse) + satellitesInUse.append(satInfo); + } + emit satellitesInViewUpdated(satellitesInView); + emit satellitesInUseUpdated(satellitesInUse); +} + +#include "moc_qgeosatelliteinfosource_simulator_p.cpp" +QT_END_NAMESPACE diff --git a/src/plugins/position/simulator/qgeosatelliteinfosource_simulator_p.h b/src/plugins/position/simulator/qgeosatelliteinfosource_simulator_p.h new file mode 100644 index 0000000..c2fb0d0 --- /dev/null +++ b/src/plugins/position/simulator/qgeosatelliteinfosource_simulator_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSATELLITEINFOSOURCE_SIMULATOR_H +#define QGEOSATELLITEINFOSOURCE_SIMULATOR_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include "qgeosatelliteinfosource.h" +#include "qgeosatelliteinfo.h" + +#define MINIMUM_UPDATE_INTERVAL 1000 +#define DEFAULT_UPDATE_INTERVAL 5000 + +QT_BEGIN_NAMESPACE + +class QGeoSatelliteInfoSourceSimulator : public QGeoSatelliteInfoSource +{ + Q_OBJECT + +public: + explicit QGeoSatelliteInfoSourceSimulator(QObject *parent = 0); + + bool isConnected() const; + + virtual void setUpdateInterval(int msec); + virtual int minimumUpdateInterval() const; + + // Default implementation for error() + Error error() const { return QGeoSatelliteInfoSource::NoError; } +public slots: + virtual void startUpdates(); + virtual void stopUpdates(); + virtual void requestUpdate(int timeout = 5000); + +private slots: + void updateData(); + +private: + Q_DISABLE_COPY(QGeoSatelliteInfoSourceSimulator) + QTimer *timer; + QTimer *requestTimer; +}; + +QT_END_NAMESPACE + +#endif // QGEOSATELLITEINFOSOURCE_SIMULATOR_H + diff --git a/src/plugins/position/simulator/qlocationconnection_simulator.cpp b/src/plugins/position/simulator/qlocationconnection_simulator.cpp new file mode 100644 index 0000000..f8e1da0 --- /dev/null +++ b/src/plugins/position/simulator/qlocationconnection_simulator.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlocationconnection_simulator_p.h" +#include "qgeopositioninfosource_simulator_p.h" +#include "qlocationdata_simulator_p.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +const QString simulatorName(QString::fromLatin1("QtSimulator_Mobility_ServerName1.3.0.0")); +const quint16 simulatorPort = 0xbeef + 1; + +namespace Simulator +{ + LocationConnection::LocationConnection() + : mConnection(new Connection(Connection::Client, simulatorName, simulatorPort, Version(1,3,0,0))) + { + qt_registerLocationTypes(); + mWorker = mConnection->connectToServer(Connection::simulatorHostName(true), simulatorPort); + if (!mWorker) + return; + + mWorker->addReceiver(this); + + // register for location notifications + mWorker->call("setRequestsLocationInfo"); + } + + LocationConnection::~LocationConnection() + { + delete mWorker; + delete mConnection; + } + + bool LocationConnection::ensureSimulatorConnection() + { + static LocationConnection locationConnection; + return locationConnection.mWorker; + } + + void LocationConnection::initialLocationDataSent() + { + emit initialDataReceived(); + } + + void LocationConnection::setLocationData(const QGeoPositionInfoData &data) + { + *qtPositionInfo() = data; + } + + void LocationConnection::setSatelliteData(const QGeoSatelliteInfoData &data) + { + *qtSatelliteInfo() = data; + } + +#include "moc_qlocationconnection_simulator_p.cpp" + +} // namespace + +QGeoPositionInfoData *qtPositionInfo() +{ + static QGeoPositionInfoData *positionInfo = 0; + if (!positionInfo) { + positionInfo = new QGeoPositionInfoData; + } + + return positionInfo; +} + +QGeoSatelliteInfoData *qtSatelliteInfo() +{ + static QGeoSatelliteInfoData *satelliteInfo = 0; + if (!satelliteInfo) { + satelliteInfo = new QGeoSatelliteInfoData; + } + + return satelliteInfo; +} + + +QT_END_NAMESPACE diff --git a/src/plugins/position/simulator/qlocationconnection_simulator_p.h b/src/plugins/position/simulator/qlocationconnection_simulator_p.h new file mode 100644 index 0000000..a13c9e8 --- /dev/null +++ b/src/plugins/position/simulator/qlocationconnection_simulator_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOCATIONCONNECTION_H +#define QLOCATIONCONNECTION_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qlocationdata_simulator_p.h" + +#include + +QT_BEGIN_NAMESPACE + +namespace Simulator +{ + class Connection; + class ConnectionWorker; + + class LocationConnection : public QObject + { + Q_OBJECT + + public: + static bool ensureSimulatorConnection(); + virtual ~LocationConnection(); + + private: + LocationConnection(); + Q_DISABLE_COPY(LocationConnection) + + private slots: + // these will be called by the simulator + void setLocationData(const QGeoPositionInfoData &); + void setSatelliteData(const QGeoSatelliteInfoData &); + void initialLocationDataSent(); + + signals: + void initialDataReceived(); + + private: + Connection *mConnection; + ConnectionWorker *mWorker; + }; +} // end namespace Simulator + +QGeoPositionInfoData *qtPositionInfo(); +QGeoSatelliteInfoData *qtSatelliteInfo(); + +QT_END_NAMESPACE + +#endif // QLOCATIONCONNECTION_H diff --git a/src/plugins/position/simulator/simulator.pro b/src/plugins/position/simulator/simulator.pro new file mode 100644 index 0000000..c3e6ea3 --- /dev/null +++ b/src/plugins/position/simulator/simulator.pro @@ -0,0 +1,22 @@ +TARGET = qtposition_simulator + +QT = core network positioning simulator + +INCLUDEPATH += ../../../positioning + +DEFINES += QT_SIMULATOR +SOURCES += qgeopositioninfosource_simulator.cpp \ + qgeosatelliteinfosource_simulator.cpp \ + qlocationconnection_simulator.cpp \ + qgeopositioninfosourcefactory_simulator.cpp +HEADERS += qgeopositioninfosource_simulator_p.h \ + qgeosatelliteinfosource_simulator_p.h \ + qlocationconnection_simulator_p.h \ + qgeopositioninfosourcefactory_simulator.h + +OTHER_FILES += \ + plugin.json + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactorySimulator +load(qt_plugin) diff --git a/src/plugins/position/winrt/plugin.json b/src/plugins/position/winrt/plugin.json new file mode 100644 index 0000000..0696cb0 --- /dev/null +++ b/src/plugins/position/winrt/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["winrt"], + "Provider": "winrt", + "Position": true, + "Satellite": false, + "Monitor" : false, + "Priority": 1000, + "Testable": false +} diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp new file mode 100644 index 0000000..245d855 --- /dev/null +++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp @@ -0,0 +1,535 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosource_winrt_p.h" + +#include +#include +#include +#ifdef Q_OS_WINRT +#include +#endif + +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Devices::Geolocation; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; + +typedef ITypedEventHandler GeoLocatorPositionHandler; +typedef ITypedEventHandler GeoLocatorStatusHandler; +typedef IAsyncOperationCompletedHandler PositionHandler; +#if _MSC_VER >= 1900 +typedef IAsyncOperationCompletedHandler AccessHandler; +#endif + +QT_BEGIN_NAMESPACE + +Q_DECLARE_METATYPE(QGeoPositionInfo) + +#ifndef Q_OS_WINRT +namespace QEventDispatcherWinRT { +HRESULT runOnXamlThread(const std::function &delegate, bool waitForRun = true) +{ + Q_UNUSED(waitForRun); + return delegate(); +} +} +#endif + +class QGeoPositionInfoSourceWinRTPrivate { +public: + ComPtr locator; + QTimer periodicTimer; + QTimer singleUpdateTimer; + QGeoPositionInfo lastPosition; + QGeoPositionInfoSource::Error positionError; + EventRegistrationToken statusToken; + EventRegistrationToken positionToken; + QMutex mutex; + bool updatesOngoing; +}; + + +QGeoPositionInfoSourceWinRT::QGeoPositionInfoSourceWinRT(QObject *parent) + : QGeoPositionInfoSource(parent) + , d_ptr(new QGeoPositionInfoSourceWinRTPrivate) +{ + Q_D(QGeoPositionInfoSourceWinRT); + d->positionError = QGeoPositionInfoSource::NoError; + d->updatesOngoing = false; + + qRegisterMetaType(); + + requestAccess(); + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { + HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(), + &d->locator); + RETURN_HR_IF_FAILED("Could not initialize native location services."); + + // StatusChanged throws an exception on Windows 8.1 +#if _MSC_VER >= 1900 + hr = d->locator->add_StatusChanged(Callback(this, + &QGeoPositionInfoSourceWinRT::onStatusChanged).Get(), + &d->statusToken); + RETURN_HR_IF_FAILED("Could not add status callback."); +#endif + + hr = d->locator->put_ReportInterval(1000); + RETURN_HR_IF_FAILED("Could not initialize report interval."); + + return hr; + }); + Q_ASSERT_SUCCEEDED(hr); + + hr = d->locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_Default); + if (FAILED(hr)) { + setError(QGeoPositionInfoSource::UnknownSourceError); + qErrnoWarning(hr, "Could not initialize desired accuracy."); + return; + } + + d->positionToken.value = 0; + + d->periodicTimer.setSingleShot(true); + d->periodicTimer.setInterval(minimumUpdateInterval()); + connect(&d->periodicTimer, &QTimer::timeout, this, &QGeoPositionInfoSourceWinRT::virtualPositionUpdate); + + d->singleUpdateTimer.setSingleShot(true); + connect(&d->singleUpdateTimer, &QTimer::timeout, this, &QGeoPositionInfoSourceWinRT::singleUpdateTimeOut); + + setPreferredPositioningMethods(QGeoPositionInfoSource::AllPositioningMethods); + + connect(this, &QGeoPositionInfoSourceWinRT::nativePositionUpdate, this, &QGeoPositionInfoSourceWinRT::updateSynchronized); +} + +QGeoPositionInfoSourceWinRT::~QGeoPositionInfoSourceWinRT() +{ +} + +QGeoPositionInfo QGeoPositionInfoSourceWinRT::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +{ + Q_D(const QGeoPositionInfoSourceWinRT); + Q_UNUSED(fromSatellitePositioningMethodsOnly) + return d->lastPosition; +} + +QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceWinRT::supportedPositioningMethods() const +{ + Q_D(const QGeoPositionInfoSourceWinRT); + + PositionStatus status; + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, &status]() { + HRESULT hr = d->locator->get_LocationStatus(&status); + return hr; + }); + if (FAILED(hr)) + return QGeoPositionInfoSource::NoPositioningMethods; + + switch (status) { + case PositionStatus::PositionStatus_NoData: + case PositionStatus::PositionStatus_Disabled: + case PositionStatus::PositionStatus_NotAvailable: + return QGeoPositionInfoSource::NoPositioningMethods; + } + + return QGeoPositionInfoSource::AllPositioningMethods; +} + +void QGeoPositionInfoSourceWinRT::setPreferredPositioningMethods(QGeoPositionInfoSource::PositioningMethods methods) +{ + Q_D(QGeoPositionInfoSourceWinRT); + + PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods(); + QGeoPositionInfoSource::setPreferredPositioningMethods(methods); + if (previousPreferredPositioningMethods == preferredPositioningMethods()) + return; + + bool needsRestart = d->positionToken.value != 0; + + if (needsRestart) + stopHandler(); + + PositionAccuracy acc = methods & PositioningMethod::SatellitePositioningMethods ? + PositionAccuracy::PositionAccuracy_High : + PositionAccuracy::PositionAccuracy_Default; + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, acc]() { + HRESULT hr = d->locator->put_DesiredAccuracy(acc); + return hr; + }); + RETURN_VOID_IF_FAILED("Could not set positioning accuracy."); + + if (needsRestart) + startHandler(); +} + +void QGeoPositionInfoSourceWinRT::setUpdateInterval(int msec) +{ + Q_D(QGeoPositionInfoSourceWinRT); + // Windows Phone 8.1 and Windows 10 do not support 0 interval +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) + if (msec == 0) + msec = minimumUpdateInterval(); +#endif + + // If msec is 0 we send updates as data becomes available, otherwise we force msec to be equal + // to or larger than the minimum update interval. + if (msec != 0 && msec < minimumUpdateInterval()) + msec = minimumUpdateInterval(); + + HRESULT hr = d->locator->put_ReportInterval(msec); + if (FAILED(hr)) { + setError(QGeoPositionInfoSource::UnknownSourceError); + qErrnoWarning(hr, "Failed to set update interval"); + return; + } + + d->periodicTimer.setInterval(qMax(msec, minimumUpdateInterval())); + + QGeoPositionInfoSource::setUpdateInterval(msec); +} + +int QGeoPositionInfoSourceWinRT::minimumUpdateInterval() const +{ + // We use one second to reduce potential timer events + // in case the platform itself stops reporting + return 1000; +} + +void QGeoPositionInfoSourceWinRT::startUpdates() +{ + Q_D(QGeoPositionInfoSourceWinRT); + + if (d->updatesOngoing) + return; + + if (!startHandler()) + return; + d->updatesOngoing = true; + d->periodicTimer.start(); +} + +void QGeoPositionInfoSourceWinRT::stopUpdates() +{ + Q_D(QGeoPositionInfoSourceWinRT); + + stopHandler(); + d->updatesOngoing = false; + d->periodicTimer.stop(); +} + +bool QGeoPositionInfoSourceWinRT::startHandler() +{ + Q_D(QGeoPositionInfoSourceWinRT); + + // Check if already attached + if (d->positionToken.value != 0) + return true; + + if (preferredPositioningMethods() == QGeoPositionInfoSource::NoPositioningMethods) { + setError(QGeoPositionInfoSource::UnknownSourceError); + return false; + } + + if (!requestAccess() || !checkNativeState()) + return false; + + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { + HRESULT hr; + + // We need to call this at least once on Windows 10 Mobile. + // Unfortunately this operation does not have a completion handler + // registered. That could have helped in the single update case + ComPtr> op; + hr = d->locator->GetGeopositionAsync(&op); + + hr = d->locator->add_PositionChanged(Callback(this, + &QGeoPositionInfoSourceWinRT::onPositionChanged).Get(), + &d->positionToken); + return hr; + }); + if (FAILED(hr)) { + setError(QGeoPositionInfoSource::UnknownSourceError); + qErrnoWarning(hr, "Could not add position handler"); + return false; + } + + return true; +} + +void QGeoPositionInfoSourceWinRT::stopHandler() +{ + Q_D(QGeoPositionInfoSourceWinRT); + + if (!d->positionToken.value) + return; + QEventDispatcherWinRT::runOnXamlThread([d]() { + d->locator->remove_PositionChanged(d->positionToken); + return S_OK; + }); + d->positionToken.value = 0; +} + +void QGeoPositionInfoSourceWinRT::requestUpdate(int timeout) +{ + Q_D(QGeoPositionInfoSourceWinRT); + + if (timeout != 0 && timeout < minimumUpdateInterval()) { + emit updateTimeout(); + return; + } + + if (timeout == 0) + timeout = 2*60*1000; // Maximum time for cold start (see Android) + + startHandler(); + d->singleUpdateTimer.start(timeout); +} + +void QGeoPositionInfoSourceWinRT::virtualPositionUpdate() +{ + Q_D(QGeoPositionInfoSourceWinRT); + QMutexLocker locker(&d->mutex); + + // Need to check if services are still running and ok + if (!checkNativeState()) { + stopUpdates(); + return; + } + + // The operating system did not provide information in time + // Hence we send a virtual position update to keep same behavior + // between backends. + // This only applies to the periodic timer, not for single requests + // We can only do this if we received a valid position before + if (d->lastPosition.isValid()) { + QGeoPositionInfo sent = d->lastPosition; + sent.setTimestamp(QDateTime::currentDateTime()); + d->lastPosition = sent; + emit positionUpdated(sent); + } + d->periodicTimer.start(); +} + +void QGeoPositionInfoSourceWinRT::singleUpdateTimeOut() +{ + Q_D(QGeoPositionInfoSourceWinRT); + QMutexLocker locker(&d->mutex); + + if (d->singleUpdateTimer.isActive()) { + emit updateTimeout(); + if (!d->updatesOngoing) + stopHandler(); + } +} + +void QGeoPositionInfoSourceWinRT::updateSynchronized(QGeoPositionInfo currentInfo) +{ + Q_D(QGeoPositionInfoSourceWinRT); + QMutexLocker locker(&d->mutex); + + d->periodicTimer.stop(); + d->lastPosition = currentInfo; + + if (d->updatesOngoing) + d->periodicTimer.start(); + + if (d->singleUpdateTimer.isActive()) { + d->singleUpdateTimer.stop(); + if (!d->updatesOngoing) + stopHandler(); + } + + emit positionUpdated(currentInfo); +} + +QGeoPositionInfoSource::Error QGeoPositionInfoSourceWinRT::error() const +{ + Q_D(const QGeoPositionInfoSourceWinRT); + return d->positionError; +} + +void QGeoPositionInfoSourceWinRT::setError(QGeoPositionInfoSource::Error positionError) +{ + Q_D(QGeoPositionInfoSourceWinRT); + + if (positionError == d->positionError) + return; + d->positionError = positionError; + emit QGeoPositionInfoSource::error(positionError); +} + +bool QGeoPositionInfoSourceWinRT::checkNativeState() +{ + Q_D(QGeoPositionInfoSourceWinRT); + + PositionStatus status; + HRESULT hr = d->locator->get_LocationStatus(&status); + if (FAILED(hr)) { + setError(QGeoPositionInfoSource::UnknownSourceError); + qErrnoWarning(hr, "Could not query status"); + return false; + } + + bool result = false; + switch (status) { + case PositionStatus::PositionStatus_NotAvailable: + setError(QGeoPositionInfoSource::UnknownSourceError); + break; + case PositionStatus::PositionStatus_Disabled: + case PositionStatus::PositionStatus_NoData: + setError(QGeoPositionInfoSource::ClosedError); + break; + default: + setError(QGeoPositionInfoSource::NoError); + result = true; + break; + } + return result; +} + +HRESULT QGeoPositionInfoSourceWinRT::onPositionChanged(IGeolocator *locator, IPositionChangedEventArgs *args) +{ + Q_UNUSED(locator); + + HRESULT hr; + ComPtr pos; + hr = args->get_Position(&pos); + RETURN_HR_IF_FAILED("Could not access position object."); + + QGeoPositionInfo currentInfo; + + ComPtr coord; + hr = pos->get_Coordinate(&coord); + if (FAILED(hr)) + qErrnoWarning(hr, "Could not access coordinate"); + + DOUBLE lat; + hr = coord->get_Latitude(&lat); + if (FAILED(hr)) + qErrnoWarning(hr, "Could not access latitude"); + + DOUBLE lon; + hr = coord->get_Longitude(&lon); + if (FAILED(hr)) + qErrnoWarning(hr, "Could not access longitude"); + + // Depending on data source altitude can + // be identified or not + IReference *alt; + hr = coord->get_Altitude(&alt); + if (SUCCEEDED(hr) && alt) { + double altd; + hr = alt->get_Value(&altd); + currentInfo.setCoordinate(QGeoCoordinate(lat, lon, altd)); + } else { + currentInfo.setCoordinate(QGeoCoordinate(lat, lon)); + } + + DOUBLE accuracy; + hr = coord->get_Accuracy(&accuracy); + if (SUCCEEDED(hr)) + currentInfo.setAttribute(QGeoPositionInfo::HorizontalAccuracy, accuracy); + + IReference *altAccuracy; + hr = coord->get_AltitudeAccuracy(&altAccuracy); + if (SUCCEEDED(hr) && altAccuracy) { + double value; + hr = alt->get_Value(&value); + currentInfo.setAttribute(QGeoPositionInfo::VerticalAccuracy, value); + } + + IReference *speed; + hr = coord->get_Speed(&speed); + if (SUCCEEDED(hr) && speed) { + double value; + hr = speed->get_Value(&value); + currentInfo.setAttribute(QGeoPositionInfo::GroundSpeed, value); + } + + currentInfo.setTimestamp(QDateTime::currentDateTime()); + + emit nativePositionUpdate(currentInfo); + + return S_OK; +} + +HRESULT QGeoPositionInfoSourceWinRT::onStatusChanged(IGeolocator*, IStatusChangedEventArgs *args) +{ + PositionStatus st; + args->get_Status(&st); + return S_OK; +} + +bool QGeoPositionInfoSourceWinRT::requestAccess() const +{ +#if _MSC_VER >= 1900 && defined(Q_OS_WINRT) + static GeolocationAccessStatus accessStatus = GeolocationAccessStatus_Unspecified; + static ComPtr statics; + + if (accessStatus == GeolocationAccessStatus_Allowed) + return true; + else if (accessStatus == GeolocationAccessStatus_Denied) + return false; + + ComPtr> op; + HRESULT hr; + hr = QEventDispatcherWinRT::runOnXamlThread([&op]() { + HRESULT hr; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(), + IID_PPV_ARGS(&statics)); + RETURN_HR_IF_FAILED("Could not access Geolocation Statics."); + + hr = statics->RequestAccessAsync(&op); + return hr; + }); + Q_ASSERT_SUCCEEDED(hr); + + // We cannot wait inside the XamlThread as that would deadlock + QWinRTFunctions::await(op, &accessStatus); + return accessStatus == GeolocationAccessStatus_Allowed; +#else // _MSC_VER < 1900 + return true; +#endif // _MSC_VER < 1900 +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h b/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h new file mode 100644 index 0000000..b8820dd --- /dev/null +++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCEWINRT_H +#define QGEOPOSITIONINFOSOURCEWINRT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeopositioninfosource.h" +#include "qgeopositioninfo.h" + +#include + +#include +#include + +namespace ABI { + namespace Windows { + namespace Devices { + namespace Geolocation{ + struct IGeolocator; + struct IPositionChangedEventArgs; + struct IStatusChangedEventArgs; + } + } + } +} + +QT_BEGIN_NAMESPACE + +class QGeoPositionInfoSourceWinRTPrivate; + +class QGeoPositionInfoSourceWinRT : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + QGeoPositionInfoSourceWinRT(QObject *parent = 0); + ~QGeoPositionInfoSourceWinRT(); + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + PositioningMethods supportedPositioningMethods() const; + + void setPreferredPositioningMethods(PositioningMethods methods); + + void setUpdateInterval(int msec); + int minimumUpdateInterval() const; + Error error() const; + + HRESULT onPositionChanged(ABI::Windows::Devices::Geolocation::IGeolocator *locator, + ABI::Windows::Devices::Geolocation::IPositionChangedEventArgs *args); + + HRESULT onStatusChanged(ABI::Windows::Devices::Geolocation::IGeolocator*, + ABI::Windows::Devices::Geolocation::IStatusChangedEventArgs *args); + + bool requestAccess() const; +Q_SIGNALS: + void nativePositionUpdate(const QGeoPositionInfo); +public slots: + void startUpdates(); + void stopUpdates(); + + void requestUpdate(int timeout = 0); + +private slots: + void stopHandler(); + void virtualPositionUpdate(); + void singleUpdateTimeOut(); + void updateSynchronized(const QGeoPositionInfo info); +private: + bool startHandler(); + + Q_DISABLE_COPY(QGeoPositionInfoSourceWinRT) + void setError(QGeoPositionInfoSource::Error positionError); + bool checkNativeState(); + + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(QGeoPositionInfoSourceWinRT) +}; + +QT_END_NAMESPACE + +#endif // QGEOPOSITIONINFOSOURCEWINRT_H diff --git a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp new file mode 100644 index 0000000..81656c2 --- /dev/null +++ b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosourcefactory_winrt.h" +#include "qgeopositioninfosource_winrt_p.h" + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryWinRT::positionInfoSource(QObject *parent) +{ + return new QGeoPositionInfoSourceWinRT(parent); +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryWinRT::satelliteInfoSource(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryWinRT::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} diff --git a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h new file mode 100644 index 0000000..46cd385 --- /dev/null +++ b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCEFACTORY_WINRT_H +#define QGEOPOSITIONINFOSOURCEFACTORY_WINRT_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoPositionInfoSourceFactoryWinRT : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +QT_END_NAMESPACE + +#endif // QGEOPOSITIONINFOSOURCEFACTORY_WINRT_H diff --git a/src/plugins/position/winrt/winrt.pro b/src/plugins/position/winrt/winrt.pro new file mode 100644 index 0000000..446cb34 --- /dev/null +++ b/src/plugins/position/winrt/winrt.pro @@ -0,0 +1,16 @@ +TARGET = qtposition_winrt + +QT = core core-private positioning + +SOURCES += qgeopositioninfosource_winrt.cpp \ + qgeopositioninfosourcefactory_winrt.cpp +HEADERS += qgeopositioninfosource_winrt_p.h \ + qgeopositioninfosourcefactory_winrt.h + +OTHER_FILES += \ + plugin.json + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryWinRT +msvc:!winrt: LIBS += runtimeobject.lib +load(qt_plugin) diff --git a/src/positioning/doc/qtpositioning.qdocconf b/src/positioning/doc/qtpositioning.qdocconf new file mode 100644 index 0000000..608b30a --- /dev/null +++ b/src/positioning/doc/qtpositioning.qdocconf @@ -0,0 +1,55 @@ +include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) + +project = QtPositioning +description = Qt Positioning Reference Documentation +version = $QT_VERSION + + + +qhp.projects = QtPositioning + +qhp.QtPositioning.file = qtpositioning.qhp +qhp.QtPositioning.namespace = org.qt-project.qtpositioning.$QT_VERSION_TAG +qhp.QtPositioning.virtualFolder = qtpositioning +qhp.QtPositioning.indexTitle = Qt Positioning +qhp.QtPositioning.indexRoot = + +qhp.QtPositioning.filterAttributes = qtpositioning $QT_VERSION qtrefdoc +qhp.QtPositioning.customFilters.Qt.name = QtPositioning $QT_VERSION +qhp.QtPositioning.customFilters.Qt.filterAttributes = qtpositioning $QT_VERSION +qhp.QtPositioning.subprojects = classes qml examples +qhp.QtPositioning.subprojects.classes.title = C++ Classes +qhp.QtPositioning.subprojects.classes.indexTitle = Qt Positioning C++ Classes +qhp.QtPositioning.subprojects.classes.selectors = class fake:headerfile +qhp.QtPositioning.subprojects.classes.sortPages = true +qhp.QtPositioning.subprojects.qml.title = QML Types +qhp.QtPositioning.subprojects.qml.indexTitle = Qt Positioning QML Types +qhp.QtPositioning.subprojects.qml.selectors = qmlclass +qhp.QtPositioning.subprojects.qml.sortPages = true +qhp.QtPositioning.subprojects.examples.title = Qt Positioning Examples +qhp.QtPositioning.subprojects.examples.indexTitle = Qt Positioning Examples +qhp.QtPositioning.subprojects.examples.selectors = fake:example + +tagfile = ../../../doc/qtpositioning/qtpositioning.tags + +depends += qtcore qtdoc qtquick qtqml qtnetwork qtlocation + +headerdirs += .. \ + ../../imports/positioning + +sourcedirs += .. \ + ../../imports/positioning + +examplesinstallpath = positioning + +exampledirs += ../../../examples/positioning \ + snippets/ + + +imagedirs += images + +navigation.landingpage = "Qt Positioning" +navigation.cppclassespage = "Qt Positioning C++ Classes" +navigation.qmltypespage = "Qt Positioning QML Types" + +manifestmeta.thumbnail.names += "QtPositioning/Log File*" diff --git a/src/positioning/doc/snippets/cpp/cpp.pro b/src/positioning/doc/snippets/cpp/cpp.pro new file mode 100644 index 0000000..47401e9 --- /dev/null +++ b/src/positioning/doc/snippets/cpp/cpp.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +TARGET = positioning_cppsnippet +QT = core positioning + +SOURCES += \ + main.cpp \ + cppqml.cpp + diff --git a/src/positioning/doc/snippets/cpp/cppqml.cpp b/src/positioning/doc/snippets/cpp/cppqml.cpp new file mode 100644 index 0000000..5954ecf --- /dev/null +++ b/src/positioning/doc/snippets/cpp/cppqml.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +void cppQmlInterface(QObject *qmlObject) +{ + //! [Address get] + QGeoAddress geoAddress = qmlObject->property("address").value(); + //! [Address get] + + //! [Address set] + qmlObject->setProperty("address", QVariant::fromValue(geoAddress)); + //! [Address set] + + //! [Location get] + QGeoLocation geoLocation = qmlObject->property("location").value(); + //! [Location get] + + //! [Location set] + qmlObject->setProperty("location", QVariant::fromValue(geoLocation)); + //! [Location set] +} + +class MyClass : public QObject +{ + Q_OBJECT +//! [BigBen] +public: + MyClass() : QObject() + { + QGeoAreaMonitorSource *monitor = QGeoAreaMonitorSource::createDefaultSource(this); + if (monitor) { + connect(monitor, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)), + this, SLOT(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo))); + connect(monitor, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo)), + this, SLOT(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo))); + + QGeoAreaMonitorInfo bigBen("Big Ben"); + QGeoCoordinate position(51.50104, -0.124632); + bigBen.setArea(QGeoCircle(position, 100)); + + monitor->startMonitoring(bigBen); + + } else { + qDebug() << "Could not create default area monitor"; + } + } + +public Q_SLOTS: + void areaEntered(const QGeoAreaMonitorInfo &mon, const QGeoPositionInfo &update) + { + Q_UNUSED(mon) + + qDebug() << "Now within 100 meters, current position is" << update.coordinate(); + } + + void areaExited(const QGeoAreaMonitorInfo &mon, const QGeoPositionInfo &update) + { + Q_UNUSED(mon) + + qDebug() << "No longer within 100 meters, current position is" << update.coordinate(); + } +//! [BigBen] +}; diff --git a/src/positioning/doc/snippets/cpp/main.cpp b/src/positioning/doc/snippets/cpp/main.cpp new file mode 100644 index 0000000..7e893f5 --- /dev/null +++ b/src/positioning/doc/snippets/cpp/main.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +int main(int /*argc*/, char ** /*argv*/) +{ + return 0; +} + diff --git a/src/positioning/doc/snippets/doc_src_qtpositioning.qml b/src/positioning/doc/snippets/doc_src_qtpositioning.qml new file mode 100644 index 0000000..1e5e4f9 --- /dev/null +++ b/src/positioning/doc/snippets/doc_src_qtpositioning.qml @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [import] +import QtPositioning 5.2 +//! [import] + +Item { +} + diff --git a/src/positioning/doc/snippets/snippets.pro b/src/positioning/doc/snippets/snippets.pro new file mode 100644 index 0000000..451d1c3 --- /dev/null +++ b/src/positioning/doc/snippets/snippets.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += cpp diff --git a/src/positioning/doc/src/cpp-position.qdoc b/src/positioning/doc/src/cpp-position.qdoc new file mode 100644 index 0000000..34f39bd --- /dev/null +++ b/src/positioning/doc/src/cpp-position.qdoc @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page location-positioning-cpp.html + +\title Positioning (C++) + +\brief The Location Positioning API enables location positioning by means of +GPS or an NMEA data source. + +\section1 Positioning + +The Positioning component of the Qt Location API is about the geographical position, size +and address of some place. Positioning contains a QGeoCoordinate class, containing latitude, longitude and altitude in meters. QGeoLocation contains a QGeoCoordinate plus address +and size information (a bounding box) so that positions can be more than mathematical points. +Movement into or out of the defined bounding box areas can be monitored. The API +also allows the developer to control the source of the positional information +as well. + +Location data involves a precisely specified position on the Earth's +surface \unicode {0x2014} as provided by a latitude-longitude coordinate +\unicode {0x2014} along with associated data, such as: + + \list + \li The date and time at which the position was reported + \li The velocity of the device that reported the position + \li The altitude of the reported position (height above sea level) + \li The bearing of the device in degrees, relative to true north + \endlist + +This data can be extracted through a variety of methods. One of the most +well known methods of positioning is GPS (Global Positioning System), a +publicly available system that uses radiowave signals received from +Earth-orbiting satellites to calculate the precise position and time of +the receiver. Another popular method is 'Cell Identifier Positioning', which uses +the cell identifier of the cell site that is currently serving the receiving +device to calculate its approximate location. These and other positioning +methods can all be used with the Location API; the only requirement for a +location data source within the API is that it provides a +latitude-longitude coordinate with a date/time value, with the option of +providing the other attributes listed above. + + +Location data sources are created by subclassing QGeoPositionInfoSource and +providing QGeoPositionInfo objects through the +QGeoPositionInfoSource::positionUpdated() signal. Clients that require +location data can connect to the +\l{QGeoPositionInfoSource::positionUpdated()}{positionUpdated()} signal and +call \l{QGeoPositionInfoSource::startUpdates()}{startUpdates()} or +\l{QGeoPositionInfoSource::requestUpdate()}{requestUpdate()} to trigger the +distribution of location data. The location data distribution can be stopped by +calling the \l {QGeoPositionInfoSource::stopUpdates()}{stopUpdates()} function. + +A default position source may be available on some platforms. Call +QGeoPositionInfoSource::createDefaultSource() to create an instance of the default +position source; the method returns 0 if no default source is available for +the platform. + +If a problem occurs with access to the information source then an +\l {QGeoPositionInfoSource::error()}{error()} signal is emitted. + +The QGeoAreaMonitorSource class enables client applications to be notified when +the receiving device has moved in or out of a particular area, as specified +by a coordinate and radius. If the platform provides built-in support for +area monitoring, QGeoAreaMonitorSource::createDefaultMonitor() returns an instance of +the default area monitor. + +Satellite information can also be distributed through the +QGeoSatelliteInfoSource class. Call QGeoSatelliteInfoSource::createDefaultSource() to +create an instance of the default satellite data source for the platform, +if one is available. Alternatively, clients can subclass it to provide a +custom satellite data source. + + + +\section2 Requesting Location Data from Data Sources + +To receive data from a source, connect to its +\l{QGeoPositionInfoSource::positionUpdated()}{positionUpdated()} signal, +then call either \l{QGeoPositionInfoSource::startUpdates()}{startUpdates()} +or \l{QGeoPositionInfoSource::requestUpdate()}{requestUpdate()} to begin. + +Here is an example of a client that receives data from the default location +data source, as returned by QGeoPositionInfoSource::createDefaultSource(): + +\code +class MyClass : public QObject +{ + Q_OBJECT +public: + MyClass(QObject *parent = 0) + : QObject(parent) + { + QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource(this); + if (source) { + connect(source, SIGNAL(positionUpdated(QGeoPositionInfo)), + this, SLOT(positionUpdated(QGeoPositionInfo))); + source->startUpdates(); + } + } + +private slots: + void positionUpdated(const QGeoPositionInfo &info) + { + qDebug() << "Position updated:" << info; + } +}; + +\endcode + +\section2 Controlling Aspects of Data Sources + +The QGeoPositionInfoSource::setUpdateInterval() method can be used to +control the rate at which position updates are received. For example, if +the client application only requires updates once every 30 seconds, it can +call \c setUpdateInterval(30000). (If no update interval is set, or +\l {QGeoPositionInfoSource::}{setUpdateInterval()} is called with a value of 0, the source uses a default +interval or some other internal logic to determine when updates should be +provided.) + +QGeoPositionInfoSource::setPreferredPositioningMethods() enables client +applications to request that a certain type of positioning method be used. +For example, if the application prefers to use only satellite positioning, +which offers fairly precise outdoor positioning but can be a heavy user of +power resources, it can call this method with the +QGeoPositionInfoSource::SatellitePositioningMethods value. However, this +method should only be used in specialized client applications; in most +cases, the default positioning methods should not be changed, as a source +may internally use a variety of positioning methods that can be useful to +the application. + +\section2 NMEA Data + +\l {http://en.wikipedia.org/wiki/NMEA_0183}{NMEA} is a common text-based +protocol for specifying navigational data. For convenience, the +QNmeaPositionInfoSource is provided to enable client applications to read +and distribute NMEA data in either real-time mode (for example, when +streaming from a GPS device) or simulation mode (for example, when reading +from a NMEA log file). In simulation mode, the source will emit updates +according to the time stamp of each NMEA sentence to produce a "replay" +of the recorded data. + +Generally, the capabilities provided by the default position source as +returned by QGeoPositionInfoSource::createDefaultSource(), along with the +QNmeaPositionInfoSource class, are sufficient for retrieving location +data. However, in some cases developers may wish to write their own custom +location data source. + +The \l {Log File Position Source (C++)} example demonstrates how to subclass QGeoPositionInfoSource +to create a custom positioning source. + + +\section1 Examples + +\section3 \b{Flickr Example} + +The \l{GeoFlickr QML}{Flickr Example} uses the current location to download thumbnail +images from Flickr relevant to the current location. + + + +\section1 Positioning Classes + +\annotatedlist QtPositioning-positioning + +*/ diff --git a/src/positioning/doc/src/cpp-qml-positioning.qdoc b/src/positioning/doc/src/cpp-qml-positioning.qdoc new file mode 100644 index 0000000..9245c17 --- /dev/null +++ b/src/positioning/doc/src/cpp-qml-positioning.qdoc @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page positioning-cpp-qml.html +\title Interfaces between C++ and QML Code in Qt Positioning + +\brief Some of the providing QtPositioning QML types providing interfaces to access and modify properties in C++. + +\section1 Overview + +Depending on the type of C++ class QtPositioning utilizes two methods to simplify +exchange of position data between C++ and QML code. + +\target Cpp_value_integration_positioning +\section1 Direct C++ Value Integration in QtPositioning + +Starting with Qt 5.5, it has become much easier to integrate non-QObject based +data types into QML. This is achieved by adding \l Q_GADGET support to QtQml. +The macro converts classes into a light-weight +version of a QObject without the required \l QObject inheritance. At the same time +it retains the reflection capabilities of \l QMetaObject. As a result they can be directly +exposed to QML and do not require any further wrapper classes. + +A significant number of Position and Location +related data types were converted to Q_GADGETs. They retain their API and value +type character but have become introspectable via \l QMetaObject. This conversion +was done to the following classes: + +\list +\li \l QGeoCircle +\li \l QGeoCoordinate +\li \l QGeoRectangle +\li \l QGeoShape +\endlist + +Using \l QGeoCoordinate as an example, the C++ types are directly exposed to the +QML environment via its meta type: + +\code + qRegisterMetaType(); + QMetaType::registerEqualsComparator(); +\endcode + +The above registration of \l QGeoCoordinate is automatically done once by the +QtPositioning QML plugin. The \l{Plane Spotter (QML)}{Plane Spotter} example demonstrates +this feature. + +\section1 QVariant Based integration + +This section provides information on how to integrate QGeoAddress and QGeoLocation. + +\section2 Address - QGeoAddress +The \l {QtPositioning::Address::address} {Address.address} property is used to provide an interface between C++ and QML code. First a pointer to a +Address object must be obtained from C++, then use the \l {QObject::property()}{property()} and +\l {QObject::setProperty()}{setProperty()} functions to get and set the \c address property. +The following gets the QGeoAddress representing this object from C++: +\snippet cpp/cppqml.cpp Address get +The following sets the properties of this object based on a QGeoAddress object from C++: +\snippet cpp/cppqml.cpp Address set + + +\section2 Location - QGeoLocation +The \l {Location::location} {Location.location} property is used to provide an interface between C++ and QML code. First a pointer to a +Location object must be obtained from C++, then use the \l {QObject::property()}{property()} and +\l {QObject::setProperty()}{setProperty()} functions to get and set the \c location property. +The following gets the QGeoLocation representing this object from C++: +\snippet cpp/cppqml.cpp Location get +The following sets the properties of this object based on a QGeoLocation object from C++: +\snippet cpp/cppqml.cpp Location set + +*/ diff --git a/src/positioning/doc/src/qml-position.qdoc b/src/positioning/doc/src/qml-position.qdoc new file mode 100644 index 0000000..4b338fd --- /dev/null +++ b/src/positioning/doc/src/qml-position.qdoc @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page location-positioning-qml.html + +\title Positioning (QML) + +\brief The Location Positioning API enables location positioning by means of +GPS or an NMEA data source. + +\section1 Location Positioning + +Location data involves a precisely specified position on the Earth's +surface \unicode {0x2014} as provided by a latitude-longitude coordinate +\unicode {0x2014} along with associated data, such as: + + \list + \li The date and time at which the position was reported + \li The velocity of the device that reported the position + \li The altitude of the reported position (height above sea level) + \li The bearing of the device in degrees, relative to true north + \endlist + +For more information see +\l {http://en.wikipedia.org/wiki/Geographic_coordinate}{Geographic Coordinate}. + +This data can be extracted through a variety of methods. One of the most +well known methods of positioning is GPS (Global Positioning System), a +publicly available system that uses radiowave signals received from +Earth-orbiting satellites to calculate the precise position and time of +the receiver. Another popular method is 'Cell Identifier Positioning', which uses +the cell identifier of the cell site that is currently serving the receiving +device to calculate its approximate location. These and other positioning +methods can all be used with the Location API; the only requirement for a +location data source within the API is that it provides a +latitude-longitude coordinate with a date/time value, with the option of +providing the other attributes listed above. + +\section2 Coordinate + +The \l {coordinate} is a basic unit of geographical information. The +\l {coordinate} type has attributes to hold the \c {latitude}, +\c longitude and \c altitude. + +\section2 Position + +The three dimensional position of an object such as a mobile device can be specified by giving +the latitude, longitude and altitude. That is the values held in the +l\ {coordinate} type. Additionally for computation of future +positions we would like to know if the object is moving, what \l {Position::speed}{speed} it is +doing and what is the \l {Position::timestamp}{timestamp} of the last position data. Position +therefore includes values for the \l {Position::coordinate}{coordinate}, +\l {Position::speed}{speed} and a \l {Position::timestamp}{timestamp}. \l Position also takes +responsibility for validation of sensible values for these properties. These are exposed as +the \l {Position::latitudeValid}{latitudeValid}, \l {Position::longitudeValid}{longitudeValid}, +\l {Position::altitudeValid}{altitudeValid}, \l {Position::speedValid}{speedValid}, +\l {Position::horizontalAccuracyValid}{horizontalAccuracyValid}, and +\l {Position::verticalAccuracyValid}{verticalAccuracyValid} properties. + + +\section2 PositionSource + +We have a Position type, a \l {coordinate} type but where does the data come from? +Also it is a good idea to be able to indicate alternative sources. +Perhaps instead of directly picking up GPS satellites it might be desirable to do +some testing using a datafile. + +The \l PositionSource type provides the developer with control, +within the limits allowed by the platform, of the source of the +geographical data. Apart from tradtional sources such as GPS and cell data the positional data can be +sourced from a logfile which is in NMEA format. + +\l {http://en.wikipedia.org/wiki/NMEA}{NMEA} is a common text-based +protocol for specifying navigational data. For convenience, the \l +{PositionSource::nmeaSource}{nmeaSource} property is provided to enable +QML applications to read NMEA data from a log file or a TCP socket, the +source will emit updates according to the time stamp of each NMEA sentence +to produce a "replay" of the recorded data. To use a TCP socket set the +"socket" uri scheme. + +\code +PositionSource { + nmeaSource: "socket://127.0.0.1:12345" +} +\endcode + + + +\section2 \b{GeoFlickr Example} + +The \l{GeoFlickr (QML)}{GeoFlickr Example} uses the Location to download thumbnail +images from Flickr relevant to the current location. + +*/ diff --git a/src/positioning/doc/src/qtpositioning-examples.qdoc b/src/positioning/doc/src/qtpositioning-examples.qdoc new file mode 100644 index 0000000..57d129a --- /dev/null +++ b/src/positioning/doc/src/qtpositioning-examples.qdoc @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \group qtpositioning-examples + \title Qt Positioning Examples + \brief Examples for the Qt Positioning module + \ingroup all-examples + \ingroup qtpositioning + + These are the \l{Qt Positioning} examples. + +*/ diff --git a/src/positioning/doc/src/qtpositioning-plugins.qdoc b/src/positioning/doc/src/qtpositioning-plugins.qdoc new file mode 100644 index 0000000..4a56b65 --- /dev/null +++ b/src/positioning/doc/src/qtpositioning-plugins.qdoc @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page qtpositioning-plugins.html +\title Qt Positioning service plugins +\brief Implementing Qt Positioning plugins + +Qt Positioning provides the majority of its functionality through plugins. This +document outlines how to develop a new position plugin. + +\section1 Plugin Description + +Each plugin is described by a json file. The json describes the plugins capabilities and +version. Below is an example of a json file used by the postionpoll plugin: + +\quotefile ../../../plugins/position/positionpoll/plugin.json + +The entries have the following meaning: + +\table + \header + \li Key + \li Description + \row + \li Keys + \li The unique name/key of the plugin. Each position plugin must have a unique name. + \row + \li Provider + \li The provider name of the services. Multiple plugins may have the same name. + In such cases the Version string will be used to further distinguish the plugins. + \row + \li Position + \li Set to \c true if the plugin implements a \l QGeoPositionInfoSource. + \row + \li Satellite + \li Set to \c true if the plugin implements a \l QGeoSatelliteInfoSource. + \row + \li Monitor + \li Set to \c true if the plugin implements a \l QGeoAreaMonitorSource. + \row + \li Priority + \li The plugin priority. If multiple plugins have the same provider name, the plugin + with the higest priority will be used. +\endtable + +\section1 Implementing Plugins + +A plugin implementer needs to subclass \l QGeoPositionInfoSourceFactory and override one or more of +its functions. If a plugin does not support a specific feature the function should return 0 or +utilize the default implementation. + +\list + \li \l QGeoPositionInfoSourceFactory::areaMonitor() + \li \l QGeoPositionInfoSourceFactory::positionInfoSource() + \li \l QGeoPositionInfoSourceFactory::satelliteInfoSource() +\endlist +*/ diff --git a/src/positioning/doc/src/qtpositioning-qml.qdoc b/src/positioning/doc/src/qtpositioning-qml.qdoc new file mode 100644 index 0000000..0c94777 --- /dev/null +++ b/src/positioning/doc/src/qtpositioning-qml.qdoc @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \qmlmodule QtPositioning 5.2 + \title Qt Positioning QML Types + \ingroup qmlmodules + \brief Provides QML types for position information + +\section1 Overview + +The identifying string for this module is \e QtPositioning. To use include the following import +statement in the QML file. + +\snippet doc_src_qtpositioning.qml import + +\section2 Positioning QML Concepts + +Position information can come from a variety of sources including satellites, +wifi, text files and so on. The position is described by the latitude, +the longitude, and the altitude in meters. For more information see +\l {http://en.wikipedia.org/wiki/Geographic_coordinate}{Geographic Coordinate}. + +The QML position is stored in a \l {coordinate} which contains the +latitude, longitude and altitude of the device. The \l {QtPositioning::Location}{Location} contains +this \l {coordinate} and adds an address, it also has a bounding box which +defines the recommended viewing region when displaying the location. + +Now that the device has a position, with regular updates the API can determine +the speed and heading of the device. It can also define a box or a circle that can +produce a notification when the device either leaves or enters that region. + +More detailed information retrieving the current position can be found under +\l {Positioning (QML)}{Location Positioning via QML} + +\section1 Basic Types + +\annotatedlist qml-QtPositioning5-basictypes + +\section1 Alphabetical Listing of All QML Types +*/ diff --git a/src/positioning/doc/src/qtpositioning.qdoc b/src/positioning/doc/src/qtpositioning.qdoc new file mode 100644 index 0000000..d5b0eb3 --- /dev/null +++ b/src/positioning/doc/src/qtpositioning.qdoc @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \module QtPositioning + \title Qt Positioning C++ Classes + \ingroup modules + \qtvariable positioning + + \brief The Positioning module provides positioning information via QML and C++ interfaces. + + To load the Qt Positioning module, add the following statement to your .qml files + + \snippet doc_src_qtpositioning.qml import + + For C++ projects include the header appropriate for the current use case, + for example applications using routes may use + + \code #include \endcode + + The .pro file should have the \e positioning keyword added + + \code QT += positioning \endcode + + + See more in the \l{Qt Positioning}{Qt Positioning Overview}. + +*/ + + + +/*! +\page qtpositioning-index.html +\title Qt Positioning +\brief The Qt Positioning API provides positioning information via QML and C++ interfaces. +\ingroup technology-apis + +The Qt Positioning API provides positioning information via QML and C++ interfaces. + +Currently the API is supported on \l {Qt for Android}{Android}, \l {Qt for iOS}{iOS}, +\l {Qt for macOS}{\macos}, +\l {Qt for Linux/X11}{Linux} (using +\l {http://www.freedesktop.org/wiki/Software/GeoClue}{GeoClue version 0.12.99}), +\l {Qt for Windows}{Windows} (with GPS receivers exposed as a serial port providing NMEA sentences), +and \l {Qt for WinRT}{WinRT} (using Windows.Devices.Geolocation). + +\section1 Overview + +The Qt Positioning API gives developers the ability to determine a position by +using a variety of possible sources, including satellite, or wifi, or text file, +and so on. That information can then be used to for example determine a position +on a map. In addition satellite information can be retrieved and area based monitoring +can be performed. + +\section1 Getting Started + +To load the Qt Positioning module, add the following statement to your .qml files + +\snippet doc_src_qtpositioning.qml import + +For C++ projects include the header appropriate for the current use case, +for example applications using routes may use + +\code #include \endcode + +The .pro file should have the \e positioning keyword added + +\code QT += positioning \endcode + +\section1 Related Information +\section2 Overview + +Positioning includes all the functionality necessary to find and work with geographic +coordinates. It can use a variety of external sources of information, including GPS. This +provides us with a coordinate and altitude for the device with additional features +such as speed and direction. This provides the fundamental location information used in the API. + +\section2 References +\table +\row + \li Positioning introduction: + \li \l{Positioning (QML)}{for QML} + \li \l{Positioning (C++)}{for C++} +\row + \li API references: + \li \l {Qt Positioning QML Types}{for QML} + \li \l {Qt Positioning C++ Classes}{for C++} +\row + \li Position plugins: + \li \l {Qt Positioning service plugins} +\endtable + +\section2 Examples + +\list + \li \l {GeoFlickr (QML)} + \li \l {Log File Position Source (C++)} + \li \l {SatelliteInfo (C++/QML)} + \li \l {Weather Info (C++/QML)} +\endlist +*/ diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro new file mode 100644 index 0000000..3cc059c --- /dev/null +++ b/src/positioning/positioning.pro @@ -0,0 +1,81 @@ +TARGET = QtPositioning +QT = core-private + +QMAKE_DOCS = $$PWD/doc/qtpositioning.qdocconf +OTHER_FILES += doc/src/*.qdoc # show .qdoc files in Qt Creator + +ANDROID_BUNDLED_JAR_DEPENDENCIES = \ + jar/QtPositioning-bundled.jar:org.qtproject.qt5.android.positioning.QtPositioning +ANDROID_JAR_DEPENDENCIES = \ + jar/QtPositioning.jar:org.qtproject.qt5.android.positioning.QtPositioning +ANDROID_PERMISSIONS = \ + android.permission.ACCESS_FINE_LOCATION +ANDROID_LIB_DEPENDENCIES = \ + plugins/position/libqtposition_android.so +MODULE_WINRT_CAPABILITIES_DEVICE += \ + location +MODULE_PLUGIN_TYPES = \ + position + +PUBLIC_HEADERS += \ + qgeoaddress.h \ + qgeoareamonitorinfo.h \ + qgeoareamonitorsource.h \ + qgeoshape.h \ + qgeorectangle.h \ + qgeocircle.h \ + qgeocoordinate.h \ + qgeolocation.h \ + qgeopositioninfo.h \ + qgeopositioninfosource.h \ + qgeosatelliteinfo.h \ + qgeosatelliteinfosource.h \ + qnmeapositioninfosource.h \ + qgeopositioninfosourcefactory.h \ + qpositioningglobal.h + +PRIVATE_HEADERS += \ + qgeoaddress_p.h \ + qgeoshape_p.h \ + qgeorectangle_p.h \ + qgeocircle_p.h \ + qgeolocation_p.h \ + qlocationutils_p.h \ + qnmeapositioninfosource_p.h \ + qgeocoordinate_p.h \ + qgeopositioninfosource_p.h \ + qdeclarativegeoaddress_p.h \ + qdeclarativegeolocation_p.h \ + qdoublevector2d_p.h \ + qdoublevector3d_p.h \ + qgeoprojection_p.h \ + qpositioningglobal_p.h \ + qlocationdata_simulator_p.h + +SOURCES += \ + qgeoaddress.cpp \ + qgeoareamonitorsource.cpp \ + qgeoareamonitorinfo.cpp \ + qgeoshape.cpp \ + qgeorectangle.cpp \ + qgeocircle.cpp \ + qgeocoordinate.cpp \ + qgeolocation.cpp \ + qgeopositioninfo.cpp \ + qgeopositioninfosource.cpp \ + qgeosatelliteinfo.cpp \ + qgeosatelliteinfosource.cpp \ + qlocationutils.cpp \ + qnmeapositioninfosource.cpp \ + qgeopositioninfosourcefactory.cpp \ + qdeclarativegeoaddress.cpp \ + qdeclarativegeolocation.cpp \ + qdoublevector2d.cpp \ + qdoublevector3d.cpp \ + qgeoprojection.cpp \ + qlocationdata_simulator.cpp + +HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS + + +load(qt_module) diff --git a/src/positioning/qdeclarativegeoaddress.cpp b/src/positioning/qdeclarativegeoaddress.cpp new file mode 100644 index 0000000..476fcac --- /dev/null +++ b/src/positioning/qdeclarativegeoaddress.cpp @@ -0,0 +1,355 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +***************************************************************************/ + +#include "qdeclarativegeoaddress_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Address + \instantiates QDeclarativeGeoAddress + \inqmlmodule QtPositioning + \since 5.2 + + \brief The Address QML type represents a specific location as a street address. + + An Address is used as a unit of data for queries such as (Reverse) Geocoding + or Places searches -- many of these operations either accept an Address + or return one. + + Not all properties of an Address are necessarily available or relevant + in all parts of the world and all locales. The \l district, \l state and + \l county properties are particularly area-specific for many data sources, + and often only one or two of these are available or useful. + + The Address has a \l text property which holds a formatted string. It + is the recommended way to display an address to the user and typically + takes the format of an address as found on an envelope, but this is not always + the case. The \l text may be automatically generated from constituent + address properties such as \l street, \l city and and so on, but can also + be explicitly assigned. See \l text for details. + + \section2 Example Usage + + The following code snippet shows the declaration of an Address object. + + \code + Address { + id: address + street: "53 Brandl St" + city: "Eight Mile Plains" + country: "Australia" + countryCode: "AUS" + } + \endcode + + This could then be used, for example, as the value of a geocoding query, + to get an exact longitude and latitude for the address. + + \sa {QGeoAddress} +*/ + +QDeclarativeGeoAddress::QDeclarativeGeoAddress(QObject *parent) : + QObject(parent) +{ +} + +QDeclarativeGeoAddress::QDeclarativeGeoAddress(const QGeoAddress &address, QObject *parent) : + QObject(parent), m_address(address) +{ +} + +/*! + \qmlproperty QGeoAddress QtPositioning::Address::address + + For details on how to use this property to interface between C++ and QML see + "\l {Address - QGeoAddress} {Interfaces between C++ and QML Code}". +*/ +QGeoAddress QDeclarativeGeoAddress::address() const +{ + return m_address; +} + +void QDeclarativeGeoAddress::setAddress(const QGeoAddress &address) +{ + // Elaborate but takes care of emiting needed signals + setText(address.text()); + setCountry(address.country()); + setCountryCode(address.countryCode()); + setState(address.state()); + setCounty(address.county()); + setCity(address.city()); + setDistrict(address.district()); + setStreet(address.street()); + setPostalCode(address.postalCode()); + m_address = address; +} + +/*! + \qmlproperty string QtPositioning::Address::text + + This property holds the address as a single formatted string. It is the recommended + string to use to display the address to the user. It typically takes the format of + an address as found on an envelope, but this is not always necessarily the case. + + The address \c text is either automatically generated or explicitly assigned, + this can be determined by checking \l isTextGenerated. + + If an empty string is assigned to \c text, then \l isTextGenerated will be set + to true and \c text will return a string which is locally formatted according to + \l countryCode and based on the properties of the address. Modifying the address + properties such as \l street, \l city and so on may cause the contents of \c text to + change. + + If a non-empty string is assigned to \c text, then \l isTextGenerated will be + set to false and \c text will always return the explicitly assigned string. + Modifying address properties will not affect the \c text property. +*/ +QString QDeclarativeGeoAddress::text() const +{ + return m_address.text(); +} + +void QDeclarativeGeoAddress::setText(const QString &address) +{ + QString oldText = m_address.text(); + bool oldIsTextGenerated = m_address.isTextGenerated(); + m_address.setText(address); + + if (oldText != m_address.text()) + emit textChanged(); + if (oldIsTextGenerated != m_address.isTextGenerated()) + emit isTextGeneratedChanged(); +} + +/*! + \qmlproperty string QtPositioning::Address::country + + This property holds the country of the address as a single formatted string. +*/ +QString QDeclarativeGeoAddress::country() const +{ + return m_address.country(); +} + +void QDeclarativeGeoAddress::setCountry(const QString &country) +{ + if (m_address.country() == country) + return; + QString oldText = m_address.text(); + m_address.setCountry(country); + emit countryChanged(); + + if (m_address.isTextGenerated() && oldText != m_address.text()) + emit textChanged(); +} + +/*! + \qmlproperty string QtPositioning::Address::countryCode + + This property holds the country code of the address as a single formatted string. +*/ +QString QDeclarativeGeoAddress::countryCode() const +{ + return m_address.countryCode(); +} + +void QDeclarativeGeoAddress::setCountryCode(const QString &countryCode) +{ + if (m_address.countryCode() == countryCode) + return; + QString oldText = m_address.text(); + m_address.setCountryCode(countryCode); + emit countryCodeChanged(); + + if (m_address.isTextGenerated() && oldText != m_address.text()) + emit textChanged(); +} + +/*! + \qmlproperty string QtPositioning::Address::state + + This property holds the state of the address as a single formatted string. +*/ +QString QDeclarativeGeoAddress::state() const +{ + return m_address.state(); +} + +void QDeclarativeGeoAddress::setState(const QString &state) +{ + if (m_address.state() == state) + return; + QString oldText = m_address.text(); + m_address.setState(state); + emit stateChanged(); + + if (m_address.isTextGenerated() && oldText != m_address.text()) + emit textChanged(); +} + +/*! + \qmlproperty string QtPositioning::Address::county + + This property holds the county of the address as a single formatted string. +*/ +QString QDeclarativeGeoAddress::county() const +{ + return m_address.county(); +} + +void QDeclarativeGeoAddress::setCounty(const QString &county) +{ + if (m_address.county() == county) + return; + QString oldText = m_address.text(); + m_address.setCounty(county); + emit countyChanged(); + + if (m_address.isTextGenerated() && oldText != m_address.text()) + emit textChanged(); +} + +/*! + \qmlproperty string QtPositioning::Address::city + + This property holds the city of the address as a single formatted string. +*/ +QString QDeclarativeGeoAddress::city() const +{ + return m_address.city(); +} + +void QDeclarativeGeoAddress::setCity(const QString &city) +{ + if (m_address.city() == city) + return; + QString oldText = m_address.text(); + m_address.setCity(city); + emit cityChanged(); + + if (m_address.isTextGenerated() && oldText != m_address.text()) + emit textChanged(); +} + +/*! + \qmlproperty string QtPositioning::Address::district + + This property holds the district of the address as a single formatted string. +*/ +QString QDeclarativeGeoAddress::district() const +{ + return m_address.district(); +} + +void QDeclarativeGeoAddress::setDistrict(const QString &district) +{ + if (m_address.district() == district) + return; + QString oldText = m_address.text(); + m_address.setDistrict(district); + emit districtChanged(); + + if (m_address.isTextGenerated() && oldText != m_address.text()) + emit textChanged(); +} + +/*! + \qmlproperty string QtPositioning::Address::street + + This property holds the street of the address but + may also contain things like a unit number, a building + name, or anything else that might be used to + distinguish one address from another. +*/ +QString QDeclarativeGeoAddress::street() const +{ + return m_address.street(); +} + +void QDeclarativeGeoAddress::setStreet(const QString &street) +{ + if (m_address.street() == street) + return; + QString oldText = m_address.text(); + m_address.setStreet(street); + emit streetChanged(); + + if (m_address.isTextGenerated() && oldText != m_address.text()) + emit textChanged(); +} + +/*! + \qmlproperty string QtPositioning::Address::postalCode + + This property holds the postal code of the address as a single formatted string. +*/ +QString QDeclarativeGeoAddress::postalCode() const +{ + return m_address.postalCode(); +} + +void QDeclarativeGeoAddress::setPostalCode(const QString &postalCode) +{ + if (m_address.postalCode() == postalCode) + return; + QString oldText = m_address.text(); + m_address.setPostalCode(postalCode); + emit postalCodeChanged(); + + if (m_address.isTextGenerated() && oldText != m_address.text()) + emit textChanged(); +} + +/*! + \qmlproperty bool QtPositioning::Address::isTextGenerated + + This property holds a boolean that if true, indicates that \l text is automatically + generated from address properties. If false, it indicates that the \l text has been + explicitly assigned. + +*/ +bool QDeclarativeGeoAddress::isTextGenerated() const +{ + return m_address.isTextGenerated(); +} + +#include "moc_qdeclarativegeoaddress_p.cpp" + +QT_END_NAMESPACE diff --git a/src/positioning/qdeclarativegeoaddress_p.h b/src/positioning/qdeclarativegeoaddress_p.h new file mode 100644 index 0000000..3285cea --- /dev/null +++ b/src/positioning/qdeclarativegeoaddress_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +***************************************************************************/ + +#ifndef QDECLARATIVEGEOADDRESS_P_H +#define QDECLARATIVEGEOADDRESS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_POSITIONING_EXPORT QDeclarativeGeoAddress : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QGeoAddress address READ address WRITE setAddress) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + Q_PROPERTY(QString country READ country WRITE setCountry NOTIFY countryChanged) + Q_PROPERTY(QString countryCode READ countryCode WRITE setCountryCode NOTIFY countryCodeChanged) + Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged) + Q_PROPERTY(QString county READ county WRITE setCounty NOTIFY countyChanged) + Q_PROPERTY(QString city READ city WRITE setCity NOTIFY cityChanged) + Q_PROPERTY(QString district READ district WRITE setDistrict NOTIFY districtChanged) + Q_PROPERTY(QString street READ street WRITE setStreet NOTIFY streetChanged) + Q_PROPERTY(QString postalCode READ postalCode WRITE setPostalCode NOTIFY postalCodeChanged) + Q_PROPERTY(bool isTextGenerated READ isTextGenerated NOTIFY isTextGeneratedChanged) + +public: + explicit QDeclarativeGeoAddress(QObject *parent = 0); + QDeclarativeGeoAddress(const QGeoAddress &address, QObject *parent = 0); + QGeoAddress address() const; + void setAddress(const QGeoAddress &address); + + QString text() const; + void setText(const QString &address); + + QString country() const; + void setCountry(const QString &country); + QString countryCode() const; + void setCountryCode(const QString &countryCode); + QString state() const; + void setState(const QString &state); + QString county() const; + void setCounty(const QString &county); + QString city() const; + void setCity(const QString &city); + QString district() const; + void setDistrict(const QString &district); + QString street() const; + void setStreet(const QString &street); + QString postalCode() const; + void setPostalCode(const QString &postalCode); + bool isTextGenerated() const; + +Q_SIGNALS: + void textChanged(); + void countryChanged(); + void countryCodeChanged(); + void stateChanged(); + void countyChanged(); + void cityChanged(); + void districtChanged(); + void streetChanged(); + void postalCodeChanged(); + void isTextGeneratedChanged(); + +private: + QGeoAddress m_address; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEGEOADDRESS_P_H diff --git a/src/positioning/qdeclarativegeolocation.cpp b/src/positioning/qdeclarativegeolocation.cpp new file mode 100644 index 0000000..9e3b71e --- /dev/null +++ b/src/positioning/qdeclarativegeolocation.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeolocation_p.h" + +QT_USE_NAMESPACE + +/*! + \qmltype Location + \instantiates QDeclarativeGeoLocation + \inqmlmodule QtPositioning + \since 5.2 + + \brief The Location type holds location data. + + Location types represent a geographic "location", in a human sense. This + consists of a specific \l {coordinate}, an \l {address} and a \l {boundingBox}{bounding box}. + The \l {boundingBox}{bounding box} represents the recommended region + to display when viewing this location. + + The Location type is most commonly seen as the contents of a search + model such as the GeocodeModel. When a GeocodeModel returns the list of + locations found for a given query, it represents these as Location objects. + + \section2 Example Usage + + The following example shows a simple Location object being declared: + + \code + Location { + coordinate { + latitude: -27.3 + longitude: 153.1 + } + address: Address { + ... + } + } + \endcode +*/ + +QDeclarativeGeoLocation::QDeclarativeGeoLocation(QObject *parent) +: QObject(parent), m_address(0) + +{ + setLocation(QGeoLocation()); +} + +QDeclarativeGeoLocation::QDeclarativeGeoLocation(const QGeoLocation &src, QObject *parent) +: QObject(parent), m_address(0) +{ + setLocation(src); +} + +QDeclarativeGeoLocation::~QDeclarativeGeoLocation() +{ +} + +/*! + \qmlproperty QGeoLocation QtPositioning::Location::location + + For details on how to use this property to interface between C++ and QML see + "\l {Location - QGeoLocation} {Interfaces between C++ and QML Code}". +*/ +void QDeclarativeGeoLocation::setLocation(const QGeoLocation &src) +{ + if (m_address && m_address->parent() == this) { + m_address->setAddress(src.address()); + } else if (!m_address || m_address->parent() != this) { + m_address = new QDeclarativeGeoAddress(src.address(), this); + emit addressChanged(); + } + + setCoordinate(src.coordinate()); + setBoundingBox(src.boundingBox()); +} + +QGeoLocation QDeclarativeGeoLocation::location() const +{ + QGeoLocation retValue; + retValue.setAddress(m_address ? m_address->address() : QGeoAddress()); + retValue.setCoordinate(m_coordinate); + retValue.setBoundingBox(m_boundingBox); + return retValue; +} + +/*! + \qmlproperty Address QtPositioning::Location::address + + This property holds the address of the location which can be use to retrieve address details of the location. +*/ +void QDeclarativeGeoLocation::setAddress(QDeclarativeGeoAddress *address) +{ + if (m_address == address) + return; + + if (m_address && m_address->parent() == this) + delete m_address; + + m_address = address; + emit addressChanged(); +} + +QDeclarativeGeoAddress *QDeclarativeGeoLocation::address() const +{ + return m_address; +} + +/*! + \qmlproperty coordinate QtPositioning::Location::coordinate + + This property holds the exact geographical coordinate of the location which can be used to retrieve the latitude, longitude and altitude of the location. + + \note this property's changed() signal is currently emitted only if the + whole object changes, not if only the contents of the object change. +*/ +void QDeclarativeGeoLocation::setCoordinate(const QGeoCoordinate coordinate) +{ + if (m_coordinate == coordinate) + return; + + m_coordinate = coordinate; + emit coordinateChanged(); +} + +QGeoCoordinate QDeclarativeGeoLocation::coordinate() const +{ + return m_coordinate; +} + +/*! + \qmlproperty georectangle QtPositioning::Location::boundingBox + + This property holds the recommended region to use when displaying the location. + For example, a building's location may have a region centered around the building, + but the region is large enough to show it's immediate surrounding geographical + context. + + Note: this property's changed() signal is currently emitted only if the + whole object changes, not if only the contents of the object change. +*/ +void QDeclarativeGeoLocation::setBoundingBox(const QGeoRectangle &boundingBox) +{ + if (m_boundingBox == boundingBox) + return; + + m_boundingBox = boundingBox; + emit boundingBoxChanged(); +} + +QGeoRectangle QDeclarativeGeoLocation::boundingBox() const +{ + return m_boundingBox; +} diff --git a/src/positioning/qdeclarativegeolocation_p.h b/src/positioning/qdeclarativegeolocation_p.h new file mode 100644 index 0000000..b208e50 --- /dev/null +++ b/src/positioning/qdeclarativegeolocation_p.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOLOCATION_P_H +#define QDECLARATIVEGEOLOCATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_POSITIONING_EXPORT QDeclarativeGeoLocation : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QGeoLocation location READ location WRITE setLocation) + Q_PROPERTY(QDeclarativeGeoAddress *address READ address WRITE setAddress NOTIFY addressChanged) + Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged) + Q_PROPERTY(QGeoRectangle boundingBox READ boundingBox WRITE setBoundingBox NOTIFY boundingBoxChanged) + +public: + explicit QDeclarativeGeoLocation(QObject *parent = 0); + explicit QDeclarativeGeoLocation(const QGeoLocation &src, QObject *parent = 0); + ~QDeclarativeGeoLocation(); + + QGeoLocation location() const; + void setLocation(const QGeoLocation &src); + + QDeclarativeGeoAddress *address() const; + void setAddress(QDeclarativeGeoAddress *address); + QGeoCoordinate coordinate() const; + void setCoordinate(const QGeoCoordinate coordinate); + + QGeoRectangle boundingBox() const; + void setBoundingBox(const QGeoRectangle &boundingBox); + +Q_SIGNALS: + void addressChanged(); + void coordinateChanged(); + void boundingBoxChanged(); + +private: + QDeclarativeGeoAddress *m_address; + QGeoRectangle m_boundingBox; + QGeoCoordinate m_coordinate; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVELOCATION_P_H diff --git a/src/positioning/qdoublevector2d.cpp b/src/positioning/qdoublevector2d.cpp new file mode 100644 index 0000000..c18f236 --- /dev/null +++ b/src/positioning/qdoublevector2d.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QDoubleVector2D::QDoubleVector2D(const QDoubleVector3D &vector) : + xp(vector.xp), yp(vector.yp) +{ +} + +double QDoubleVector2D::length() const +{ + return qSqrt(xp * xp + yp * yp); +} + +QDoubleVector2D QDoubleVector2D::normalized() const +{ + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp); + if (qFuzzyIsNull(len - 1.0)) + return *this; + else if (!qFuzzyIsNull(len)) + return *this / (double)qSqrt(len); + else + return QDoubleVector2D(); +} + +void QDoubleVector2D::normalize() +{ + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp); + if (qFuzzyIsNull(len - 1.0) || qFuzzyIsNull(len)) + return; + + len = qSqrt(len); + + xp /= len; + yp /= len; +} + +QDoubleVector3D QDoubleVector2D::toVector3D() const +{ + return QDoubleVector3D(xp, yp, 0.0); +} + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<(QDebug dbg, const QDoubleVector2D &vector) +{ + QDebugStateSaver saver(dbg); + dbg.nospace() << "QDoubleVector2D(" << vector.x() << ", " << vector.y() << ')'; + return dbg; +} + +#endif + +#ifndef QT_NO_DATASTREAM + +QDataStream &operator<<(QDataStream &stream, const QDoubleVector2D &vector) +{ + stream << double(vector.x()) << double(vector.y()); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QDoubleVector2D &vector) +{ + double x, y; + stream >> x; + stream >> y; + vector.setX(double(x)); + vector.setY(double(y)); + return stream; +} + +#endif // QT_NO_DATASTREAM + +QT_END_NAMESPACE diff --git a/src/positioning/qdoublevector2d_p.h b/src/positioning/qdoublevector2d_p.h new file mode 100644 index 0000000..c35899e --- /dev/null +++ b/src/positioning/qdoublevector2d_p.h @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDOUBLEVECTOR2D_P_H +#define QDOUBLEVECTOR2D_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifdef QT_BUILD_LOCATION_LIB +#include +#endif + +#include "qpositioningglobal.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QDoubleVector3D; + +class Q_POSITIONING_EXPORT QDoubleVector2D +{ +public: + Q_DECL_CONSTEXPR inline QDoubleVector2D(); + Q_DECL_CONSTEXPR inline QDoubleVector2D(double xpos, double ypos); + Q_DECL_CONSTEXPR explicit inline QDoubleVector2D(const QPointF &p); + explicit QDoubleVector2D(const QDoubleVector3D &vector); + + Q_DECL_CONSTEXPR inline double manhattanLength() const; + inline bool isNull() const; + + Q_DECL_CONSTEXPR inline double x() const; + Q_DECL_CONSTEXPR inline double y() const; + + inline void setX(double x); + inline void setY(double y); + + double length() const; + Q_DECL_CONSTEXPR inline double lengthSquared() const; + + QDoubleVector2D normalized() const; + void normalize(); + + inline QDoubleVector2D &operator+=(const QDoubleVector2D &vector); + inline QDoubleVector2D &operator-=(const QDoubleVector2D &vector); + inline QDoubleVector2D &operator*=(double factor); + inline QDoubleVector2D &operator*=(const QDoubleVector2D &vector); + inline QDoubleVector2D &operator/=(double divisor); + + Q_DECL_CONSTEXPR static inline double dotProduct(const QDoubleVector2D &v1, const QDoubleVector2D &v2) + { return v1.xp * v2.xp + v1.yp * v2.yp; } + + + friend Q_DECL_CONSTEXPR inline bool operator==(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend Q_DECL_CONSTEXPR inline bool operator!=(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend Q_DECL_CONSTEXPR inline const QDoubleVector2D operator+(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend Q_DECL_CONSTEXPR inline const QDoubleVector2D operator-(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend Q_DECL_CONSTEXPR inline const QDoubleVector2D operator*(double factor, const QDoubleVector2D &vector); + friend Q_DECL_CONSTEXPR inline const QDoubleVector2D operator*(const QDoubleVector2D &vector, double factor); + friend Q_DECL_CONSTEXPR inline const QDoubleVector2D operator*(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend Q_DECL_CONSTEXPR inline const QDoubleVector2D operator-(const QDoubleVector2D &vector); + friend Q_DECL_CONSTEXPR inline const QDoubleVector2D operator/(const QDoubleVector2D &vector, double divisor); + + friend Q_DECL_CONSTEXPR inline bool qFuzzyCompare(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + + QDoubleVector3D toVector3D() const; + Q_DECL_CONSTEXPR inline QPointF toPointF() const; + +private: + double xp, yp; + + friend class QDoubleVector3D; +}; + +Q_DECLARE_TYPEINFO(QDoubleVector2D, Q_MOVABLE_TYPE); + +Q_DECL_CONSTEXPR inline QDoubleVector2D::QDoubleVector2D() : xp(0.0), yp(0.0) {} + +Q_DECL_CONSTEXPR inline QDoubleVector2D::QDoubleVector2D(double xpos, double ypos) : xp(xpos), yp(ypos) {} + +Q_DECL_CONSTEXPR inline QDoubleVector2D::QDoubleVector2D(const QPointF &p) : xp(p.x()), yp(p.y()) { } + +Q_DECL_CONSTEXPR inline double QDoubleVector2D::manhattanLength() const +{ + return qAbs(x())+qAbs(y()); +} + +inline bool QDoubleVector2D::isNull() const +{ + return qIsNull(xp) && qIsNull(yp); +} + +Q_DECL_CONSTEXPR inline double QDoubleVector2D::x() const { return xp; } +Q_DECL_CONSTEXPR inline double QDoubleVector2D::y() const { return yp; } + +inline void QDoubleVector2D::setX(double aX) { xp = aX; } +inline void QDoubleVector2D::setY(double aY) { yp = aY; } + +Q_DECL_CONSTEXPR inline double QDoubleVector2D::lengthSquared() const +{ return xp * xp + yp * yp; } + +inline QDoubleVector2D &QDoubleVector2D::operator+=(const QDoubleVector2D &vector) +{ + xp += vector.xp; + yp += vector.yp; + return *this; +} + +inline QDoubleVector2D &QDoubleVector2D::operator-=(const QDoubleVector2D &vector) +{ + xp -= vector.xp; + yp -= vector.yp; + return *this; +} + +inline QDoubleVector2D &QDoubleVector2D::operator*=(double factor) +{ + xp *= factor; + yp *= factor; + return *this; +} + +inline QDoubleVector2D &QDoubleVector2D::operator*=(const QDoubleVector2D &vector) +{ + xp *= vector.xp; + yp *= vector.yp; + return *this; +} + +inline QDoubleVector2D &QDoubleVector2D::operator/=(double divisor) +{ + xp /= divisor; + yp /= divisor; + return *this; +} + +Q_DECL_CONSTEXPR inline bool operator==(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return v1.xp == v2.xp && v1.yp == v2.yp; +} + +Q_DECL_CONSTEXPR inline bool operator!=(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return v1.xp != v2.xp || v1.yp != v2.yp; +} + +Q_DECL_CONSTEXPR inline const QDoubleVector2D operator+(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return QDoubleVector2D(v1.xp + v2.xp, v1.yp + v2.yp); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector2D operator-(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return QDoubleVector2D(v1.xp - v2.xp, v1.yp - v2.yp); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector2D operator*(double factor, const QDoubleVector2D &vector) +{ + return QDoubleVector2D(vector.xp * factor, vector.yp * factor); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector2D operator*(const QDoubleVector2D &vector, double factor) +{ + return QDoubleVector2D(vector.xp * factor, vector.yp * factor); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector2D operator*(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return QDoubleVector2D(v1.xp * v2.xp, v1.yp * v2.yp); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector2D operator-(const QDoubleVector2D &vector) +{ + return QDoubleVector2D(-vector.xp, -vector.yp); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector2D operator/(const QDoubleVector2D &vector, double divisor) +{ + return QDoubleVector2D(vector.xp / divisor, vector.yp / divisor); +} + +Q_DECL_CONSTEXPR inline bool qFuzzyCompare(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return qFuzzyCompare(v1.xp, v2.xp) && qFuzzyCompare(v1.yp, v2.yp); +} + +Q_DECL_CONSTEXPR inline QPointF QDoubleVector2D::toPointF() const +{ + return QPointF(qreal(xp), qreal(yp)); +} + +#ifndef QT_NO_DEBUG_STREAM +Q_POSITIONING_EXPORT QDebug operator<<(QDebug dbg, const QDoubleVector2D &vector); +#endif + +#ifndef QT_NO_DATASTREAM +Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &, const QDoubleVector2D &); +Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &, QDoubleVector2D &); +#endif + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qdoublevector3d.cpp b/src/positioning/qdoublevector3d.cpp new file mode 100644 index 0000000..b308084 --- /dev/null +++ b/src/positioning/qdoublevector3d.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdoublevector3d_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QDoubleVector3D QDoubleVector3D::normalized() const +{ + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp); + if (qFuzzyIsNull(len - 1.0)) + return *this; + else if (!qFuzzyIsNull(len)) + return *this / (double)qSqrt(len); + else + return QDoubleVector3D(); +} + +void QDoubleVector3D::normalize() +{ + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp); + if (qFuzzyIsNull(len - 1.0) || qFuzzyIsNull(len)) + return; + + len = qSqrt(len); + + xp /= len; + yp /= len; + zp /= len; +} + +QDoubleVector3D QDoubleVector3D::normal(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return crossProduct(v1, v2).normalized(); +} + +QDoubleVector3D QDoubleVector3D::normal + (const QDoubleVector3D &v1, const QDoubleVector3D &v2, const QDoubleVector3D &v3) +{ + return crossProduct((v2 - v1), (v3 - v1)).normalized(); +} + +double QDoubleVector3D::distanceToPlane + (const QDoubleVector3D &plane1, const QDoubleVector3D &plane2, const QDoubleVector3D &plane3) const +{ + QDoubleVector3D n = normal(plane2 - plane1, plane3 - plane1); + return dotProduct(*this - plane1, n); +} + +double QDoubleVector3D::distanceToLine + (const QDoubleVector3D &point, const QDoubleVector3D &direction) const +{ + if (direction.isNull()) + return (*this - point).length(); + QDoubleVector3D p = point + dotProduct(*this - point, direction) * direction; + return (*this - p).length(); +} + +double QDoubleVector3D::length() const +{ + return qSqrt(xp * xp + yp * yp + zp * zp); +} + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<(QDebug dbg, const QDoubleVector3D &vector) +{ + QDebugStateSaver saver(dbg); + dbg.nospace() << "QDoubleVector3D(" + << vector.x() << ", " << vector.y() << ", " << vector.z() << ')'; + return dbg; +} + +#endif + +#ifndef QT_NO_DATASTREAM + +QDataStream &operator<<(QDataStream &stream, const QDoubleVector3D &vector) +{ + stream << double(vector.x()) << double(vector.y()) + << double(vector.z()); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QDoubleVector3D &vector) +{ + double x, y, z; + stream >> x; + stream >> y; + stream >> z; + vector.setX(double(x)); + vector.setY(double(y)); + vector.setZ(double(z)); + return stream; +} + +#endif // QT_NO_DATASTREAM + +QT_END_NAMESPACE diff --git a/src/positioning/qdoublevector3d_p.h b/src/positioning/qdoublevector3d_p.h new file mode 100644 index 0000000..d500fbe --- /dev/null +++ b/src/positioning/qdoublevector3d_p.h @@ -0,0 +1,302 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDOUBLEVECTOR3D_P_H +#define QDOUBLEVECTOR3D_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifdef QT_BUILD_LOCATION_LIB +#include +#endif + +#include "qpositioningglobal.h" +#include "qdoublevector2d_p.h" +#include + +QT_BEGIN_NAMESPACE + +class Q_POSITIONING_EXPORT QDoubleVector3D +{ +public: + Q_DECL_CONSTEXPR inline QDoubleVector3D(); + Q_DECL_CONSTEXPR inline QDoubleVector3D(double xpos, double ypos, double zpos); + Q_DECL_CONSTEXPR inline QDoubleVector3D(const QDoubleVector2D &vector); + Q_DECL_CONSTEXPR inline QDoubleVector3D(const QDoubleVector2D &vector, double zpos); + + inline bool isNull() const; + + Q_DECL_CONSTEXPR inline double x() const; + Q_DECL_CONSTEXPR inline double y() const; + Q_DECL_CONSTEXPR inline double z() const; + + inline void setX(double x); + inline void setY(double y); + inline void setZ(double z); + + inline double get(int i) const; + inline void set(int i, double value); + + double length() const; + Q_DECL_CONSTEXPR inline double lengthSquared() const; + + QDoubleVector3D normalized() const; + void normalize(); + + inline QDoubleVector3D &operator+=(const QDoubleVector3D &vector); + inline QDoubleVector3D &operator-=(const QDoubleVector3D &vector); + inline QDoubleVector3D &operator*=(double factor); + inline QDoubleVector3D &operator*=(const QDoubleVector3D &vector); + inline QDoubleVector3D &operator/=(double divisor); + + Q_DECL_CONSTEXPR static inline double dotProduct(const QDoubleVector3D &v1, const QDoubleVector3D &v2) + { return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp; } + + Q_DECL_CONSTEXPR static inline QDoubleVector3D crossProduct(const QDoubleVector3D &v1, const QDoubleVector3D &v2) + { return QDoubleVector3D(v1.yp * v2.zp - v1.zp * v2.yp, + v1.zp * v2.xp - v1.xp * v2.zp, + v1.xp * v2.yp - v1.yp * v2.xp); } + + static QDoubleVector3D normal(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + static QDoubleVector3D normal + (const QDoubleVector3D &v1, const QDoubleVector3D &v2, const QDoubleVector3D &v3); + + double distanceToPlane(const QDoubleVector3D &plane, const QDoubleVector3D &normal) const; + double distanceToPlane(const QDoubleVector3D &plane1, const QDoubleVector3D &plane2, const QDoubleVector3D &plane3) const; + double distanceToLine(const QDoubleVector3D &point, const QDoubleVector3D &direction) const; + + friend Q_DECL_CONSTEXPR inline bool operator==(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + friend Q_DECL_CONSTEXPR inline bool operator!=(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + friend Q_DECL_CONSTEXPR inline const QDoubleVector3D operator+(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + friend Q_DECL_CONSTEXPR inline const QDoubleVector3D operator-(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + friend Q_DECL_CONSTEXPR inline const QDoubleVector3D operator*(double factor, const QDoubleVector3D &vector); + friend Q_DECL_CONSTEXPR inline const QDoubleVector3D operator*(const QDoubleVector3D &vector, double factor); + friend Q_DECL_CONSTEXPR inline const QDoubleVector3D operator*(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + friend Q_DECL_CONSTEXPR inline const QDoubleVector3D operator-(const QDoubleVector3D &vector); + friend Q_DECL_CONSTEXPR inline const QDoubleVector3D operator/(const QDoubleVector3D &vector, double divisor); + + friend Q_DECL_CONSTEXPR inline bool qFuzzyCompare(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + + Q_DECL_CONSTEXPR inline QDoubleVector2D toVector2D() const; + +private: + double xp, yp, zp; + + friend class QDoubleVector2D; +}; + +Q_DECLARE_TYPEINFO(QDoubleVector3D, Q_MOVABLE_TYPE); + +Q_DECL_CONSTEXPR inline QDoubleVector3D::QDoubleVector3D() : xp(0.0), yp(0.0), zp(0.0) {} + +Q_DECL_CONSTEXPR inline QDoubleVector3D::QDoubleVector3D(double xpos, double ypos, double zpos) : xp(xpos), yp(ypos), zp(zpos) {} + +Q_DECL_CONSTEXPR inline QDoubleVector3D::QDoubleVector3D(const QDoubleVector2D &v) + : xp(v.xp), yp(v.yp), zp(0.0) {} + +Q_DECL_CONSTEXPR inline QDoubleVector3D::QDoubleVector3D(const QDoubleVector2D &v, double zpos) + : xp(v.xp), yp(v.yp), zp(zpos) {} + +inline bool QDoubleVector3D::isNull() const +{ + return qIsNull(xp) && qIsNull(yp) && qIsNull(zp); +} + +Q_DECL_CONSTEXPR inline double QDoubleVector3D::x() const { return xp; } +Q_DECL_CONSTEXPR inline double QDoubleVector3D::y() const { return yp; } +Q_DECL_CONSTEXPR inline double QDoubleVector3D::z() const { return zp; } + +Q_DECL_CONSTEXPR inline double QDoubleVector3D::lengthSquared() const +{ return xp * xp + yp * yp + zp * zp; } + + +inline void QDoubleVector3D::setX(double aX) { xp = aX; } +inline void QDoubleVector3D::setY(double aY) { yp = aY; } +inline void QDoubleVector3D::setZ(double aZ) { zp = aZ; } + +inline double QDoubleVector3D::get(int i) const +{ + switch (i) { + case 0: + return xp; + case 1: + return yp; + case 2: + return zp; + default: + return 0.0; + } +} + +inline void QDoubleVector3D::set(int i, double value) +{ + switch (i) { + case 0: + xp = value; + break; + case 1: + yp = value; + break; + case 2: + zp = value; + break; + default: + break; + } +} + +inline QDoubleVector3D &QDoubleVector3D::operator+=(const QDoubleVector3D &vector) +{ + xp += vector.xp; + yp += vector.yp; + zp += vector.zp; + return *this; +} + +inline QDoubleVector3D &QDoubleVector3D::operator-=(const QDoubleVector3D &vector) +{ + xp -= vector.xp; + yp -= vector.yp; + zp -= vector.zp; + return *this; +} + +inline QDoubleVector3D &QDoubleVector3D::operator*=(double factor) +{ + xp *= factor; + yp *= factor; + zp *= factor; + return *this; +} + +inline QDoubleVector3D &QDoubleVector3D::operator*=(const QDoubleVector3D &vector) +{ + xp *= vector.xp; + yp *= vector.yp; + zp *= vector.zp; + return *this; +} + +inline QDoubleVector3D &QDoubleVector3D::operator/=(double divisor) +{ + xp /= divisor; + yp /= divisor; + zp /= divisor; + return *this; +} + +Q_DECL_CONSTEXPR inline bool operator==(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp; +} + +Q_DECL_CONSTEXPR inline bool operator!=(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp; +} + +Q_DECL_CONSTEXPR inline const QDoubleVector3D operator+(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return QDoubleVector3D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector3D operator-(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return QDoubleVector3D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector3D operator*(double factor, const QDoubleVector3D &vector) +{ + return QDoubleVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector3D operator*(const QDoubleVector3D &vector, double factor) +{ + return QDoubleVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector3D operator*(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return QDoubleVector3D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector3D operator-(const QDoubleVector3D &vector) +{ + return QDoubleVector3D(-vector.xp, -vector.yp, -vector.zp); +} + +Q_DECL_CONSTEXPR inline const QDoubleVector3D operator/(const QDoubleVector3D &vector, double divisor) +{ + return QDoubleVector3D(vector.xp / divisor, vector.yp / divisor, vector.zp / divisor); +} + +Q_DECL_CONSTEXPR inline bool qFuzzyCompare(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return qFuzzyCompare(v1.xp, v2.xp) && + qFuzzyCompare(v1.yp, v2.yp) && + qFuzzyCompare(v1.zp, v2.zp); +} + +Q_DECL_CONSTEXPR inline QDoubleVector2D QDoubleVector3D::toVector2D() const +{ + return QDoubleVector2D(xp, yp); +} + + +#ifndef QT_NO_DEBUG_STREAM +Q_POSITIONING_EXPORT QDebug operator<<(QDebug dbg, const QDoubleVector3D &vector); +#endif + +#ifndef QT_NO_DATASTREAM +Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &, const QDoubleVector3D &); +Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &, QDoubleVector3D &); +#endif + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeoaddress.cpp b/src/positioning/qgeoaddress.cpp new file mode 100644 index 0000000..6f08f2d --- /dev/null +++ b/src/positioning/qgeoaddress.cpp @@ -0,0 +1,635 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoaddress.h" +#include "qgeoaddress_p.h" + +#include + +#ifdef QGEOADDRESS_DEBUG +#include +#endif + +QT_BEGIN_NAMESPACE + +/* + Combines a list of address parts into a single line. + + The parts parameter contains both address elements such as city, state and so on + as well as separators such as spaces and commas. + + It is expected that an element is always followed by a separator and the last + sepator is usually a new line delimeter. + + For example: Springfield, 8900 + would have four parts + ["Springfield", ", ", "8900", "
"] + + The addressLine takes care of putting in separators appropriately or leaving + them out depending on whether the adjacent elements are present or not. + For example if city were empty in the above scenario the returned string is "8900
" + If the postal code was empty, returned string is "Springfield
" + If both city and postal code were empty, the returned string is "". +*/ +static QString addressLine(const QStringList &parts) +{ + QString line; + Q_ASSERT(parts.count() % 2 == 0); + + //iterate until just before the last pair + QString penultimateSeparator; + for (int i = 0; i < parts.count() - 2; i += 2) { + if (!parts.at(i).isEmpty()) { + line.append(parts.at(i) + parts.at(i + 1)); + penultimateSeparator = parts.at(i + 1); + } + } + + if (parts.at(parts.count() - 2).isEmpty()) { + line.chop(penultimateSeparator.length()); + + if (!line.isEmpty()) + line.append(parts.at(parts.count() - 1)); + } else { + line.append(parts.at(parts.count() - 2)); + line.append(parts.at(parts.count() - 1)); + } + + return line; +} + +/* + Returns a single formatted string representing the \a address. Lines of the address + are delimited by \a newLine. By default lines are delimited by
. The \l + {QGeoAddress::countryCode} {countryCode} of the \a address determines the format of + the resultant string. +*/ +static QString formattedAddress(const QGeoAddress &address, + const QString &newLine = QLatin1String("
")) +{ + const QString Comma(QStringLiteral(", ")); + const QString Dash(QStringLiteral("-")); + const QString Space(QStringLiteral(" ")); + + QString text; + + if (address.countryCode() == QLatin1String("ALB") + || address.countryCode() == QLatin1String("MTQ")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.postalCode() << Comma + << address.city() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("AND") + || address.countryCode() == QLatin1String("AUT") + || address.countryCode() == QLatin1String("FRA") + || address.countryCode() == QLatin1String("GLP") + || address.countryCode() == QLatin1String("GUF") + || address.countryCode() == QLatin1String("ITA") + || address.countryCode() == QLatin1String("LUX") + || address.countryCode() == QLatin1String("MCO") + || address.countryCode() == QLatin1String("REU") + || address.countryCode() == QLatin1String("RUS") + || address.countryCode() == QLatin1String("SMR") + || address.countryCode() == QLatin1String("VAT")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.postalCode() << Space + << address.city() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("ARE") + || address.countryCode() == QLatin1String("BHS")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Space + << address.city() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("AUS")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << (address.district().isEmpty() ? address.city() : address.district()) + << Space << address.state() << Space << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("BHR")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Comma + << address.city() << Comma << address.state() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("BRA")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Space + << address.city() << Dash << address.state() << Space << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("BRN") + || address.countryCode() == QLatin1String("JOR") + || address.countryCode() == QLatin1String("LBN") + || address.countryCode() == QLatin1String("NZL")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Space + << address.city() << Space << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("CAN") + || address.countryCode() == QLatin1String("USA") + || address.countryCode() == QLatin1String("VIR")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.city() << Comma << address.state() << Space + << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("CHN")) { + text += addressLine(QStringList() << address.street() << Comma << address.city() << newLine); + text += addressLine(QStringList() << address.postalCode() << Space << address.state() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("CHL")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.postalCode() << Space + << address.district() << Comma << address.city() << Comma + << address.state() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("CYM")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.state() << Space + << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("GBR")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Comma + << address.city() << Comma << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("GIB")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.city() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("HKG")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << newLine); + text += addressLine(QStringList() << address.city() << newLine); + } else if (address.countryCode() == QLatin1String("IND")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.city() << Space << address.postalCode() << Space + << address.state() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("IDN") + || address.countryCode() == QLatin1String("JEY") + || address.countryCode() == QLatin1String("LVA")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.city() << Comma << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("IRL")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Comma << address.state() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("KWT")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.postalCode() << Comma + << address.district() << Comma << address.city() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("MLT") + || address.countryCode() == QLatin1String("SGP") + || address.countryCode() == QLatin1String("UKR")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.city() << Space << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("MEX")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << newLine); + text += addressLine(QStringList() << address.postalCode() << Space << address.city() << Comma + << address.state() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("MYS")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.postalCode() << Space << address.city() << newLine); + text += addressLine(QStringList() << address.state() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("OMN")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Comma + << address.postalCode() << Comma + << address.city() << Comma + << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("PRI")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Comma << address.city() << Comma + << address.state() << Comma << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("QAT")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Space << address.city() << Comma + << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("SAU")) { + text += addressLine(QStringList() << address.street() << Space << address.district() << newLine); + text += addressLine(QStringList() << address.city() << Space << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("TWN")) { + text += addressLine(QStringList() << address.street() << Comma + << address.district() << Comma << address.city() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("THA")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Comma << address.city() << Space + << address.postalCode() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("TUR")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.postalCode() << Space << address.district() << Comma + << address.city() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("VEN")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.city() << Space << address.postalCode() << Comma + << address.state() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else if (address.countryCode() == QLatin1String("ZAF")) { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.district() << Comma << address.city() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } else { + text += addressLine(QStringList() << address.street() << newLine); + text += addressLine(QStringList() << address.postalCode() << Space << address.city() << newLine); + text += addressLine(QStringList() << address.country() << newLine); + } + + text.chop(newLine.length()); + return text; +} + +QGeoAddressPrivate::QGeoAddressPrivate() + : QSharedData(), + m_autoGeneratedText(false) +{ +} + +QGeoAddressPrivate::QGeoAddressPrivate(const QGeoAddressPrivate &other) + : QSharedData(other), + sCountry(other.sCountry), + sCountryCode(other.sCountryCode), + sState(other.sState), + sCounty(other.sCounty), + sCity(other.sCity), + sDistrict(other.sDistrict), + sStreet(other.sStreet), + sPostalCode(other.sPostalCode), + sText(other.sText), + m_autoGeneratedText(false) +{ +} + +QGeoAddressPrivate::~QGeoAddressPrivate() +{ +} + +/*! + \class QGeoAddress + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \ingroup QtLocation-places-data + \ingroup QtLocation-places + \since 5.2 + + \brief The QGeoAddress class represents an address of a \l QGeoLocation. + + The address' attributes are normalized to US feature names and can be mapped + to the local feature levels (for example State matches "Bundesland" in Germany). + + The address contains a \l text() for displaying purposes and additional + properties to access the components of an address: + + \list + \li QGeoAddress::country() + \li QGeoAddress::countryCode() + \li QGeoAddress::state() + \li QGeoAddress::city() + \li QGeoAddress::district() + \li QGeoAddress::street() + \li QGeoAddress::postalCode() + \endlist +*/ + +/*! + Default constructor. +*/ +QGeoAddress::QGeoAddress() + : d(new QGeoAddressPrivate) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QGeoAddress::QGeoAddress(const QGeoAddress &other) + : d(other.d) +{ +} + +/*! + Destroys this address. +*/ +QGeoAddress::~QGeoAddress() +{ +} + +/*! + Assigns the given \a address to this address and + returns a reference to this address. +*/ +QGeoAddress &QGeoAddress::operator=(const QGeoAddress & address) +{ + if (this == &address) + return *this; + + d = address.d; + return *this; +} + +/*! + Returns true if this address is equal to \a other, + otherwise returns false. +*/ +bool QGeoAddress::operator==(const QGeoAddress &other) const +{ +#ifdef QGEOADDRESS_DEBUG + qDebug() << "country" << (d->sCountry == other.country()); + qDebug() << "countryCode" << (d->sCountryCode == other.countryCode()); + qDebug() << "state:" << (d->sState == other.state()); + qDebug() << "county:" << (d->sCounty == other.county()); + qDebug() << "city:" << (d->sCity == other.city()); + qDebug() << "district:" << (d->sDistrict == other.district()); + qDebug() << "street:" << (d->sStreet == other.street()); + qDebug() << "postalCode:" << (d->sPostalCode == other.postalCode()); + qDebug() << "text:" << (text() == other.text()); +#endif + + return d->sCountry == other.country() && + d->sCountryCode == other.countryCode() && + d->sState == other.state() && + d->sCounty == other.county() && + d->sCity == other.city() && + d->sDistrict == other.district() && + d->sStreet == other.street() && + d->sPostalCode == other.postalCode() && + this->text() == other.text(); +} + +/*! + \fn bool QGeoAddress::operator!=(const QGeoAddress &other) const + + Returns true if this address is not equal to \a other, + otherwise returns false. +*/ + +/*! + Returns the address as a single formatted string. It is the recommended string + to use to display the address to the user. It typically takes the format of + an address as found on an envelope, but this is not always necessarily the case. + + The address text is either automatically generated or explicitly assigned. + This can be determined by checking \l {QGeoAddress::isTextGenerated()} {isTextGenerated}. + + If an empty string is provided to setText(), then isTextGenerated() will be set + to true and text() will return a string which is locally formatted according to + countryCode() and based on the elements of the address such as street, city and so on. + Because the text string is generated from the address elements, a sequence + of calls such as text(), setStreet(), text() may return different strings for each + invocation of text(). + + If a non-empty string is provided to setText(), then isTextGenerated() will be + set to false and text() will always return the explicitly assigned string. + Calls to modify other elements such as setStreet(), setCity() and so on will not + affect the resultant string from text(). +*/ +QString QGeoAddress::text() const +{ + if (d->sText.isEmpty()) + return formattedAddress(*this); + else + return d->sText; +} + +/*! + If \a text is not empty, explicitly assigns \a text as the string to be returned by + text(). isTextGenerated() will return false. + + If \a text is empty, indicates that text() should be automatically generated + from the address elements. isTextGenerated() will return true. +*/ +void QGeoAddress::setText(const QString &text) +{ + d->sText = text; +} + +/*! + Returns the country name. +*/ +QString QGeoAddress::country() const +{ + return d->sCountry; +} + +/*! + Sets the \a country name. +*/ +void QGeoAddress::setCountry(const QString &country) +{ + d->sCountry = country; +} + +/*! + Returns the country code according to ISO 3166-1 alpha-3 +*/ +QString QGeoAddress::countryCode() const +{ + return d->sCountryCode; +} + +/*! + Sets the \a countryCode according to ISO 3166-1 alpha-3 +*/ +void QGeoAddress::setCountryCode(const QString &countryCode) +{ + d->sCountryCode = countryCode; +} + +/*! + Returns the state. The state is considered the first subdivision below country. +*/ +QString QGeoAddress::state() const +{ + return d->sState; +} + +/*! + Sets the \a state. +*/ +void QGeoAddress::setState(const QString &state) +{ + d->sState = state; +} + +/*! + Returns the county. The county is considered the second subdivision below country. +*/ +QString QGeoAddress::county() const +{ + return d->sCounty; +} + +/*! + Sets the \a county. +*/ +void QGeoAddress::setCounty(const QString &county) +{ + d->sCounty = county; +} + +/*! + Returns the city. +*/ +QString QGeoAddress::city() const +{ + return d->sCity; +} + +/*! + Sets the \a city. +*/ +void QGeoAddress::setCity(const QString &city) +{ + d->sCity = city; +} + +/*! + Returns the district. The district is considered the subdivison below city. +*/ +QString QGeoAddress::district() const +{ + return d->sDistrict; +} + +/*! + Sets the \a district. +*/ +void QGeoAddress::setDistrict(const QString &district) +{ + d->sDistrict = district; +} + +/*! + Returns the street-level component of the address. + + This typically includes a street number and street name + but may also contain things like a unit number, a building + name, or anything else that might be used to + distinguish one address from another. +*/ +QString QGeoAddress::street() const +{ + return d->sStreet; +} + +/*! + Sets the street-level component of the address to \a street. + + This typically includes a street number and street name + but may also contain things like a unit number, a building + name, or anything else that might be used to + distinguish one address from another. +*/ +void QGeoAddress::setStreet(const QString &street) +{ + d->sStreet = street; +} + +/*! + Returns the postal code. +*/ +QString QGeoAddress::postalCode() const +{ + return d->sPostalCode; +} + +/*! + Sets the \a postalCode. +*/ +void QGeoAddress::setPostalCode(const QString &postalCode) +{ + d->sPostalCode = postalCode; +} + +/*! + Returns whether this address is empty. An address is considered empty + if \e all of its fields are empty. +*/ +bool QGeoAddress::isEmpty() const +{ + return d->sCountry.isEmpty() && + d->sCountryCode.isEmpty() && + d->sState.isEmpty() && + d->sCounty.isEmpty() && + d->sCity.isEmpty() && + d->sDistrict.isEmpty() && + d->sStreet.isEmpty() && + d->sPostalCode.isEmpty() && + d->sText.isEmpty(); + +} + +/*! + Clears all of the address' data fields. +*/ +void QGeoAddress::clear() +{ + d->sCountry.clear(); + d->sCountryCode.clear(); + d->sState.clear(); + d->sCounty.clear(); + d->sCity.clear(); + d->sDistrict.clear(); + d->sStreet.clear(); + d->sPostalCode.clear(); + d->sText.clear(); +} + +/*! + Returns true if QGeoAddress::text() is automatically generated from address elements, + otherwise returns false if text() has been explicitly assigned. + + \sa text(), setText() +*/ +bool QGeoAddress::isTextGenerated() const +{ + return d->sText.isEmpty(); +} + +QT_END_NAMESPACE + diff --git a/src/positioning/qgeoaddress.h b/src/positioning/qgeoaddress.h new file mode 100644 index 0000000..6231274 --- /dev/null +++ b/src/positioning/qgeoaddress.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOADDRESS_H +#define QGEOADDRESS_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QString; +class QGeoAddressPrivate; +class Q_POSITIONING_EXPORT QGeoAddress +{ +public: + QGeoAddress(); + QGeoAddress(const QGeoAddress &other); + ~QGeoAddress(); + + QGeoAddress &operator=(const QGeoAddress &other); + bool operator==(const QGeoAddress &other) const; + bool operator!=(const QGeoAddress &other) const { + return !(other == *this); + } + + QString text() const; + void setText(const QString &text); + + QString country() const; + void setCountry(const QString &country); + + QString countryCode() const; + void setCountryCode(const QString &countryCode); + + QString state() const; + void setState(const QString &state); + + QString county() const; + void setCounty(const QString &county); + + QString city() const; + void setCity(const QString &city); + + QString district() const; + void setDistrict(const QString &district); + + QString postalCode() const; + void setPostalCode(const QString &postalCode); + + QString street() const; + void setStreet(const QString &street); + + bool isEmpty() const; + void clear(); + + bool isTextGenerated() const; + +private: + QSharedDataPointer d; +}; + +Q_DECLARE_TYPEINFO(QGeoAddress, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoAddress) + +#endif diff --git a/src/positioning/qgeoaddress_p.h b/src/positioning/qgeoaddress_p.h new file mode 100644 index 0000000..ca0897e --- /dev/null +++ b/src/positioning/qgeoaddress_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOCATION_GEOADDRESS_P_H +#define QLOCATION_GEOADDRESS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoAddressPrivate : public QSharedData +{ +public: + QGeoAddressPrivate(); + QGeoAddressPrivate(const QGeoAddressPrivate &other); + ~QGeoAddressPrivate(); + + QString sCountry; //!< country field + QString sCountryCode; //!< country code field + QString sState; //!< state field + QString sCounty; //!< county field + QString sCity; //!< city field + QString sDistrict; //!< district field + QString sStreet; //!< street name field + QString sPostalCode; //!< postal code field + QString sText; + bool m_autoGeneratedText; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeoareamonitorinfo.cpp b/src/positioning/qgeoareamonitorinfo.cpp new file mode 100644 index 0000000..5d39dee --- /dev/null +++ b/src/positioning/qgeoareamonitorinfo.cpp @@ -0,0 +1,379 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#ifndef QT_NO_DEBUG_STREAM +#include +#endif + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoAreaMonitorInfo + \inmodule QtPositioning + \since 5.2 + \ingroup QtPositioning-positioning + + \brief The QGeoAreaMonitorInfo class describes the parameters of an area or region + to be monitored for proximity. + + The purpose of area monitoring is to inform a user when he/she comes close to an area of + interest. In general such an area is described by a \l QGeoCircle. The circle's center + represents the place of interest and the area around it identifies the geographical region + within which notifications are sent. + + A QGeoAreaMonitorInfo object is valid if it has a non-empty name and a valid \l area(). + Such objects must be registered with a \l QGeoAreaMonitorSource to start and stop the + monitoring process. Note that extensive monitoring can be very resource consuming + because the positioning engine must remain active and has to match the current position + with each QGeoAreaMonitorInfo instance. + + To further reduce the burden on the system there are optional attributes which can + set. Each monitored area can have an expiry date which automatically removes the + to-be-monitored area from the monitoring source once the expiry date has been reached. + Another option is to adjust the persistence of a monitored area. A QGeoAreaMonitorInfo + that \l isPersistent() will remain active beyond + the current applications lifetime. If an area is entered while the monitoring + application is not running the application will be started. Note that this feature is + not available on all platforms. Its availability can be checked via + \l QGeoAreaMonitorSource::supportedAreaMonitorFeatures(). + + \sa QGeoAreaMonitorSource + + */ + +class QGeoAreaMonitorInfoPrivate : public QSharedData +{ +public: + QGeoAreaMonitorInfoPrivate() : QSharedData(), persistent(false) {} + QGeoAreaMonitorInfoPrivate(const QGeoAreaMonitorInfoPrivate &other) + : QSharedData(other) + { + uid = other.uid; + name = other.name; + shape = other.shape; + persistent = other.persistent; + notificationParameters = other.notificationParameters; + expiry = other.expiry; + } + ~QGeoAreaMonitorInfoPrivate() {} + + QUuid uid; + QString name; + QGeoShape shape; + bool persistent; + QVariantMap notificationParameters; + QDateTime expiry; +}; + +/*! + Constructs a QGeoAreaMonitorInfo object with the specified \a name. + + \sa name() + */ +QGeoAreaMonitorInfo::QGeoAreaMonitorInfo(const QString &name) +{ + d = new QGeoAreaMonitorInfoPrivate; + d->name = name; + d->uid = QUuid::createUuid(); +} + +/*! + Constructs a QGeoAreaMonitorInfo object as a copy of \a other. + */ +QGeoAreaMonitorInfo::QGeoAreaMonitorInfo(const QGeoAreaMonitorInfo &other) + : d(other.d) +{ +} + +/*! + Destructor + */ +QGeoAreaMonitorInfo::~QGeoAreaMonitorInfo() +{ +} + +/*! + Assigns \a other to this QGeoAreaMonitorInfo object and returns a reference + to this QGeoAreaMonitorInfo object. + */ +QGeoAreaMonitorInfo &QGeoAreaMonitorInfo::operator=(const QGeoAreaMonitorInfo &other) +{ + d = other.d; + return *this; +} + +/*! + Returns true if all of this object's values are the same as those of + \a other. +*/ +bool QGeoAreaMonitorInfo::operator==(const QGeoAreaMonitorInfo &other) const +{ + return (d->name == other.d->name && + d->uid == other.d->uid && + d->shape == other.d->shape && + d->persistent == other.d->persistent && + d->expiry == other.d->expiry && + d->notificationParameters == other.d->notificationParameters); +} + +/*! + Returns true if any of this object's values are not the same as those of + \a other. +*/ +bool QGeoAreaMonitorInfo::operator!=(const QGeoAreaMonitorInfo &other) const +{ + return !QGeoAreaMonitorInfo::operator ==(other); +} + +/*! + Returns the name of the QGeoAreaMonitorInfo object. The name should be used to + for user-visibility purposes. + */ +QString QGeoAreaMonitorInfo::name() const +{ + return d->name; +} + +/*! + Sets the user visibile \a name. + */ +void QGeoAreaMonitorInfo::setName(const QString &name) +{ + if (d->name != name) + d->name = name; +} + +/*! + Returns the identifier of the QGeoAreaMonitorInfo object. + The identifier is automatically generated upon construction of a new + QGeoAreaMonitorInfo object. +*/ + +QString QGeoAreaMonitorInfo::identifier() const +{ + return d->uid.toString(); +} + +/*! + Returns true, if the monitor is valid. A valid QGeoAreaMonitorInfo has a non-empty name() + and the monitored area is not \l {QGeoShape::isEmpty()}{empty()}. + Otherwise this function returns false. + */ +bool QGeoAreaMonitorInfo::isValid() const +{ + return (!d->name.isEmpty() && !d->shape.isEmpty()); +} + +/*! + Returns the boundaries of the to-be-monitored area. This area must not be empty. + + \sa setArea() + */ +QGeoShape QGeoAreaMonitorInfo::area() const +{ + return d->shape; +} + +/*! + Sets the to-be-monitored area to \a newShape. + + \sa area() + */ +void QGeoAreaMonitorInfo::setArea(const QGeoShape &newShape) +{ + d->shape = newShape; +} + +/*! + Returns the expiry date. + + After an active QGeoAreaMonitorInfo has expired the region is no longer monitored + and the QGeoAreaMonitorInfo object is removed from the list of + \l {QGeoAreaMonitorSource::activeMonitors()}{active monitors}. + + If the expiry \l QDateTime is invalid the QGeoAreaMonitorInfo object is treated as not having + an expiry date. This implies an indefinite monitoring period if the object is persistent or + until the current application closes if the object is non-persistent. + + \sa QGeoAreaMonitorSource::activeMonitors() + */ +QDateTime QGeoAreaMonitorInfo::expiration() const +{ + return d->expiry; +} + +/*! + Sets the expiry date and time to \a expiry. + */ +void QGeoAreaMonitorInfo::setExpiration(const QDateTime &expiry) +{ + d->expiry = expiry; +} + +/*! + Returns true if the QGeoAreaMonitorInfo is persistent. + The default value for this property is false. + + A non-persistent QGeoAreaMonitorInfo will be removed by the system once + the application owning the monitor object stops. Persistent objects remain + active and can be retrieved once the application restarts. + + If the system triggers an event associated to a persistent QGeoAreaMonitorInfo + the relevant application will be re-started and the appropriate signal emitted. + + \sa setPersistent() + */ +bool QGeoAreaMonitorInfo::isPersistent() const +{ + return d->persistent; +} + +/*! + Sets the QGeoAreaMonitorInfo objects persistence to \a isPersistent. + + Note that setting this flag does not imply that QGeoAreaMonitorInfoSource supports persistent + monitoring. \l QGeoAreaMonitorSource::supportedAreaMonitorFeatures() can be used to + check for this feature's availability. + + \sa isPersistent() + */ +void QGeoAreaMonitorInfo::setPersistent(bool isPersistent) +{ + d->persistent = isPersistent; +} + + +/*! + Returns the set of platform specific paraemters used by this QGeoAreaMonitorInfo. + + \sa setNotificationParameters() + */ +QVariantMap QGeoAreaMonitorInfo::notificationParameters() const +{ + return d->notificationParameters; +} + +/*! + Sets the set of platform specific \a parameters used by QGeoAreaMonitorInfo. + + \sa notificationParameters() + */ +void QGeoAreaMonitorInfo::setNotificationParameters(const QVariantMap ¶meters) +{ + d->notificationParameters = parameters; +} + +#ifndef QT_NO_DATASTREAM + +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QGeoAreaMonitorInfo &monitor) + \relates QGeoAreaMonitorInfo + + Writes the given \a monitor to the specified \a stream. + + \sa {Serializing Qt Data Types} +*/ +QDataStream &operator<<(QDataStream &ds, const QGeoAreaMonitorInfo &monitor) +{ + ds << monitor.name() << monitor.d->uid << monitor.area() + << monitor.isPersistent() << monitor.notificationParameters() << monitor.expiration(); + return ds; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QGeoAreaMonitorInfo &monitor) + \relates QGeoAreaMonitorInfo + + Reads a area monitoring data from the specified \a stream into the given + \a monitor. + + \sa {Serializing Qt Data Types} +*/ + +QDataStream &operator>>(QDataStream &ds, QGeoAreaMonitorInfo &monitor) +{ + QString s; + ds >> s; + monitor = QGeoAreaMonitorInfo(s); + + QUuid id; + ds >> id; + monitor.d->uid = id; + + QGeoShape shape; + ds >> shape; + monitor.setArea(shape); + + bool persistent; + ds >> persistent; + monitor.setPersistent(persistent); + + QVariantMap map; + ds >> map; + monitor.setNotificationParameters(map); + + QDateTime dt; + ds >> dt; + monitor.setExpiration(dt); + + return ds; +} + +#endif + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QGeoAreaMonitorInfo &monitor) +{ + QDebugStateSaver saver(dbg); + dbg.nospace() << "QGeoAreaMonitorInfo(\"" << qPrintable(monitor.name()) + << "\", " << monitor.area() + << ", persistent: " << monitor.isPersistent() + << ", expiry: " << monitor.expiration() << ")"; + return dbg; +} + +#endif + +QT_END_NAMESPACE diff --git a/src/positioning/qgeoareamonitorinfo.h b/src/positioning/qgeoareamonitorinfo.h new file mode 100644 index 0000000..ae65d2c --- /dev/null +++ b/src/positioning/qgeoareamonitorinfo.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOAREAMONITORINFO_H +#define QGEOAREAMONITORINFO_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDataStream; +class QGeoAreaMonitorInfo; + +#ifndef QT_NO_DATASTREAM +Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &, const QGeoAreaMonitorInfo &); +Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &, QGeoAreaMonitorInfo &); +#endif + +class QGeoAreaMonitorInfoPrivate; +class Q_POSITIONING_EXPORT QGeoAreaMonitorInfo +{ +public: + explicit QGeoAreaMonitorInfo(const QString &name = QString()); + QGeoAreaMonitorInfo(const QGeoAreaMonitorInfo &other); + ~QGeoAreaMonitorInfo(); + + QGeoAreaMonitorInfo &operator=(const QGeoAreaMonitorInfo &other); + + bool operator==(const QGeoAreaMonitorInfo &other) const; + bool operator!=(const QGeoAreaMonitorInfo &other) const; + + QString name() const; + void setName(const QString &name); + + QString identifier() const; + bool isValid() const; + + QGeoShape area() const; + void setArea(const QGeoShape &newShape); + + QDateTime expiration() const; + void setExpiration(const QDateTime &expiry); + + bool isPersistent() const; + void setPersistent(bool isPersistent); + + QVariantMap notificationParameters() const; + void setNotificationParameters(const QVariantMap ¶meters); +private: + QSharedDataPointer d; + +#ifndef QT_NO_DATASTREAM + friend Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &, const QGeoAreaMonitorInfo &); + friend Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &, QGeoAreaMonitorInfo &); +#endif +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_POSITIONING_EXPORT QDebug operator<<(QDebug, const QGeoAreaMonitorInfo &); +#endif + +QT_END_NAMESPACE + +#endif // QGEOAREAMONITORINFO_H diff --git a/src/positioning/qgeoareamonitorsource.cpp b/src/positioning/qgeoareamonitorsource.cpp new file mode 100644 index 0000000..1db9c74 --- /dev/null +++ b/src/positioning/qgeoareamonitorsource.cpp @@ -0,0 +1,389 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "qgeopositioninfosourcefactory.h" +#include "qgeopositioninfosource_p.h" + +/*! + \class QGeoAreaMonitorSource + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QGeoAreaMonitorSource class enables the detection of proximity + changes for a specified set of coordinates. + + A QGeoAreaMonitorSource emits signals when the current position is in + range, or has moved out of range, of a specified area. + Each area is specified by a \l QGeoAreaMonitorInfo object. + For example: + + \snippet cpp/cppqml.cpp BigBen + + \c QGeoAreaMonitorSource follows a singleton pattern. Each instance of + the class with the same \l sourceName() shares the same area monitoring backend. + If a new \l QGeoAreaMonitorInfo object is added via \l startMonitoring() + or \l requestUpdate() it can be retrieved by another instance of this class + (provided that they are sourced from the same area monitor provider plug-in). + The same singleton pattern applies to the \l QGeoPositionInfoSource instance + used by this class. The following code snippet emphasizes the behavior: + + \code + QGeoAreaMonitorSource *s1 = QGeoAreaMonitorSource::createSource("blah", this); + QGeoAreaMonitorSource *s2 = QGeoAreaMonitorSource::createSource("blah", this); + QVERIFY(s1->positionInfoSource() == s2->positionInfoSource); + \endcode +*/ + +QT_BEGIN_NAMESPACE + + + +class QGeoAreaMonitorSourcePrivate +{ +public: + QGeoPositionInfoSource *source; + QString providerName; +}; + +/*! + \enum QGeoAreaMonitorSource::Error + Defines the types of positioning methods. + + The Error enumeration represents the errors which can occur. + + \value AccessError The connection setup to the remote area monitoring backend failed because the + application lacked the required privileges. + \value InsufficientPositionInfo The area monitoring source could not retrieve a location fix or + the accuracy of the fix is not high enough to provide an effective area monitoring. + \value NoError No error has occurred. + \value UnknownSourceError An unidentified error occurred. +*/ + +/*! + \enum QGeoAreaMonitorSource::AreaMonitorFeature + Defines the types of area monitoring capabilities. + + \value PersistentAreaMonitorFeature QGeoAreaMonitorInfo instances can be made persistent. + A persistent monitor continues to be active even when the application managing the monitor is + not running. + \value AnyAreaMonitorFeature Matches all possible area monitoring features. +*/ + +/*! + \fn virtual AreaMonitoringFeatures QGeoAreaMonitorSource::supportedAreaMonitorFeatures() const = 0; + + Returns the area monitoring features available to this source. +*/ + +/*! + \fn virtual QGeoAreaMonitorSource::Error QGeoAreaMonitorSource::error() const + + Returns the type of error that last occurred. +*/ + +/*! + Creates a monitor with the given \a parent. +*/ +QGeoAreaMonitorSource::QGeoAreaMonitorSource(QObject *parent) + : QObject(parent), + d(new QGeoAreaMonitorSourcePrivate) +{ + d->source = 0; +} + +/*! + Destroys the monitor. +*/ +QGeoAreaMonitorSource::~QGeoAreaMonitorSource() +{ + delete d; +} + +/*! + Creates and returns a monitor with the given \a parent that + monitors areas using resources on the underlying system. + + Returns 0 if the system has no support for position monitoring. +*/ +QGeoAreaMonitorSource *QGeoAreaMonitorSource::createDefaultSource(QObject *parent) +{ + QList plugins = QGeoPositionInfoSourcePrivate::pluginsSorted(); + foreach (const QJsonObject &obj, plugins) { + if (obj.value(QStringLiteral("Monitor")).isBool() + && obj.value(QStringLiteral("Monitor")).toBool()) + { + QGeoPositionInfoSourcePrivate d; + d.metaData = obj; + d.loadPlugin(); + QGeoAreaMonitorSource *s = 0; + if (d.factory) + s = d.factory->areaMonitor(parent); + if (s) + s->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString(); + return s; + } + } + + return 0; +} + +/*! + Creates and returns a monitor with the given \a parent, + by loading the plugin named \a sourceName. + + Returns 0 if the plugin cannot be found. +*/ +QGeoAreaMonitorSource *QGeoAreaMonitorSource::createSource(const QString &sourceName, QObject *parent) +{ + QHash plugins = QGeoPositionInfoSourcePrivate::plugins(); + if (plugins.contains(sourceName)) { + QGeoPositionInfoSourcePrivate d; + d.metaData = plugins.value(sourceName); + d.loadPlugin(); + QGeoAreaMonitorSource *s = 0; + if (d.factory) + s = d.factory->areaMonitor(parent); + if (s) + s->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString(); + return s; + } + + return 0; +} + +/*! + Returns a list of available monitor plugins, including the default system + backend if one is available. +*/ +QStringList QGeoAreaMonitorSource::availableSources() +{ + QStringList plugins; + const QHash meta = QGeoPositionInfoSourcePrivate::plugins(); + for (auto it = meta.cbegin(), end = meta.cend(); it != end; ++it) { + if (it.value().value(QStringLiteral("Monitor")).isBool() + && it.value().value(QStringLiteral("Monitor")).toBool()) { + plugins << it.key(); + } + } + + return plugins; +} + +/*! + Returns the unique name of the area monitor source implementation in use. + + This is the same name that can be passed to createSource() in order to + create a new instance of a particular area monitor source implementation. +*/ +QString QGeoAreaMonitorSource::sourceName() const +{ + return d->providerName; +} + +/*! + Returns the current QGeoPositionInfoSource used by this QGeoAreaMonitorSource + object. The function will return \l QGeoPositionInfoSource::createDefaultSource() + if no other object has been set. + + The function returns 0 if not even a default QGeoPositionInfoSource exists. + + Any usage of the returned \l QGeoPositionInfoSource instance should account + for the fact that it may reside in a different thread. + + \sa QGeoPositionInfoSource, setPositionInfoSource() +*/ +QGeoPositionInfoSource* QGeoAreaMonitorSource::positionInfoSource() const +{ + return d->source; +} + +/*! + Sets the new \l QGeoPositionInfoSource to be used by this QGeoAreaMonitorSource object. + The area monitoring backend becomes the new QObject parent for \a newSource. + The previous \l QGeoPositionInfoSource object will be deleted. All QGeoAreaMonitorSource + instances based on the same \l sourceName() share the same QGeoPositionInfoSource + instance. + + This may be useful when it is desirable to manipulate the positioning system + used by the area monitoring engine. + + Note that ownership must be taken care of by subclasses of QGeoAreaMonitorSource. + Due to the singleton pattern behind this class \a newSource may be moved to a + new thread. + + \sa positionInfoSource() + */ +void QGeoAreaMonitorSource::setPositionInfoSource(QGeoPositionInfoSource *newSource) +{ + d->source = newSource; +} + + +/*! + \fn virtual bool QGeoAreaMonitorSource::startMonitoring(const QGeoAreaMonitorInfo &monitor) + + Returns \c true if the monitoring of \a monitor could be successfully started; otherwise + returns false. A reason for not being able to start monitoring could be the unavailability + of an appropriate default position info source while no alternative QGeoPositionInfoSource + has been set via \l setPositionInfoSource(). + + If \a monitor is already active the existing monitor object will be replaced by the new \a monitor reference. + The identification of QGeoAreaMonitorInfo instances happens via \l QGeoAreaMonitorInfo::identifier(). + Therefore this function can also be used to update active monitors. + + If \a monitor has an expiry date that has been passed this function returns false. Calling + this function for an already via \l requestUpdate() registered single shot monitor + switches the monitor to a permanent monitoring mode. + + Requesting persistent monitoring on a QGeoAreaMonitorSource instance fails if the area monitoring + backend doesn't support \l QGeoAreaMonitorSource::PersistentAreaMonitorFeature. + + \sa stopMonitoring() +*/ + +/*! + \fn virtual bool QGeoAreaMonitorSource::requestUpdate(const QGeoAreaMonitorInfo &monitor, const char *signal) + + Enables single shot area monitoring. Area monitoring for \a monitor will be performed + until this QGeoAreaMonitorSource instance emits \a signal for the first time. Once + the signal was emitted, \a monitor is automatically removed from the list of \l activeMonitors(). + If \a monitor is invalid or has an expiry date that has been passed this function returns false. + + \code + QGeoAreaMonitor singleShotMonitor; + QGeoAreaMonitorSource * source = QGeoAreaMonitorSource::createDefaultSource(this); + //... + bool ret = source->requestUpdate(singleShotMonitor, + SIGNAL(areaExited(QGeoAreaMonitor,QGeoPositionInfo))); + \endcode + + The above \c singleShotMonitor object will cease to send updates once the \l areaExited() signal + was emitted for the first time. Until this point in time any other signal may be emitted + zero or more times depending on the area context. + + It is not possible to simultanously request updates for more than one signal of the same monitor object. + The last call to this function determines the signal upon which the updates cease to continue. + At this stage only the \l areaEntered() and \l areaExited() signals can be used to + terminate the monitoring process. + + Requesting persistent monitoring on a QGeoAreaMonitorSource instance fails if the area monitoring + backend doesn't support \l QGeoAreaMonitorSource::PersistentAreaMonitorFeature. + + If \a monitor was already registered via \l startMonitoring() it is converted to a single + shot behavior. + + \sa startMonitoring(), stopMonitoring() + */ + +/*! + \fn virtual bool QGeoAreaMonitorSource::stopMonitoring(const QGeoAreaMonitorInfo &monitor) + + Returns true if \a monitor was successfully removed from the list of \l activeMonitors(); + otherwise returns false. This behavior is independent on whether \a monitor was registered + via \l startMonitoring() or \l requestUpdate(). +*/ + +/*! + \fn virtual QList QGeoAreaMonitorSource::activeMonitors() const + + Returns the list of all active monitors known to the QGeoAreaMonitorSource object. + + An active monitor was started via startMonitoring() the source object will emit + the required signals such as areaEntered() or areaExited(). Multiple \l QGeoAreaMonitorSource + instances within the same application share the same active monitor objects. + + Unless an active QGeoAreaMonitorInfo \l {QGeoAreaMonitorInfo::isPersistent()}{isPersistent()} an active QGeoAreaMonitorInfo + will be stopped once the current application terminates. +*/ + +/*! + \fn virtual QList QGeoAreaMonitorSource::activeMonitors(const QGeoShape &lookupArea) const + + Returns the list of all active monitors known to the QGeoAreaMonitorSource object whose + center lies within \a lookupArea. If \a lookupArea is empty the returned list will be empty. + + An active monitor was started via startMonitoring() and the source object will emit + the required signals such as areaEntered() or areaExited(). Multiple QGeoAreaMonitorSource + instances within the same application share the same monitor objects. + + Unless an active QGeoAreaMonitorInfo \l {QGeoAreaMonitorInfo::isPersistent()}{isPersistent()} an active QGeoAreaMonitorInfo + will be stopped once the current application terminates. + + \sa QGeoShape +*/ + + +/*! + \fn void QGeoAreaMonitorSource::monitorExpired(const QGeoAreaMonitorInfo &monitor) + + Emitted when \a monitor has expired. An expired area monitor is automatically + removed from the list of \l activeMonitors(). + + \sa activeMonitors() +*/ + +/*! + \fn void QGeoAreaMonitorSource::areaEntered(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update) + + Emitted when the current position has moved from a position outside of the active \a monitor + to a position within the monitored area. + + The \a update holds the new position. +*/ + +/*! + \fn void QGeoAreaMonitorSource::areaExited(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update) + + Emitted when the current position has moved from a position within the active \a monitor + to a position outside the monitored area. + + The \a update holds the new position. +*/ + +/*! + \fn void QGeoAreaMonitorSource::error(QGeoAreaMonitorSource::Error areaMonitoringError) + + This signal is emitted after an error occurred. The \a areaMonitoringError + parameter describes the type of error that occurred. + +*/ + +QT_END_NAMESPACE diff --git a/src/positioning/qgeoareamonitorsource.h b/src/positioning/qgeoareamonitorsource.h new file mode 100644 index 0000000..519f313 --- /dev/null +++ b/src/positioning/qgeoareamonitorsource.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOAREAMONITORSOURCE_H +#define QGEOAREAMONITORSOURCE_H + +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoPositionInfo; +class QGeoAreaMonitorSourcePrivate; +class Q_POSITIONING_EXPORT QGeoAreaMonitorSource : public QObject +{ + Q_OBJECT + +public: + enum Error { + AccessError = 0, + InsufficientPositionInfo = 1, + UnknownSourceError = 2, + NoError = 3 + }; + Q_ENUMS(Error) + + enum AreaMonitorFeature { + PersistentAreaMonitorFeature = 0x00000001, + AnyAreaMonitorFeature = 0xffffffff + }; + Q_DECLARE_FLAGS(AreaMonitorFeatures, AreaMonitorFeature) + + explicit QGeoAreaMonitorSource(QObject *parent); + virtual ~QGeoAreaMonitorSource(); + + static QGeoAreaMonitorSource *createDefaultSource(QObject *parent); + static QGeoAreaMonitorSource *createSource(const QString& sourceName, QObject *parent); + static QStringList availableSources(); + + virtual void setPositionInfoSource(QGeoPositionInfoSource *source); + virtual QGeoPositionInfoSource* positionInfoSource() const; + + QString sourceName() const; + + virtual Error error() const = 0; + virtual AreaMonitorFeatures supportedAreaMonitorFeatures() const = 0; + + virtual bool startMonitoring(const QGeoAreaMonitorInfo &monitor) = 0; + virtual bool stopMonitoring(const QGeoAreaMonitorInfo &monitor) = 0; + virtual bool requestUpdate(const QGeoAreaMonitorInfo &monitor, const char *signal) = 0; + + virtual QList activeMonitors() const = 0; + virtual QList activeMonitors(const QGeoShape &lookupArea) const = 0; + +Q_SIGNALS: + void areaEntered(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update); + void areaExited(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update); + void monitorExpired(const QGeoAreaMonitorInfo &monitor); + void error(QGeoAreaMonitorSource::Error error); + +private: + Q_DISABLE_COPY(QGeoAreaMonitorSource) + QGeoAreaMonitorSourcePrivate *d; +}; + + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeocircle.cpp b/src/positioning/qgeocircle.cpp new file mode 100644 index 0000000..3f2707a --- /dev/null +++ b/src/positioning/qgeocircle.cpp @@ -0,0 +1,385 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocircle.h" +#include "qgeocircle_p.h" + +#include "qgeocoordinate.h" +#include "qnumeric.h" + +#include "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" +QT_BEGIN_NAMESPACE + +/*! + \class QGeoCircle + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QGeoCircle class defines a circular geographic area. + + The circle is defined in terms of a QGeoCoordinate which specifies the + center of the circle and a qreal which specifies the radius of the circle + in meters. + + The circle is considered invalid if the center coordinate is invalid + or if the radius is less than zero. + + This class is a \l Q_GADGET since Qt 5.5. It can be + \l{Cpp_value_integration_positioning}{directly used from C++ and QML}. +*/ + +/*! + \property QGeoCircle::center + \brief This property holds the center coordinate for the geo circle. + + The circle is considered invalid if this property contains an invalid + coordinate. + + A default constructed QGeoCircle uses an invalid \l QGeoCoordinate + as center. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoCircle::radius + \brief This property holds the circle radius in meters. + + The circle is considered invalid if this property is negative. + + By default, the radius is initialized with \c -1. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +inline QGeoCirclePrivate *QGeoCircle::d_func() +{ + return static_cast(d_ptr.data()); +} + +inline const QGeoCirclePrivate *QGeoCircle::d_func() const +{ + return static_cast(d_ptr.constData()); +} + +struct CircleVariantConversions +{ + CircleVariantConversions() + { + QMetaType::registerConverter(); + QMetaType::registerConverter(); + } +}; + +Q_GLOBAL_STATIC(CircleVariantConversions, initCircleConversions) + +/*! + Constructs a new, invalid geo circle. +*/ +QGeoCircle::QGeoCircle() +: QGeoShape(new QGeoCirclePrivate) +{ + initCircleConversions(); +} + +/*! + Constructs a new geo circle centered at \a center and with a radius of \a radius meters. +*/ +QGeoCircle::QGeoCircle(const QGeoCoordinate ¢er, qreal radius) +{ + initCircleConversions(); + d_ptr = new QGeoCirclePrivate(center, radius); +} + +/*! + Constructs a new geo circle from the contents of \a other. +*/ +QGeoCircle::QGeoCircle(const QGeoCircle &other) +: QGeoShape(other) +{ + initCircleConversions(); +} + +/*! + Constructs a new geo circle from the contents of \a other. +*/ +QGeoCircle::QGeoCircle(const QGeoShape &other) +: QGeoShape(other) +{ + initCircleConversions(); + if (type() != QGeoShape::CircleType) + d_ptr = new QGeoCirclePrivate; +} + +/*! + Destroys this geo circle. +*/ +QGeoCircle::~QGeoCircle() {} + +/*! + Assigns \a other to this geo circle and returns a reference to this geo circle. +*/ +QGeoCircle &QGeoCircle::operator=(const QGeoCircle &other) +{ + QGeoShape::operator=(other); + return *this; +} + +/*! + Returns whether this geo circle is equal to \a other. +*/ +bool QGeoCircle::operator==(const QGeoCircle &other) const +{ + Q_D(const QGeoCircle); + + return *d == *other.d_func(); +} + +/*! + Returns whether this geo circle is not equal to \a other. +*/ +bool QGeoCircle::operator!=(const QGeoCircle &other) const +{ + Q_D(const QGeoCircle); + + return !(*d == *other.d_func()); +} + +bool QGeoCirclePrivate::isValid() const +{ + return m_center.isValid() && !qIsNaN(radius) && radius >= -1e-7; +} + +bool QGeoCirclePrivate::isEmpty() const +{ + return !isValid() || radius <= 1e-7; +} + +/*! + Sets the center coordinate of this geo circle to \a center. +*/ +void QGeoCircle::setCenter(const QGeoCoordinate ¢er) +{ + Q_D(QGeoCircle); + + d->m_center = center; +} + +/*! + Returns the center coordinate of this geo circle. Equivalent to QGeoShape::center(). +*/ +QGeoCoordinate QGeoCircle::center() const +{ + Q_D(const QGeoCircle); + + return d->center(); +} + +/*! + Sets the radius in meters of this geo circle to \a radius. +*/ +void QGeoCircle::setRadius(qreal radius) +{ + Q_D(QGeoCircle); + + d->radius = radius; +} + +/*! + Returns the radius in meters of this geo circle. +*/ +qreal QGeoCircle::radius() const +{ + Q_D(const QGeoCircle); + + return d->radius; +} + +bool QGeoCirclePrivate::contains(const QGeoCoordinate &coordinate) const +{ + if (!isValid() || !coordinate.isValid()) + return false; + + // see QTBUG-41447 for details + qreal distance = m_center.distanceTo(coordinate); + if (qFuzzyCompare(distance, radius) || distance <= radius) + return true; + + return false; +} + +QGeoCoordinate QGeoCirclePrivate::center() const +{ + return m_center; +} + +/*! + Extends the circle to include \a coordinate +*/ +void QGeoCirclePrivate::extendShape(const QGeoCoordinate &coordinate) +{ + if (!isValid() || !coordinate.isValid() || contains(coordinate)) + return; + + radius = m_center.distanceTo(coordinate); +} + +/*! + Translates this geo circle by \a degreesLatitude northwards and \a degreesLongitude eastwards. + + Negative values of \a degreesLatitude and \a degreesLongitude correspond to + southward and westward translation respectively. +*/ +void QGeoCircle::translate(double degreesLatitude, double degreesLongitude) +{ + // TODO handle dlat, dlon larger than 360 degrees + + Q_D(QGeoCircle); + + double lat = d->m_center.latitude(); + double lon = d->m_center.longitude(); + + lat += degreesLatitude; + lon += degreesLongitude; + + if (lon < -180.0) + lon += 360.0; + if (lon > 180.0) + lon -= 360.0; + + if (lat > 90.0) { + lat = 180.0 - lat; + if (lon < 0.0) + lon = 180.0; + else + lon -= 180; + } + + if (lat < -90.0) { + lat = 180.0 + lat; + if (lon < 0.0) + lon = 180.0; + else + lon -= 180; + } + + d->m_center = QGeoCoordinate(lat, lon); +} + +/*! + Returns a copy of this geo circle translated by \a degreesLatitude northwards and + \a degreesLongitude eastwards. + + Negative values of \a degreesLatitude and \a degreesLongitude correspond to + southward and westward translation respectively. + + \sa translate() +*/ +QGeoCircle QGeoCircle::translated(double degreesLatitude, double degreesLongitude) const +{ + QGeoCircle result(*this); + result.translate(degreesLatitude, degreesLongitude); + return result; +} + +/*! + Returns the geo circle properties as a string. + + \since 5.5 +*/ + +QString QGeoCircle::toString() const +{ + if (type() != QGeoShape::CircleType) { + qWarning("Not a circle"); + return QStringLiteral("QGeoCircle(not a circle)"); + } + + return QStringLiteral("QGeoCircle({%1, %2}, %3)") + .arg(center().latitude()) + .arg(center().longitude()) + .arg(radius()); +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoCirclePrivate::QGeoCirclePrivate() +: QGeoShapePrivate(QGeoShape::CircleType), radius(-1.0) +{ +} + +QGeoCirclePrivate::QGeoCirclePrivate(const QGeoCoordinate ¢er, qreal radius) +: QGeoShapePrivate(QGeoShape::CircleType), m_center(center), radius(radius) +{ +} + +QGeoCirclePrivate::QGeoCirclePrivate(const QGeoCirclePrivate &other) +: QGeoShapePrivate(QGeoShape::CircleType), m_center(other.m_center), + radius(other.radius) +{ +} + +QGeoCirclePrivate::~QGeoCirclePrivate() {} + +QGeoShapePrivate *QGeoCirclePrivate::clone() const +{ + return new QGeoCirclePrivate(*this); +} + +bool QGeoCirclePrivate::operator==(const QGeoShapePrivate &other) const +{ + if (!QGeoShapePrivate::operator==(other)) + return false; + + const QGeoCirclePrivate &otherCircle = static_cast(other); + + return radius == otherCircle.radius && m_center == otherCircle.m_center; +} + +QT_END_NAMESPACE + diff --git a/src/positioning/qgeocircle.h b/src/positioning/qgeocircle.h new file mode 100644 index 0000000..b4b6c45 --- /dev/null +++ b/src/positioning/qgeocircle.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCIRCLE_H +#define QGEOCIRCLE_H + +#include + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; +class QGeoCirclePrivate; + +class Q_POSITIONING_EXPORT QGeoCircle : public QGeoShape +{ + Q_GADGET + Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter) + Q_PROPERTY(qreal radius READ radius WRITE setRadius) + +public: + QGeoCircle(); + QGeoCircle(const QGeoCoordinate ¢er, qreal radius = -1.0); + QGeoCircle(const QGeoCircle &other); + QGeoCircle(const QGeoShape &other); + + ~QGeoCircle(); + + QGeoCircle &operator=(const QGeoCircle &other); + + using QGeoShape::operator==; + bool operator==(const QGeoCircle &other) const; + + using QGeoShape::operator!=; + bool operator!=(const QGeoCircle &other) const; + + void setCenter(const QGeoCoordinate ¢er); + QGeoCoordinate center() const; + + void setRadius(qreal radius); + qreal radius() const; + + void translate(double degreesLatitude, double degreesLongitude); + QGeoCircle translated(double degreesLatitude, double degreesLongitude) const; + + Q_INVOKABLE QString toString() const; + +private: + inline QGeoCirclePrivate *d_func(); + inline const QGeoCirclePrivate *d_func() const; +}; + +Q_DECLARE_TYPEINFO(QGeoCircle, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoCircle) + +#endif + diff --git a/src/positioning/qgeocircle_p.h b/src/positioning/qgeocircle_p.h new file mode 100644 index 0000000..311aba8 --- /dev/null +++ b/src/positioning/qgeocircle_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCIRCLE_P_H +#define QGEOCIRCLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeoshape_p.h" +#include "qgeocoordinate.h" + +QT_BEGIN_NAMESPACE + +class QGeoCirclePrivate : public QGeoShapePrivate +{ +public: + QGeoCirclePrivate(); + QGeoCirclePrivate(const QGeoCoordinate ¢er, qreal radius); + QGeoCirclePrivate(const QGeoCirclePrivate &other); + ~QGeoCirclePrivate(); + + bool isValid() const Q_DECL_OVERRIDE; + bool isEmpty() const Q_DECL_OVERRIDE; + bool contains(const QGeoCoordinate &coordinate) const Q_DECL_OVERRIDE; + + QGeoCoordinate center() const Q_DECL_OVERRIDE; + + void extendShape(const QGeoCoordinate &coordinate) Q_DECL_OVERRIDE; + + QGeoShapePrivate *clone() const Q_DECL_OVERRIDE; + + bool operator==(const QGeoShapePrivate &other) const Q_DECL_OVERRIDE; + + QGeoCoordinate m_center; + qreal radius; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeocoordinate.cpp b/src/positioning/qgeocoordinate.cpp new file mode 100644 index 0000000..0386e85 --- /dev/null +++ b/src/positioning/qgeocoordinate.cpp @@ -0,0 +1,783 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeocoordinate.h" +#include "qgeocoordinate_p.h" +#include "qlocationutils_p.h" + +#include +#include +#include +#include +#include + +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +QT_BEGIN_NAMESPACE + +static const double qgeocoordinate_EARTH_MEAN_RADIUS = 6371.0072; + +inline static double qgeocoordinate_degToRad(double deg) +{ + return deg * M_PI / 180; +} +inline static double qgeocoordinate_radToDeg(double rad) +{ + return rad * 180 / M_PI; +} + + +QGeoCoordinatePrivate::QGeoCoordinatePrivate(): + lat(qQNaN()), + lng(qQNaN()), + alt(qQNaN()) +{} + +QGeoCoordinatePrivate::QGeoCoordinatePrivate(const QGeoCoordinatePrivate &other) + : QSharedData(other), + lat(other.lat), + lng(other.lng), + alt(other.alt) +{} + +QGeoCoordinatePrivate::~QGeoCoordinatePrivate() +{} + + +QGeoMercatorCoordinatePrivate::QGeoMercatorCoordinatePrivate(): + QGeoCoordinatePrivate(), + m_mercatorX(qQNaN()), + m_mercatorY(qQNaN()) +{} + +QGeoMercatorCoordinatePrivate::QGeoMercatorCoordinatePrivate(const QGeoMercatorCoordinatePrivate &other) + : QGeoCoordinatePrivate(other), + m_mercatorX(other.m_mercatorX), + m_mercatorY(other.m_mercatorY) +{} + +QGeoMercatorCoordinatePrivate::~QGeoMercatorCoordinatePrivate() +{} + +/*! + \class QGeoCoordinate + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QGeoCoordinate class defines a geographical position on the surface of the Earth. + + A QGeoCoordinate is defined by latitude, longitude, and optionally, altitude. + + Use type() to determine whether a coordinate is a 2D coordinate (has + latitude and longitude only) or 3D coordinate (has latitude, longitude + and altitude). Use distanceTo() and azimuthTo() to calculate the distance + and bearing between coordinates. + + The coordinate values should be specified using the WGS84 datum. For more information + on geographical terms see this article on \l {http://en.wikipedia.org/wiki/Geographic_coordinate_system}{coordinates} and + another on \l {http://en.wikipedia.org/wiki/Geodetic_system}{geodetic systems} + including WGS84. + + Azimuth in this context is equivalent to a compass bearing based on true north. + + This class is a \l Q_GADGET since Qt 5.5. It can be + \l{Cpp_value_integration_positioning}{directly used from C++ and QML}. +*/ + +/*! + \enum QGeoCoordinate::CoordinateType + Defines the types of a coordinate. + + \value InvalidCoordinate An invalid coordinate. A coordinate is invalid if its latitude or longitude values are invalid. + \value Coordinate2D A coordinate with valid latitude and longitude values. + \value Coordinate3D A coordinate with valid latitude and longitude values, and also an altitude value. +*/ + +/*! + \enum QGeoCoordinate::CoordinateFormat + Defines the possible formatting options for toString(). + + \value Degrees Returns a string representation of the coordinates in decimal degrees format. + \value DegreesWithHemisphere Returns a string representation of the coordinates in decimal degrees format, using 'N', 'S', 'E' or 'W' to indicate the hemispheres of the coordinates. + \value DegreesMinutes Returns a string representation of the coordinates in degrees-minutes format. + \value DegreesMinutesWithHemisphere Returns a string representation of the coordinates in degrees-minutes format, using 'N', 'S', 'E' or 'W' to indicate the hemispheres of the coordinates. + \value DegreesMinutesSeconds Returns a string representation of the coordinates in degrees-minutes-seconds format. + \value DegreesMinutesSecondsWithHemisphere Returns a string representation of the coordinates in degrees-minutes-seconds format, using 'N', 'S', 'E' or 'W' to indicate the hemispheres of the coordinates. + + \sa toString() +*/ + +/*! + \property QGeoCoordinate::latitude + \brief This property holds the latitude in decimal degrees. + + The property is undefined (\l {qQNaN()}) if the latitude has not been set. + A positive latitude indicates the Northern Hemisphere, and a negative + latitude indicates the Southern Hemisphere. When setting the latitude the + new value should be in the + \l {http://en.wikipedia.org/wiki/World_Geodetic_System}{WGS84} datum format. + + To be valid, the latitude must be between -90 to 90 inclusive. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoCoordinate::longitude + \brief This property holds the longitude in decimal degrees. + + The property is undefined (\l {qQNaN()}) if the longitude has not been set. + A positive longitude indicates the Eastern Hemisphere, and a negative + longitude indicates the Western Hemisphere. When setting the longitude the + new value should be in the + \l {http://en.wikipedia.org/wiki/World_Geodetic_System}{WGS84} datum format. + + To be valid, the longitude must be between -180 to 180 inclusive. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoCoordinate::altitude + \brief This property holds the altitude in meters above sea level. + + The property is undefined (\l {qQNaN()}) if the altitude has not been set. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoCoordinate::isValid + \brief This property holds the validity of this geo coordinate. + + The geo coordinate is valid if the \l [CPP]{longitude} and \l [CPP]{latitude} + properties have been set to valid values. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + Constructs a coordinate. The coordinate will be invalid until + setLatitude() and setLongitude() have been called. +*/ +QGeoCoordinate::QGeoCoordinate() + : d(new QGeoCoordinatePrivate) +{ +} + +/*! + Constructs a coordinate with the given \a latitude and \a longitude. + + If the latitude is not between -90 to 90 inclusive, or the longitude + is not between -180 to 180 inclusive, none of the values are set and + the type() will be QGeoCoordinate::InvalidCoordinate. + + \sa isValid() +*/ +QGeoCoordinate::QGeoCoordinate(double latitude, double longitude) + : d(new QGeoCoordinatePrivate) +{ + if (QLocationUtils::isValidLat(latitude) && QLocationUtils::isValidLong(longitude)) { + d->lat = latitude; + d->lng = longitude; + } +} + +/*! + Constructs a coordinate with the given \a latitude, \a longitude + and \a altitude. + + If the latitude is not between -90 to 90 inclusive, or the longitude + is not between -180 to 180 inclusive, none of the values are set and + the type() will be QGeoCoordinate::InvalidCoordinate. + + Note that \a altitude specifies the meters above sea level. + + \sa isValid() +*/ +QGeoCoordinate::QGeoCoordinate(double latitude, double longitude, double altitude) + : d(new QGeoCoordinatePrivate) +{ + if (QLocationUtils::isValidLat(latitude) && QLocationUtils::isValidLong(longitude)) { + d->lat = latitude; + d->lng = longitude; + d->alt = altitude; + } +} + +/*! + Constructs a coordinate from the contents of \a other. +*/ +QGeoCoordinate::QGeoCoordinate(const QGeoCoordinate &other) + : d(other.d) +{} + +/*! + Assigns \a other to this coordinate and returns a reference to this coordinate. +*/ +QGeoCoordinate &QGeoCoordinate::operator=(const QGeoCoordinate &other) +{ + if (this == &other) + return *this; + + d = other.d; + return (*this); +} + +/*! + Destroys the coordinate object. +*/ +QGeoCoordinate::~QGeoCoordinate() +{ +} + +/*! + Returns true if the latitude, longitude and altitude of this + coordinate are the same as those of \a other. + + The longitude will be ignored if the latitude is +/- 90 degrees. +*/ +bool QGeoCoordinate::operator==(const QGeoCoordinate &other) const +{ + bool latEqual = (qIsNaN(d->lat) && qIsNaN(other.d->lat)) + || qFuzzyCompare(d->lat, other.d->lat); + bool lngEqual = (qIsNaN(d->lng) && qIsNaN(other.d->lng)) + || qFuzzyCompare(d->lng, other.d->lng); + bool altEqual = (qIsNaN(d->alt) && qIsNaN(other.d->alt)) + || qFuzzyCompare(d->alt, other.d->alt); + + if (!qIsNaN(d->lat) && ((d->lat == 90.0) || (d->lat == -90.0))) + lngEqual = true; + + return (latEqual && lngEqual && altEqual); +} + +/*! + \fn bool QGeoCoordinate::operator!=(const QGeoCoordinate &other) const; + + Returns true if the latitude, longitude or altitude of this + coordinate are not the same as those of \a other. +*/ + +/*! + Returns true if the \l longitude and \l latitude are valid. +*/ +bool QGeoCoordinate::isValid() const +{ + CoordinateType t = type(); + return t == Coordinate2D || t == Coordinate3D; +} + +/*! + Returns the type of this coordinate. +*/ +QGeoCoordinate::CoordinateType QGeoCoordinate::type() const +{ + if (QLocationUtils::isValidLat(d->lat) + && QLocationUtils::isValidLong(d->lng)) { + if (qIsNaN(d->alt)) + return Coordinate2D; + return Coordinate3D; + } + return InvalidCoordinate; +} + + +/*! + Returns the latitude, in decimal degrees. The return value is undefined + if the latitude has not been set. + + A positive latitude indicates the Northern Hemisphere, and a negative + latitude indicates the Southern Hemisphere. + + \sa setLatitude(), type() +*/ +double QGeoCoordinate::latitude() const +{ + return d->lat; +} + +/*! + Sets the latitude (in decimal degrees) to \a latitude. The value should + be in the WGS84 datum. + + To be valid, the latitude must be between -90 to 90 inclusive. + + \sa latitude() +*/ +void QGeoCoordinate::setLatitude(double latitude) +{ + d->lat = latitude; +} + +/*! + Returns the longitude, in decimal degrees. The return value is undefined + if the longitude has not been set. + + A positive longitude indicates the Eastern Hemisphere, and a negative + longitude indicates the Western Hemisphere. + + \sa setLongitude(), type() +*/ +double QGeoCoordinate::longitude() const +{ + return d->lng; +} + +/*! + Sets the longitude (in decimal degrees) to \a longitude. The value should + be in the WGS84 datum. + + To be valid, the longitude must be between -180 to 180 inclusive. + + \sa longitude() +*/ +void QGeoCoordinate::setLongitude(double longitude) +{ + d->lng = longitude; +} + +/*! + Returns the altitude (meters above sea level). + + The return value is undefined if the altitude has not been set. + + \sa setAltitude(), type() +*/ +double QGeoCoordinate::altitude() const +{ + return d->alt; +} + +/*! + Sets the altitude (meters above sea level) to \a altitude. + + \sa altitude() +*/ +void QGeoCoordinate::setAltitude(double altitude) +{ + d->alt = altitude; +} + +/*! + Returns the distance (in meters) from this coordinate to the coordinate + specified by \a other. Altitude is not used in the calculation. + + This calculation returns the great-circle distance between the two + coordinates, with an assumption that the Earth is spherical for the + purpose of this calculation. + + Returns 0 if the type of this coordinate or the type of \a other is + QGeoCoordinate::InvalidCoordinate. +*/ +qreal QGeoCoordinate::distanceTo(const QGeoCoordinate &other) const +{ + if (type() == QGeoCoordinate::InvalidCoordinate + || other.type() == QGeoCoordinate::InvalidCoordinate) { + return 0; + } + + // Haversine formula + double dlat = qgeocoordinate_degToRad(other.d->lat - d->lat); + double dlon = qgeocoordinate_degToRad(other.d->lng - d->lng); + double haversine_dlat = sin(dlat / 2.0); + haversine_dlat *= haversine_dlat; + double haversine_dlon = sin(dlon / 2.0); + haversine_dlon *= haversine_dlon; + double y = haversine_dlat + + cos(qgeocoordinate_degToRad(d->lat)) + * cos(qgeocoordinate_degToRad(other.d->lat)) + * haversine_dlon; + double x = 2 * asin(sqrt(y)); + return qreal(x * qgeocoordinate_EARTH_MEAN_RADIUS * 1000); +} + +/*! + Returns the azimuth (or bearing) in degrees from this coordinate to the + coordinate specified by \a other. Altitude is not used in the calculation. + + The bearing returned is the bearing from the origin to \a other along the + great-circle between the two coordinates. There is an assumption that the + Earth is spherical for the purpose of this calculation. + + Returns 0 if the type of this coordinate or the type of \a other is + QGeoCoordinate::InvalidCoordinate. +*/ +qreal QGeoCoordinate::azimuthTo(const QGeoCoordinate &other) const +{ + if (type() == QGeoCoordinate::InvalidCoordinate + || other.type() == QGeoCoordinate::InvalidCoordinate) { + return 0; + } + + double dlon = qgeocoordinate_degToRad(other.d->lng - d->lng); + double lat1Rad = qgeocoordinate_degToRad(d->lat); + double lat2Rad = qgeocoordinate_degToRad(other.d->lat); + + double y = sin(dlon) * cos(lat2Rad); + double x = cos(lat1Rad) * sin(lat2Rad) - sin(lat1Rad) * cos(lat2Rad) * cos(dlon); + + double azimuth = qgeocoordinate_radToDeg(atan2(y, x)) + 360.0; + double whole; + double fraction = modf(azimuth, &whole); + return qreal((int(whole + 360) % 360) + fraction); +} + +void QGeoCoordinatePrivate::atDistanceAndAzimuth(const QGeoCoordinate &coord, + qreal distance, qreal azimuth, + double *lon, double *lat) +{ + double latRad = qgeocoordinate_degToRad(coord.d->lat); + double lonRad = qgeocoordinate_degToRad(coord.d->lng); + double cosLatRad = cos(latRad); + double sinLatRad = sin(latRad); + + double azimuthRad = qgeocoordinate_degToRad(azimuth); + + double ratio = (distance / (qgeocoordinate_EARTH_MEAN_RADIUS * 1000.0)); + double cosRatio = cos(ratio); + double sinRatio = sin(ratio); + + double resultLatRad = asin(sinLatRad * cosRatio + + cosLatRad * sinRatio * cos(azimuthRad)); + double resultLonRad = lonRad + atan2(sin(azimuthRad) * sinRatio * cosLatRad, + cosRatio - sinLatRad * sin(resultLatRad)); + + *lat = qgeocoordinate_radToDeg(resultLatRad); + *lon = qgeocoordinate_radToDeg(resultLonRad); +} + +/*! + Returns the coordinate that is reached by traveling \a distance meters + from the current coordinate at \a azimuth (or bearing) along a great-circle. + There is an assumption that the Earth is spherical for the purpose of this + calculation. + + The altitude will have \a distanceUp added to it. + + Returns an invalid coordinate if this coordinate is invalid. +*/ +QGeoCoordinate QGeoCoordinate::atDistanceAndAzimuth(qreal distance, qreal azimuth, qreal distanceUp) const +{ + if (!isValid()) + return QGeoCoordinate(); + + double resultLon, resultLat; + QGeoCoordinatePrivate::atDistanceAndAzimuth(*this, distance, azimuth, + &resultLon, &resultLat); + + if (resultLon > 180.0) + resultLon -= 360.0; + else if (resultLon < -180.0) + resultLon += 360.0; + + double resultAlt = d->alt + distanceUp; + return QGeoCoordinate(resultLat, resultLon, resultAlt); +} + +/*! + Returns this coordinate as a string in the specified \a format. + + For example, if this coordinate has a latitude of -27.46758, a longitude + of 153.027892 and an altitude of 28.1, these are the strings + returned depending on \a format: + + \table + \header + \li \a format value + \li Returned string + \row + \li \l Degrees + \li -27.46758\unicode{0xB0}, 153.02789\unicode{0xB0}, 28.1m + \row + \li \l DegreesWithHemisphere + \li 27.46758\unicode{0xB0} S, 153.02789\unicode{0xB0} E, 28.1m + \row + \li \l DegreesMinutes + \li -27\unicode{0xB0} 28.054', 153\unicode{0xB0} 1.673', 28.1m + \row + \li \l DegreesMinutesWithHemisphere + \li 27\unicode{0xB0} 28.054 S', 153\unicode{0xB0} 1.673' E, 28.1m + \row + \li \l DegreesMinutesSeconds + \li -27\unicode{0xB0} 28' 3.2", 153\unicode{0xB0} 1' 40.4", 28.1m + \row + \li \l DegreesMinutesSecondsWithHemisphere + \li 27\unicode{0xB0} 28' 3.2" S, 153\unicode{0xB0} 1' 40.4" E, 28.1m + \endtable + + The altitude field is omitted if no altitude is set. + + If the coordinate is invalid, an empty string is returned. +*/ +QString QGeoCoordinate::toString(CoordinateFormat format) const +{ + if (type() == QGeoCoordinate::InvalidCoordinate) + return QString(); + + QString latStr; + QString longStr; + + double absLat = qAbs(d->lat); + double absLng = qAbs(d->lng); + QChar symbol(0x00B0); // degrees symbol + + switch (format) { + case Degrees: + case DegreesWithHemisphere: { + latStr = QString::number(absLat, 'f', 5) + symbol; + longStr = QString::number(absLng, 'f', 5) + symbol; + break; + } + case DegreesMinutes: + case DegreesMinutesWithHemisphere: { + double latMin = (absLat - int(absLat)) * 60; + double lngMin = (absLng - int(absLng)) * 60; + + if (qRound(latMin) >= 60) { + absLat++; + latMin = qAbs(latMin - 60.0f); + //avoid invalid latitude due to latMin rounding below + if (qRound(absLat) >= 90) + latMin = 0.0f; + } + if (qRound(lngMin) >= 60) { + absLng++; + lngMin = qAbs(lngMin - 60.0f); + // avoid invalid longitude due to lngMin rounding below + if (qRound(absLng) >= 180) + lngMin = 0.0f; + } + + latStr = QString::fromLatin1("%1%2 %3'") + .arg(QString::number(int(absLat))) + .arg(symbol) + .arg(QString::number(latMin, 'f', 3)); + longStr = QString::fromLatin1("%1%2 %3'") + .arg(QString::number(int(absLng))) + .arg(symbol) + .arg(QString::number(lngMin, 'f', 3)); + break; + } + case DegreesMinutesSeconds: + case DegreesMinutesSecondsWithHemisphere: { + double latMin = (absLat - int(absLat)) * 60; + double lngMin = (absLng - int(absLng)) * 60; + double latSec = (latMin - int(latMin)) * 60; + double lngSec = (lngMin - int(lngMin)) * 60; + + // overflow to full minutes + if (qRound(latSec) >= 60) { + latMin++; + latSec = qAbs(latSec - 60.0f); + // overflow to full degrees + if (qRound(latMin) >= 60) { + absLat++; + latMin = qAbs(latMin - 60.0f); + // avoid invalid latitude due to latSec rounding below + if (qRound(absLat) >= 90) + latSec = 0.0f; + } + } + if (qRound(lngSec) >= 60) { + lngMin++; + lngSec = qAbs(lngSec - 60.0f); + if (qRound(lngMin) >= 60) { + absLng++; + lngMin = qAbs(lngMin - 60.0f); + // avoid invalid longitude due to lngSec rounding below + if (qRound(absLng) >= 180) + lngSec = 0.0f; + } + } + + latStr = QString::fromLatin1("%1%2 %3' %4\"") + .arg(QString::number(int(absLat))) + .arg(symbol) + .arg(QString::number(int(latMin))) + .arg(QString::number(latSec, 'f', 1)); + longStr = QString::fromLatin1("%1%2 %3' %4\"") + .arg(QString::number(int(absLng))) + .arg(symbol) + .arg(QString::number(int(lngMin))) + .arg(QString::number(lngSec, 'f', 1)); + break; + } + } + + // now add the "-" to the start, or append the hemisphere char + switch (format) { + case Degrees: + case DegreesMinutes: + case DegreesMinutesSeconds: { + if (d->lat < 0) + latStr.insert(0, QStringLiteral("-")); + if (d->lng < 0) + longStr.insert(0, QStringLiteral("-")); + break; + } + case DegreesWithHemisphere: + case DegreesMinutesWithHemisphere: + case DegreesMinutesSecondsWithHemisphere: { + if (d->lat < 0) + latStr.append(QString::fromLatin1(" S")); + else if (d->lat > 0) + latStr.append(QString::fromLatin1(" N")); + if (d->lng < 0) + longStr.append(QString::fromLatin1(" W")); + else if (d->lng > 0) + longStr.append(QString::fromLatin1(" E")); + break; + } + } + + if (qIsNaN(d->alt)) + return QString::fromLatin1("%1, %2").arg(latStr, longStr); + return QString::fromLatin1("%1, %2, %3m").arg(latStr, longStr, QString::number(d->alt)); +} + +QGeoCoordinate::QGeoCoordinate(QGeoCoordinatePrivate &dd): + d(&dd) +{ +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QGeoCoordinate &coord) +{ + QDebugStateSaver saver(dbg); + double lat = coord.latitude(); + double lng = coord.longitude(); + + dbg.nospace() << "QGeoCoordinate("; + if (qIsNaN(lat)) + dbg << '?'; + else + dbg << lat; + dbg << ", "; + if (qIsNaN(lng)) + dbg << '?'; + else + dbg << lng; + if (coord.type() == QGeoCoordinate::Coordinate3D) { + dbg << ", "; + dbg << coord.altitude(); + } + dbg << ')'; + return dbg; +} +#endif + +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QGeoCoordinate &coordinate) + + \relates QGeoCoordinate + + Writes the given \a coordinate to the specified \a stream. + + \sa {Serializing Qt Data Types} +*/ + +QDataStream &operator<<(QDataStream &stream, const QGeoCoordinate &coordinate) +{ + stream << coordinate.latitude(); + stream << coordinate.longitude(); + stream << coordinate.altitude(); + return stream; +} +#endif + +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator>>(QDataStream &stream, QGeoCoordinate &coordinate) + \relates QGeoCoordinate + + Reads a coordinate from the specified \a stream into the given + \a coordinate. + + \sa {Serializing Qt Data Types} +*/ + +QDataStream &operator>>(QDataStream &stream, QGeoCoordinate &coordinate) +{ + double value; + stream >> value; + coordinate.setLatitude(value); + stream >> value; + coordinate.setLongitude(value); + stream >> value; + coordinate.setAltitude(value); + return stream; +} +#endif + +/*! \fn uint qHash(const QGeoCoordinate &coordinate, uint seed = 0) + \relates QHash + \since Qt 5.7 + + Returns a hash value for \a coordinate, using \a seed to seed the calculation. +*/ +uint qHash(const QGeoCoordinate &coordinate, uint seed) +{ + QtPrivate::QHashCombine hash; + // north and south pole are geographically equivalent (no matter the longitude) + if (coordinate.latitude() != 90.0 && coordinate.latitude() != -90.0) + seed = hash(seed, coordinate.longitude()); + seed = hash(seed, coordinate.latitude()); + seed = hash(seed, coordinate.altitude()); + return seed; +} + +QT_END_NAMESPACE diff --git a/src/positioning/qgeocoordinate.h b/src/positioning/qgeocoordinate.h new file mode 100644 index 0000000..ddb6274 --- /dev/null +++ b/src/positioning/qgeocoordinate.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCOORDINATE_H +#define QGEOCOORDINATE_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDebug; +class QDataStream; + +class QGeoCoordinatePrivate; +class Q_POSITIONING_EXPORT QGeoCoordinate +{ + Q_GADGET + + Q_PROPERTY(double latitude READ latitude WRITE setLatitude) + Q_PROPERTY(double longitude READ longitude WRITE setLongitude) + Q_PROPERTY(double altitude READ altitude WRITE setAltitude) + Q_PROPERTY(bool isValid READ isValid) + +public: + + enum CoordinateType { + InvalidCoordinate, + Coordinate2D, + Coordinate3D + }; + + enum CoordinateFormat { + Degrees, + DegreesWithHemisphere, + DegreesMinutes, + DegreesMinutesWithHemisphere, + DegreesMinutesSeconds, + DegreesMinutesSecondsWithHemisphere + }; + + QGeoCoordinate(); + QGeoCoordinate(double latitude, double longitude); + QGeoCoordinate(double latitude, double longitude, double altitude); + QGeoCoordinate(const QGeoCoordinate &other); + ~QGeoCoordinate(); + + QGeoCoordinate &operator=(const QGeoCoordinate &other); + + bool operator==(const QGeoCoordinate &other) const; + inline bool operator!=(const QGeoCoordinate &other) const { + return !operator==(other); + } + + bool isValid() const; + CoordinateType type() const; + + void setLatitude(double latitude); + double latitude() const; + + void setLongitude(double longitude); + double longitude() const; + + void setAltitude(double altitude); + double altitude() const; + + Q_INVOKABLE qreal distanceTo(const QGeoCoordinate &other) const; + Q_INVOKABLE qreal azimuthTo(const QGeoCoordinate &other) const; + + Q_INVOKABLE QGeoCoordinate atDistanceAndAzimuth(qreal distance, qreal azimuth, qreal distanceUp = 0.0) const; + + Q_INVOKABLE QString toString(CoordinateFormat format = DegreesMinutesSecondsWithHemisphere) const; + +private: + QGeoCoordinate(QGeoCoordinatePrivate &dd); + QSharedDataPointer d; + friend class QGeoCoordinatePrivate; + friend class QQuickGeoCoordinateAnimation; +}; + +Q_DECLARE_TYPEINFO(QGeoCoordinate, Q_MOVABLE_TYPE); + +#ifndef QT_NO_DEBUG_STREAM +Q_POSITIONING_EXPORT QDebug operator<<(QDebug, const QGeoCoordinate &); +#endif + +Q_POSITIONING_EXPORT uint qHash(const QGeoCoordinate &coordinate, uint seed = 0); + +#ifndef QT_NO_DATASTREAM +Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &stream, const QGeoCoordinate &coordinate); +Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &stream, QGeoCoordinate &coordinate); +#endif + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoCoordinate) + +#endif diff --git a/src/positioning/qgeocoordinate_p.h b/src/positioning/qgeocoordinate_p.h new file mode 100644 index 0000000..e00cbfa --- /dev/null +++ b/src/positioning/qgeocoordinate_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCOORDINATE_P_H +#define QGEOCOORDINATE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include "qgeocoordinate.h" + +QT_BEGIN_NAMESPACE + +class QGeoCoordinatePrivate : public QSharedData +{ +public: + QGeoCoordinatePrivate(); + QGeoCoordinatePrivate(const QGeoCoordinatePrivate &other); + ~QGeoCoordinatePrivate(); + + double lat; + double lng; + double alt; + + static void atDistanceAndAzimuth(const QGeoCoordinate &coord, + qreal distance, qreal azimuth, + double *lon, double *lat); + static const QGeoCoordinatePrivate *get(const QGeoCoordinate *c) { + return c->d.constData(); + } +}; + +class Q_POSITIONING_EXPORT QGeoMercatorCoordinatePrivate : public QGeoCoordinatePrivate +{ +public: + QGeoMercatorCoordinatePrivate(); + QGeoMercatorCoordinatePrivate(const QGeoMercatorCoordinatePrivate &other); + ~QGeoMercatorCoordinatePrivate(); + + double m_mercatorX; + double m_mercatorY; +}; + + +QT_END_NAMESPACE + +#endif // QGEOCOORDINATE_P_H diff --git a/src/positioning/qgeolocation.cpp b/src/positioning/qgeolocation.cpp new file mode 100644 index 0000000..62e1a6a --- /dev/null +++ b/src/positioning/qgeolocation.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeolocation.h" +#include "qgeolocation_p.h" + +QT_USE_NAMESPACE + +QGeoLocationPrivate::QGeoLocationPrivate() + : QSharedData() +{ +} + +QGeoLocationPrivate::QGeoLocationPrivate(const QGeoLocationPrivate &other) + : QSharedData() +{ + this->address = other.address; + this->coordinate = other.coordinate; + this->viewport = other.viewport; +} + +QGeoLocationPrivate::~QGeoLocationPrivate() +{ +} + +bool QGeoLocationPrivate::operator==(const QGeoLocationPrivate &other) const +{ + return (this->address == other.address + && this->coordinate == other.coordinate + && this->viewport == other.viewport); + +} + +bool QGeoLocationPrivate::isEmpty() const +{ + return (address.isEmpty() + && !coordinate.isValid() + && viewport.isEmpty() + ); +} + +/*! + \class QGeoLocation + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \ingroup QtLocation-places + \ingroup QtLocation-places-data + \since 5.2 + + \brief The QGeoLocation class represents basic information about a location. + + A QGeoLocation consists of a coordinate and corresponding address, along with an optional + bounding box which is the recommended region to be displayed when viewing the location. +*/ + +/*! + \fn bool QGeoLocation::operator!=(const QGeoLocation &other) const + + Returns true if this location is not equal to \a other, otherwise returns false. +*/ + +/*! + Constructs an new location object. +*/ +QGeoLocation::QGeoLocation() + : d(new QGeoLocationPrivate) +{ +} + +/*! + Constructs a copy of \a other +*/ +QGeoLocation::QGeoLocation(const QGeoLocation &other) + :d(other.d) +{ +} + +/*! + Destroys the location object. +*/ +QGeoLocation::~QGeoLocation() +{ +} + +/*! + Assigns \a other to this location and returns a reference to this location. +*/ +QGeoLocation &QGeoLocation::operator =(const QGeoLocation &other) +{ + if (this == &other) + return *this; + + d = other.d; + return *this; +} + +/*! + Returns true if this location is equal to \a other, + otherwise returns false. +*/ +bool QGeoLocation::operator==(const QGeoLocation &other) const +{ + return (*(d.constData()) == *(other.d.constData())); +} + +/*! + Returns the address of the location. +*/ +QGeoAddress QGeoLocation::address() const +{ + return d->address; +} + +/*! + Sets the \a address of the location. +*/ +void QGeoLocation::setAddress(const QGeoAddress &address) +{ + d->address = address; +} + +/*! + Returns the coordinate of the location. +*/ +QGeoCoordinate QGeoLocation::coordinate() const +{ + return d->coordinate; +} + +/*! + Sets the \a coordinate of the location. +*/ +void QGeoLocation::setCoordinate(const QGeoCoordinate &coordinate) +{ + d->coordinate = coordinate; +} + +/*! + Returns a bounding box which represents the recommended region + to display when viewing this location. + + For example, a building's location may have a region centered around the building, + but the region is large enough to show it's immediate surrounding geographical + context. +*/ +QGeoRectangle QGeoLocation::boundingBox() const +{ + return d->viewport; +} + +/*! + Sets the \a boundingBox of the location. +*/ +void QGeoLocation::setBoundingBox(const QGeoRectangle &boundingBox) +{ + d->viewport = boundingBox; +} + +/*! + Returns true if all fields of the location are 0; otherwise returns false. +*/ +bool QGeoLocation::isEmpty() const +{ + return d->isEmpty(); +} diff --git a/src/positioning/qgeolocation.h b/src/positioning/qgeolocation.h new file mode 100644 index 0000000..580b2fb --- /dev/null +++ b/src/positioning/qgeolocation.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOLOCATION_H +#define QGEOLOCATION_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoAddress; +class QGeoCoordinate; +class QGeoRectangle; +class QGeoLocationPrivate; + +class Q_POSITIONING_EXPORT QGeoLocation +{ +public: + QGeoLocation(); + QGeoLocation(const QGeoLocation &other); + + ~QGeoLocation(); + + QGeoLocation &operator=(const QGeoLocation &other); + + bool operator==(const QGeoLocation &other) const; + bool operator!=(const QGeoLocation &other) const { + return !(other == *this); + } + + QGeoAddress address() const; + void setAddress(const QGeoAddress &address); + QGeoCoordinate coordinate() const; + void setCoordinate(const QGeoCoordinate &position); + QGeoRectangle boundingBox() const; + void setBoundingBox(const QGeoRectangle &box); + + bool isEmpty() const; + +private: + QSharedDataPointer d; +}; + +Q_DECLARE_TYPEINFO(QGeoLocation, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoLocation) + +#endif diff --git a/src/positioning/qgeolocation_p.h b/src/positioning/qgeolocation_p.h new file mode 100644 index 0000000..a12e4cb --- /dev/null +++ b/src/positioning/qgeolocation_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOLOCATION_P_H +#define QGEOLOCATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoLocationPrivate : public QSharedData +{ +public: + QGeoLocationPrivate(); + QGeoLocationPrivate(const QGeoLocationPrivate &other); + + ~QGeoLocationPrivate(); + + bool operator==(const QGeoLocationPrivate &other) const; + + bool isEmpty() const; + + QGeoAddress address; + QGeoCoordinate coordinate; + QGeoRectangle viewport; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeopositioninfo.cpp b/src/positioning/qgeopositioninfo.cpp new file mode 100644 index 0000000..84b7fa1 --- /dev/null +++ b/src/positioning/qgeopositioninfo.cpp @@ -0,0 +1,359 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeopositioninfo.h" + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoPositionInfoPrivate +{ +public: + QDateTime timestamp; + QGeoCoordinate coord; + QHash doubleAttribs; +}; + +/*! + \class QGeoPositionInfo + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QGeoPositionInfo class contains information gathered on a global position, direction and velocity at a particular point in time. + + A QGeoPositionInfo contains, at a minimum, a geographical coordinate and + a timestamp. It may also have heading and speed measurements as well as + estimates of the accuracy of the provided data. + + \sa QGeoPositionInfoSource +*/ + +/*! + \enum QGeoPositionInfo::Attribute + Defines the attributes for positional information. + + \value Direction The bearing measured in degrees clockwise from true north to the direction of travel. + \value GroundSpeed The ground speed, in meters/sec. + \value VerticalSpeed The vertical speed, in meters/sec. + \value MagneticVariation The angle between the horizontal component of the magnetic field and true north, in degrees. Also known as magnetic declination. A positive value indicates a clockwise direction from true north and a negative value indicates a counter-clockwise direction. + \value HorizontalAccuracy The accuracy of the provided latitude-longitude value, in meters. + \value VerticalAccuracy The accuracy of the provided altitude value, in meters. +*/ + +/*! + Creates an invalid QGeoPositionInfo object. + + \sa isValid() +*/ +QGeoPositionInfo::QGeoPositionInfo() + : d(new QGeoPositionInfoPrivate) +{ +} + +/*! + Creates a QGeoPositionInfo for the given \a coordinate and \a timestamp. +*/ +QGeoPositionInfo::QGeoPositionInfo(const QGeoCoordinate &coordinate, const QDateTime ×tamp) + : d(new QGeoPositionInfoPrivate) +{ + d->timestamp = timestamp; + d->coord = coordinate; +} + +/*! + Creates a QGeoPositionInfo with the values of \a other. +*/ +QGeoPositionInfo::QGeoPositionInfo(const QGeoPositionInfo &other) + : d(new QGeoPositionInfoPrivate) +{ + operator=(other); +} + +/*! + Destroys a QGeoPositionInfo object. +*/ +QGeoPositionInfo::~QGeoPositionInfo() +{ + delete d; +} + +/*! + Assigns the values from \a other to this QGeoPositionInfo. +*/ +QGeoPositionInfo &QGeoPositionInfo::operator=(const QGeoPositionInfo & other) +{ + if (this == &other) + return *this; + + d->timestamp = other.d->timestamp; + d->coord = other.d->coord; + d->doubleAttribs = other.d->doubleAttribs; + + return *this; +} + +/*! + Returns true if all of this object's values are the same as those of + \a other. +*/ +bool QGeoPositionInfo::operator==(const QGeoPositionInfo &other) const +{ + return d->timestamp == other.d->timestamp + && d->coord == other.d->coord + && d->doubleAttribs == other.d->doubleAttribs; +} + +/*! + \fn bool QGeoPositionInfo::operator!=(const QGeoPositionInfo &other) const + + Returns true if any of this object's values are not the same as those of + \a other. +*/ + +/*! + Returns true if the timestamp() and coordinate() values are both valid. + + \sa QGeoCoordinate::isValid(), QDateTime::isValid() +*/ +bool QGeoPositionInfo::isValid() const +{ + return d->timestamp.isValid() && d->coord.isValid(); +} + +/*! + Sets the date and time at which this position was reported to \a timestamp. + + The \a timestamp must be in UTC time. + + \sa timestamp() +*/ +void QGeoPositionInfo::setTimestamp(const QDateTime ×tamp) +{ + d->timestamp = timestamp; +} + +/*! + Returns the date and time at which this position was reported, in UTC time. + + Returns an invalid QDateTime if no date/time value has been set. + + \sa setTimestamp() +*/ +QDateTime QGeoPositionInfo::timestamp() const +{ + return d->timestamp; +} + +/*! + Sets the coordinate for this position to \a coordinate. + + \sa coordinate() +*/ +void QGeoPositionInfo::setCoordinate(const QGeoCoordinate &coordinate) +{ + d->coord = coordinate; +} + +/*! + Returns the coordinate for this position. + + Returns an invalid coordinate if no coordinate has been set. + + \sa setCoordinate() +*/ +QGeoCoordinate QGeoPositionInfo::coordinate() const +{ + return d->coord; +} + +/*! + Sets the value for \a attribute to \a value. + + \sa attribute() +*/ +void QGeoPositionInfo::setAttribute(Attribute attribute, qreal value) +{ + d->doubleAttribs[attribute] = value; +} + +/*! + Returns the value of the specified \a attribute as a qreal value. + + Returns NaN if the value has not been set. + + The function hasAttribute() should be used to determine whether or + not a value has been set for an attribute. + + \sa hasAttribute(), setAttribute() +*/ +qreal QGeoPositionInfo::attribute(Attribute attribute) const +{ + if (d->doubleAttribs.contains(attribute)) + return d->doubleAttribs[attribute]; + return qQNaN(); +} + +/*! + Removes the specified \a attribute and its value. +*/ +void QGeoPositionInfo::removeAttribute(Attribute attribute) +{ + d->doubleAttribs.remove(attribute); +} + +/*! + Returns true if the specified \a attribute is present for this + QGeoPositionInfo object. +*/ +bool QGeoPositionInfo::hasAttribute(Attribute attribute) const +{ + return d->doubleAttribs.contains(attribute); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QGeoPositionInfo &info) +{ + QDebugStateSaver saver(dbg); + dbg.nospace() << "QGeoPositionInfo(" << info.d->timestamp; + dbg.nospace() << ", "; // timestamp force dbg.space() -> reverting here + dbg << info.d->coord; + + QList attribs = info.d->doubleAttribs.keys(); + std::stable_sort(attribs.begin(), attribs.end()); // Output a sorted list from an unsorted hash. + for (int i = 0; i < attribs.count(); ++i) { + dbg << ", "; + switch (attribs[i]) { + case QGeoPositionInfo::Direction: + dbg << "Direction="; + break; + case QGeoPositionInfo::GroundSpeed: + dbg << "GroundSpeed="; + break; + case QGeoPositionInfo::VerticalSpeed: + dbg << "VerticalSpeed="; + break; + case QGeoPositionInfo::MagneticVariation: + dbg << "MagneticVariation="; + break; + case QGeoPositionInfo::HorizontalAccuracy: + dbg << "HorizontalAccuracy="; + break; + case QGeoPositionInfo::VerticalAccuracy: + dbg << "VerticalAccuracy="; + break; + } + dbg << info.d->doubleAttribs[attribs[i]]; + } + dbg << ')'; + return dbg; +} +#endif + + +#ifndef QT_NO_DATASTREAM +/*! + \relates QGeoPositionInfo + + Writes the given \a attr enumeration to the specified \a stream. + + \sa {Serializing Qt Data Types} +*/ +QDataStream &operator<<(QDataStream &stream, QGeoPositionInfo::Attribute attr) +{ + return stream << int(attr); +} + +/*! + \relates QGeoPositionInfo + + Reads an attribute enumeration from the specified \a stream info the given \a attr. + + \sa {Serializing Qt Data Types} +*/ +QDataStream &operator>>(QDataStream &stream, QGeoPositionInfo::Attribute &attr) +{ + int a; + stream >> a; + attr = static_cast(a); + return stream; +} + +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QGeoPositionInfo &info) + \relates QGeoPositionInfo + + Writes the given \a info to the specified \a stream. + + \sa {Serializing Qt Data Types} +*/ + +QDataStream &operator<<(QDataStream &stream, const QGeoPositionInfo &info) +{ + stream << info.d->timestamp; + stream << info.d->coord; + stream << info.d->doubleAttribs; + return stream; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QGeoPositionInfo &info) + \relates QGeoPositionInfo + + Reads a coordinate from the specified \a stream into the given + \a info. + + \sa {Serializing Qt Data Types} +*/ + +QDataStream &operator>>(QDataStream &stream, QGeoPositionInfo &info) +{ + stream >> info.d->timestamp; + stream >> info.d->coord; + stream >> info.d->doubleAttribs; + return stream; +} +#endif + +QT_END_NAMESPACE diff --git a/src/positioning/qgeopositioninfo.h b/src/positioning/qgeopositioninfo.h new file mode 100644 index 0000000..9f43fe8 --- /dev/null +++ b/src/positioning/qgeopositioninfo.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOPOSITIONINFO_H +#define QGEOPOSITIONINFO_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QDebug; +class QDataStream; + +class QGeoPositionInfoPrivate; +class Q_POSITIONING_EXPORT QGeoPositionInfo +{ +public: + enum Attribute { + Direction, + GroundSpeed, + VerticalSpeed, + MagneticVariation, + HorizontalAccuracy, + VerticalAccuracy + }; + + QGeoPositionInfo(); + QGeoPositionInfo(const QGeoCoordinate &coordinate, const QDateTime &updateTime); + QGeoPositionInfo(const QGeoPositionInfo &other); + ~QGeoPositionInfo(); + + QGeoPositionInfo &operator=(const QGeoPositionInfo &other); + + bool operator==(const QGeoPositionInfo &other) const; + inline bool operator!=(const QGeoPositionInfo &other) const { + return !operator==(other); + } + + bool isValid() const; + + void setTimestamp(const QDateTime ×tamp); + QDateTime timestamp() const; + + void setCoordinate(const QGeoCoordinate &coordinate); + QGeoCoordinate coordinate() const; + + void setAttribute(Attribute attribute, qreal value); + qreal attribute(Attribute attribute) const; + void removeAttribute(Attribute attribute); + bool hasAttribute(Attribute attribute) const; + +private: +#ifndef QT_NO_DEBUG_STREAM + friend Q_POSITIONING_EXPORT QDebug operator<<(QDebug dbg, const QGeoPositionInfo &info); +#endif +#ifndef QT_NO_DATASTREAM + friend Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &stream, const QGeoPositionInfo &info); + friend Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &stream, QGeoPositionInfo &info); +#endif + QGeoPositionInfoPrivate *d; +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_POSITIONING_EXPORT QDebug operator<<(QDebug dbg, const QGeoPositionInfo &info); +#endif + +#ifndef QT_NO_DATASTREAM +Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &stream, QGeoPositionInfo::Attribute attr); +Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &stream, QGeoPositionInfo::Attribute &attr); +Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &stream, const QGeoPositionInfo &info); +Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &stream, QGeoPositionInfo &info); +#endif + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeopositioninfosource.cpp b/src/positioning/qgeopositioninfosource.cpp new file mode 100644 index 0000000..facace9 --- /dev/null +++ b/src/positioning/qgeopositioninfosource.cpp @@ -0,0 +1,483 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include "qgeopositioninfosource_p.h" +#include "qgeopositioninfosourcefactory.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_LIBRARY +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + ("org.qt-project.qt.position.sourcefactory/5.0", + QLatin1String("/position"))) +#endif + +/*! + \class QGeoPositionInfoSource + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QGeoPositionInfoSource class is an abstract base class for the distribution of positional updates. + + The static function QGeoPositionInfoSource::createDefaultSource() creates a default + position source that is appropriate for the platform, if one is available. + Otherwise, QGeoPositionInfoSource will check for available plugins that + implement the QGeoPositionInfoSourceFactory interface. + + Users of a QGeoPositionInfoSource subclass can request the current position using + requestUpdate(), or start and stop regular position updates using + startUpdates() and stopUpdates(). When an update is available, + positionUpdated() is emitted. The last known position can be accessed with + lastKnownPosition(). + + If regular position updates are required, setUpdateInterval() can be used + to specify how often these updates should be emitted. If no interval is + specified, updates are simply provided whenever they are available. + For example: + + \code + // Emit updates every 10 seconds if available + QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource(0); + if (source) + source->setUpdateInterval(10000); + \endcode + + To remove an update interval that was previously set, call + setUpdateInterval() with a value of 0. + + Note that the position source may have a minimum value requirement for + update intervals, as returned by minimumUpdateInterval(). +*/ + +/*! + \enum QGeoPositionInfoSource::PositioningMethod + Defines the types of positioning methods. + + \value NoPositioningMethods None of the positioning methods. + \value SatellitePositioningMethods Satellite-based positioning methods such as GPS or GLONASS. + \value NonSatellitePositioningMethods Other positioning methods such as 3GPP cell identifier or WiFi based positioning. + \value AllPositioningMethods Satellite-based positioning methods as soon as available. Otherwise non-satellite based methods. +*/ + +void QGeoPositionInfoSourcePrivate::loadMeta() +{ + metaData = plugins().value(providerName); +} + +void QGeoPositionInfoSourcePrivate::loadPlugin() +{ + int idx = int(metaData.value(QStringLiteral("index")).toDouble()); + if (idx < 0) + return; + factory = qobject_cast(loader()->instance(idx)); +} + +QHash QGeoPositionInfoSourcePrivate::plugins(bool reload) +{ + static QHash plugins; + static bool alreadyDiscovered = false; + + if (reload == true) + alreadyDiscovered = false; + + if (!alreadyDiscovered) { + loadPluginMetadata(plugins); + alreadyDiscovered = true; + } + return plugins; +} + +static bool pluginComparator(const QJsonObject &p1, const QJsonObject &p2) +{ + const QString prio = QStringLiteral("Priority"); + if (p1.contains(prio) && !p2.contains(prio)) + return true; + if (!p1.contains(prio) && p2.contains(prio)) + return false; + if (p1.value(prio).isDouble() && !p2.value(prio).isDouble()) + return true; + if (!p1.value(prio).isDouble() && p2.value(prio).isDouble()) + return false; + return (p1.value(prio).toDouble() > p2.value(prio).toDouble()); +} + +QList QGeoPositionInfoSourcePrivate::pluginsSorted() +{ + QList list = plugins().values(); + std::stable_sort(list.begin(), list.end(), pluginComparator); + return list; +} + +void QGeoPositionInfoSourcePrivate::loadPluginMetadata(QHash &plugins) +{ + QFactoryLoader *l = loader(); + QList meta = l->metaData(); + for (int i = 0; i < meta.size(); ++i) { + QJsonObject obj = meta.at(i).value(QStringLiteral("MetaData")).toObject(); + const QString testableKey = QStringLiteral("Testable"); + if (obj.contains(testableKey) && !obj.value(testableKey).toBool()) { + static bool inTest = qEnvironmentVariableIsSet("QT_QTESTLIB_RUNNING"); + if (inTest) + continue; + } + obj.insert(QStringLiteral("index"), i); + plugins.insertMulti(obj.value(QStringLiteral("Provider")).toString(), obj); + } +} + +/*! + Creates a position source with the specified \a parent. +*/ + +QGeoPositionInfoSource::QGeoPositionInfoSource(QObject *parent) + : QObject(parent), + d(new QGeoPositionInfoSourcePrivate) +{ + d->interval = 0; + d->methods = 0; +} + +/*! + Destroys the position source. +*/ +QGeoPositionInfoSource::~QGeoPositionInfoSource() +{ + delete d; +} + +/*! + \property QGeoPositionInfoSource::sourceName + \brief This property holds the unique name of the position source + implementation in use. + + This is the same name that can be passed to createSource() in order to + create a new instance of a particular position source implementation. +*/ +QString QGeoPositionInfoSource::sourceName() const +{ + return d->metaData.value(QStringLiteral("Provider")).toString(); +} + +/*! + \property QGeoPositionInfoSource::updateInterval + \brief This property holds the requested interval in milliseconds between each update. + + If the update interval is not set (or is set to 0) the + source will provide updates as often as necessary. + + If the update interval is set, the source will provide updates at an + interval as close to the requested interval as possible. If the requested + interval is less than the minimumUpdateInterval(), + the minimum interval is used instead. + + Changes to the update interval will happen as soon as is practical, however the + time the change takes may vary between implementations. Whether or not the elapsed + time from the previous interval is counted as part of the new interval is also + implementation dependent. + + The default value for this property is 0. + + Note: Subclass implementations must call the base implementation of + setUpdateInterval() so that updateInterval() returns the correct value. +*/ +void QGeoPositionInfoSource::setUpdateInterval(int msec) +{ + d->interval = msec; +} + +int QGeoPositionInfoSource::updateInterval() const +{ + return d->interval; +} + +/*! + Sets the preferred positioning methods for this source to \a methods. + + If \a methods includes a method that is not supported by the source, the + unsupported method will be ignored. + + If \a methods does not include any methods supported by the source, the + preferred methods will be set to the set of methods which the source supports. + + \b {Note:} When reimplementing this method, subclasses must call the + base method implementation to ensure preferredPositioningMethods() returns the correct value. + + \sa supportedPositioningMethods() +*/ +void QGeoPositionInfoSource::setPreferredPositioningMethods(PositioningMethods methods) +{ + d->methods = methods & supportedPositioningMethods(); + if (d->methods == 0) { + d->methods = supportedPositioningMethods(); + } +} + +/*! + Returns the positioning methods set by setPreferredPositioningMethods(). +*/ +QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSource::preferredPositioningMethods() const +{ + return d->methods; +} + +/*! + Creates and returns a position source with the given \a parent that + reads from the system's default sources of location data, or the plugin + with the highest available priority. + + Returns 0 if the system has no default position source, no valid plugins + could be found or the user does not have the permission to access the current position. +*/ +QGeoPositionInfoSource *QGeoPositionInfoSource::createDefaultSource(QObject *parent) +{ + QList plugins = QGeoPositionInfoSourcePrivate::pluginsSorted(); + foreach (const QJsonObject &obj, plugins) { + if (obj.value(QStringLiteral("Position")).isBool() + && obj.value(QStringLiteral("Position")).toBool()) + { + QGeoPositionInfoSourcePrivate d; + d.metaData = obj; + d.loadPlugin(); + QGeoPositionInfoSource *s = 0; + if (d.factory) + s = d.factory->positionInfoSource(parent); + if (s) { + s->d->metaData = d.metaData; + return s; + } + } + } + return 0; +} + + +/*! + Creates and returns a position source with the given \a parent, + by loading the plugin named \a sourceName. + + Returns 0 if the plugin cannot be found. +*/ +QGeoPositionInfoSource *QGeoPositionInfoSource::createSource(const QString &sourceName, QObject *parent) +{ + QHash plugins = QGeoPositionInfoSourcePrivate::plugins(); + if (plugins.contains(sourceName)) + { + QGeoPositionInfoSourcePrivate d; + d.metaData = plugins.value(sourceName); + d.loadPlugin(); + QGeoPositionInfoSource *src = 0; + if (d.factory) + src = d.factory->positionInfoSource(parent); + if (src) + { + src->d->metaData = d.metaData; + return src; + } + } + return 0; +} + + +/*! + Returns a list of available source plugins. This includes any default backend + plugin for the current platform. +*/ +QStringList QGeoPositionInfoSource::availableSources() +{ + QStringList plugins; + const QHash meta = QGeoPositionInfoSourcePrivate::plugins(); + for (auto it = meta.cbegin(), end = meta.cend(); it != end; ++it) { + if (it.value().value(QStringLiteral("Position")).isBool() + && it.value().value(QStringLiteral("Position")).toBool()) { + plugins << it.key(); + } + } + + return plugins; +} + +/*! + \fn QGeoPositionInfo QGeoPositionInfoSource::lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const = 0; + + Returns an update containing the last known position, or a null update + if none is available. + + If \a fromSatellitePositioningMethodsOnly is true, this returns the last + known position received from a satellite positioning method; if none + is available, a null update is returned. +*/ + +/*! + \fn virtual PositioningMethods QGeoPositionInfoSource::supportedPositioningMethods() const = 0; + + Returns the positioning methods available to this source. + + \sa setPreferredPositioningMethods() +*/ + + +/*! + \property QGeoPositionInfoSource::minimumUpdateInterval + \brief This property holds the minimum time (in milliseconds) required to retrieve a position update. + + This is the minimum value accepted by setUpdateInterval() and + requestUpdate(). +*/ + + +/*! + \fn virtual void QGeoPositionInfoSource::startUpdates() = 0; + + Starts emitting updates at regular intervals as specified by setUpdateInterval(). + + If setUpdateInterval() has not been called, the source will emit updates + as soon as they become available. + + An updateTimeout() signal will be emitted if this QGeoPositionInfoSource subclass determines + that it will not be able to provide regular updates. This could happen if a satellite fix is + lost or if a hardware error is detected. Position updates will recommence if the data becomes + available later on. The updateTimeout() signal will not be emitted again until after the + periodic updates resume. + + On iOS, starting from version 8, Core Location framework requires additional + entries in the application's Info.plist with keys NSLocationAlwaysUsageDescription or + NSLocationWhenInUseUsageDescription and a string to be displayed in the authorization prompt. + The key NSLocationWhenInUseUsageDescription is used when requesting permission + to use location services while the app is in the foreground. + The key NSLocationAlwaysUsageDescription is used when requesting permission + to use location services whenever the app is running (both the foreground and the background). + If both entries are defined, NSLocationWhenInUseUsageDescription has a priority in the + foreground mode. +*/ + +/*! + \fn virtual void QGeoPositionInfoSource::stopUpdates() = 0; + + Stops emitting updates at regular intervals. +*/ + +/*! + \fn virtual void QGeoPositionInfoSource::requestUpdate(int timeout = 0); + + Attempts to get the current position and emit positionUpdated() with + this information. If the current position cannot be found within the given \a timeout + (in milliseconds) or if \a timeout is less than the value returned by + minimumUpdateInterval(), updateTimeout() is emitted. + + If the timeout is zero, the timeout defaults to a reasonable timeout + period as appropriate for the source. + + This does nothing if another update request is in progress. However + it can be called even if startUpdates() has already been called and + regular updates are in progress. + + If the source uses multiple positioning methods, it tries to get the + current position from the most accurate positioning method within the + given timeout. +*/ + +/*! + \fn virtual QGeoPositionInfoSource::Error QGeoPositionInfoSource::error() const; + + Returns the type of error that last occurred. + +*/ + +/*! + \fn void QGeoPositionInfoSource::positionUpdated(const QGeoPositionInfo &update); + + If startUpdates() or requestUpdate() is called, this signal is emitted + when an update becomes available. + + The \a update value holds the value of the new update. +*/ + +/*! + \fn void QGeoPositionInfoSource::updateTimeout(); + + If requestUpdate() was called, this signal will be emitted if the current position could not + be retrieved within the specified timeout. + + If startUpdates() has been called, this signal will be emitted if this QGeoPositionInfoSource + subclass determines that it will not be able to provide further regular updates. This signal + will not be emitted again until after the regular updates resume. + + While the triggering of this signal may be considered an error condition, it does not + imply the emission of the \c error() signal. Only the emission of \c updateTimeout() is required + to indicate a timeout. +*/ + +/*! + \fn void QGeoPositionInfoSource::error(QGeoPositionInfoSource::Error positioningError) + + This signal is emitted after an error occurred. The \a positioningError + parameter describes the type of error that occurred. + + This signal is not emitted when an updateTimeout() has occurred. + +*/ + +/*! + \enum QGeoPositionInfoSource::Error + + The Error enumeration represents the errors which can occur. + + \value AccessError The connection setup to the remote positioning backend failed because the + application lacked the required privileges. + \value ClosedError The remote positioning backend closed the connection, which happens for example in case + the user is switching location services to off. As soon as the location service is re-enabled + regular updates will resume. + \value NoError No error has occurred. + \value UnknownSourceError An unidentified error occurred. + */ + +#include "moc_qgeopositioninfosource.cpp" + +QT_END_NAMESPACE diff --git a/src/positioning/qgeopositioninfosource.h b/src/positioning/qgeopositioninfosource.h new file mode 100644 index 0000000..2478446 --- /dev/null +++ b/src/positioning/qgeopositioninfosource.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOPOSITIONINFOSOURCE_H +#define QGEOPOSITIONINFOSOURCE_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGeoPositionInfoSourcePrivate; +class Q_POSITIONING_EXPORT QGeoPositionInfoSource : public QObject +{ + Q_OBJECT + Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval) + Q_PROPERTY(int minimumUpdateInterval READ minimumUpdateInterval) + Q_PROPERTY(QString sourceName READ sourceName) + +public: + enum Error { + AccessError = 0, + ClosedError = 1, + UnknownSourceError = 2, + NoError = 3 + }; + Q_ENUMS(Error) + + enum PositioningMethod { + NoPositioningMethods = 0x00000000, + SatellitePositioningMethods = 0x000000ff, + NonSatellitePositioningMethods = 0xffffff00, + AllPositioningMethods = 0xffffffff + }; + Q_DECLARE_FLAGS(PositioningMethods, PositioningMethod) + + explicit QGeoPositionInfoSource(QObject *parent); + virtual ~QGeoPositionInfoSource(); + + virtual void setUpdateInterval(int msec); + int updateInterval() const; + + virtual void setPreferredPositioningMethods(PositioningMethods methods); + PositioningMethods preferredPositioningMethods() const; + + virtual QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const = 0; + + virtual PositioningMethods supportedPositioningMethods() const = 0; + virtual int minimumUpdateInterval() const = 0; + + QString sourceName() const; + + static QGeoPositionInfoSource *createDefaultSource(QObject *parent); + static QGeoPositionInfoSource *createSource(const QString &sourceName, QObject *parent); + static QStringList availableSources(); + virtual Error error() const = 0; + +public Q_SLOTS: + virtual void startUpdates() = 0; + virtual void stopUpdates() = 0; + + virtual void requestUpdate(int timeout = 0) = 0; + +Q_SIGNALS: + void positionUpdated(const QGeoPositionInfo &update); + void updateTimeout(); + void error(QGeoPositionInfoSource::Error); + +private: + Q_DISABLE_COPY(QGeoPositionInfoSource) + QGeoPositionInfoSourcePrivate *d; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoPositionInfoSource::PositioningMethods) + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeopositioninfosource_p.h b/src/positioning/qgeopositioninfosource_p.h new file mode 100644 index 0000000..32fd23e --- /dev/null +++ b/src/positioning/qgeopositioninfosource_p.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCE_P_H +#define QGEOPOSITIONINFOSOURCE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeopositioninfosource.h" +#include "qgeopositioninfosourcefactory.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoPositionInfoSourcePrivate +{ +public: + int interval; + QGeoPositionInfoSource::PositioningMethods methods; + QJsonObject metaData; + QGeoPositionInfoSourceFactory *factory; + QString providerName; + + void loadMeta(); + void loadPlugin(); + + static QHash plugins(bool reload = false); + static void loadPluginMetadata(QHash &list); + static QList pluginsSorted(); +}; + +QT_END_NAMESPACE + +#endif // QGEOPOSITIONINFOSOURCE_P_H diff --git a/src/positioning/qgeopositioninfosourcefactory.cpp b/src/positioning/qgeopositioninfosourcefactory.cpp new file mode 100644 index 0000000..6c6e9c7 --- /dev/null +++ b/src/positioning/qgeopositioninfosourcefactory.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosourcefactory.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoPositionInfoSourceFactory + \inmodule QtPositioning + \since 5.2 + + \brief The QGeoPositionInfoSourceFactory class is a factory class used + as the plugin interface for external providers of positioning data. + + The other functions must be overridden by all plugins, other than + sourcePriority() which defaults to returning 0. Higher values of + priority will be preferred to lower ones. +*/ + +/*! + \fn QGeoPositionInfoSource *QGeoPositionInfoSourceFactory::positionInfoSource(QObject *parent) + + Returns a new QGeoPositionInfoSource associated with this plugin + with parent \a parent. Can also return 0, in which case the plugin + loader will use the factory with the next highest priority. + */ + +/*! + \fn QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactory::satelliteInfoSource(QObject *parent) + + Returns a new QGeoSatelliteInfoSource associated with this plugin + with parent \a parent. Can also return 0, in which case the plugin + loader will use the factory with the next highest priority. + */ + +/*! + \fn QGeoAreaMonitorSource *QGeoPositionInfoSourceFactory::areaMonitor(QObject *parent); + + Returns a new QGeoAreaMonitorSource associated with this plugin with parent \a parent. + Can also return 0, in which case the plugin loader will use the factory with the + next highest priority. + */ + +/*! + Destroys the position info source factory. +*/ +QGeoPositionInfoSourceFactory::~QGeoPositionInfoSourceFactory() +{} + +QT_END_NAMESPACE diff --git a/src/positioning/qgeopositioninfosourcefactory.h b/src/positioning/qgeopositioninfosourcefactory.h new file mode 100644 index 0000000..b30aaf7 --- /dev/null +++ b/src/positioning/qgeopositioninfosourcefactory.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCEFACTORY_H +#define QGEOPOSITIONINFOSOURCEFACTORY_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_POSITIONING_EXPORT QGeoPositionInfoSourceFactory +{ +public: + virtual ~QGeoPositionInfoSourceFactory(); + + virtual QGeoPositionInfoSource *positionInfoSource(QObject *parent) = 0; + virtual QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent) = 0; + virtual QGeoAreaMonitorSource *areaMonitor(QObject *parent) = 0; +}; + +#define QT_POSITION_SOURCE_INTERFACE +Q_DECLARE_INTERFACE(QGeoPositionInfoSourceFactory, + "org.qt-project.qt.position.sourcefactory/5.0") + +QT_END_NAMESPACE + +#endif // QGEOPOSITIONINFOSOURCEFACTORY_H diff --git a/src/positioning/qgeoprojection.cpp b/src/positioning/qgeoprojection.cpp new file mode 100644 index 0000000..507f080 --- /dev/null +++ b/src/positioning/qgeoprojection.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeoprojection_p.h" + +#include "qgeocoordinate.h" + +#include + +#include + +#include "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" + +QT_BEGIN_NAMESPACE + +QDoubleVector2D QGeoProjection::coordToMercator(const QGeoCoordinate &coord) +{ + const double pi = M_PI; + + double lon = coord.longitude() / 360.0 + 0.5; + + double lat = coord.latitude(); + lat = 0.5 - (std::log(std::tan((pi / 4.0) + (pi / 2.0) * lat / 180.0)) / pi) / 2.0; + lat = qBound(0.0, lat, 1.0); + + return QDoubleVector2D(lon, lat); +} + +double QGeoProjection::realmod(const double a, const double b) +{ + quint64 div = static_cast(a / b); + return a - static_cast(div) * b; +} + +QGeoCoordinate QGeoProjection::mercatorToCoord(const QDoubleVector2D &mercator) +{ + const double pi = M_PI; + + double fx = mercator.x(); + double fy = mercator.y(); + + if (fy < 0.0) + fy = 0.0; + else if (fy > 1.0) + fy = 1.0; + + double lat; + + if (fy == 0.0) + lat = 90.0; + else if (fy == 1.0) + lat = -90.0; + else + lat = (180.0 / pi) * (2.0 * std::atan(std::exp(pi * (1.0 - 2.0 * fy))) - (pi / 2.0)); + + double lng; + if (fx >= 0) { + lng = realmod(fx, 1.0); + } else { + lng = realmod(1.0 - realmod(-1.0 * fx, 1.0), 1.0); + } + + lng = lng * 360.0 - 180.0; + + return QGeoCoordinate(lat, lng, 0.0); +} + +QGeoCoordinate QGeoProjection::coordinateInterpolation(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) +{ + QDoubleVector2D s = QGeoProjection::coordToMercator(from); + QDoubleVector2D e = QGeoProjection::coordToMercator(to); + + double x = s.x(); + + if (0.5 < qAbs(e.x() - s.x())) { + // handle dateline crossing + double ex = e.x(); + double sx = s.x(); + if (ex < sx) + sx -= 1.0; + else if (sx < ex) + ex -= 1.0; + + x = (1.0 - progress) * sx + progress * ex; + + if (!qFuzzyIsNull(x) && (x < 0.0)) + x += 1.0; + + } else { + x = (1.0 - progress) * s.x() + progress * e.x(); + } + + double y = (1.0 - progress) * s.y() + progress * e.y(); + + QGeoCoordinate result = QGeoProjection::mercatorToCoord(QDoubleVector2D(x, y)); + result.setAltitude((1.0 - progress) * from.altitude() + progress * to.altitude()); + + return result; +} + +QT_END_NAMESPACE diff --git a/src/positioning/qgeoprojection_p.h b/src/positioning/qgeoprojection_p.h new file mode 100644 index 0000000..b80678b --- /dev/null +++ b/src/positioning/qgeoprojection_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOPROJECTION_P_H +#define QGEOPROJECTION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif + +#include +#include +#include "qpositioningglobal.h" + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; +class QDoubleVector2D; + +class Q_POSITIONING_EXPORT QGeoProjection +{ +public: + static QDoubleVector2D coordToMercator(const QGeoCoordinate &coord); + static QGeoCoordinate mercatorToCoord(const QDoubleVector2D &mercator); + static QGeoCoordinate coordinateInterpolation(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress); + +private: + static double realmod(const double a, const double b); +}; + +QT_END_NAMESPACE + +#endif // QGEOPROJECTION_P_H diff --git a/src/positioning/qgeorectangle.cpp b/src/positioning/qgeorectangle.cpp new file mode 100644 index 0000000..bbcafd6 --- /dev/null +++ b/src/positioning/qgeorectangle.cpp @@ -0,0 +1,1063 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeorectangle.h" +#include "qgeorectangle_p.h" + +#include "qgeocoordinate.h" +#include "qnumeric.h" +#include +QT_BEGIN_NAMESPACE + +/*! + \class QGeoRectangle + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QGeoRectangle class defines a rectangular geographic area. + + The rectangle is defined in terms of a QGeoCoordinate which specifies the + top left coordinate of the rectangle and a QGeoCoordinate which specifies + the bottom right coordinate of the rectangle. + + A geo rectangle is considered invalid if the top left or bottom right + coordinates are invalid or if the top left coordinate is south of the + bottom right coordinate. + + Geo rectangles can never cross the poles. + + Several methods behave as though the geo rectangle is defined in terms of a + center coordinate, the width of the geo rectangle in degrees and the height + of the geo rectangle in degrees. + + If the height or center of a geo rectangle is adjusted such that it would + cross one of the poles the height is modified such that the geo rectangle + touches but does not cross the pole and that the center coordinate is still + in the center of the geo rectangle. + + This class is a \l Q_GADGET since Qt 5.5. It can be + \l{Cpp_value_integration_positioning}{directly used from C++ and QML}. +*/ + +/*! + \property QGeoRectangle::bottomLeft + \brief This property holds the bottom left coorindate of this geo rectangle. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoRectangle::bottomRight + \brief This property holds the bottom right coordinate of this geo rectangle. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoRectangle::topLeft + \brief This property holds the top left coordinate of this geo rectangle. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoRectangle::topRight + \brief This property holds the top right coordinate of this geo rectangle. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoRectangle::center + \brief This property holds the center of this geo rectangle. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \sa QGeoShape::center + + \since 5.5 +*/ + +/*! + \property QGeoRectangle::width + \brief This property holds the width of this geo rectangle in degrees. + + The property value is undefined if this geo rectangle is invalid. + + If the new width is less than 0.0 or if this geo rectangle is invalid, this + function does nothing. To set up the values of an invalid + geo rectangle based on the center, width, and height, you should use + \l setCenter() first to make the geo rectangle valid. + + 360.0 is the width used only if the new width is equal or greater than 360. + In such cases the leftmost longitude of the geo rectangle is set to -180.0 + degrees and the rightmost longitude of the geo rectangle is set to 180.0 + degrees. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoRectangle::height + \brief This property holds the height of this geo rectangle in degrees. + + The property value is undefined if this geo rectangle is invalid. + + If the new height is less than 0.0 or if this geo rectangle is invalid, + the property is not changed. To set up the values of an invalid + geo rectangle based on the center, width, and height, you should use + \l setCenter() first to make the geo rectangle valid. + + If the change in height would cause the geo rectangle to cross a pole, + the height is adjusted such that the geo rectangle only touches the pole. + + This change is done such that the center coordinate is still at the + center of the geo rectangle, which may result in a geo rectangle with + a smaller height than expected. + + 180.0 is the height used only if the new height is greater or equal than 180. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +inline QGeoRectanglePrivate *QGeoRectangle::d_func() +{ + return static_cast(d_ptr.data()); +} + +inline const QGeoRectanglePrivate *QGeoRectangle::d_func() const +{ + return static_cast(d_ptr.constData()); +} + +struct RectangleVariantConversions +{ + RectangleVariantConversions() + { + QMetaType::registerConverter(); + QMetaType::registerConverter(); + } +}; + + +Q_GLOBAL_STATIC(RectangleVariantConversions, initRectangleConversions) + +/*! + Constructs a new, invalid geo rectangle. +*/ +QGeoRectangle::QGeoRectangle() +: QGeoShape(new QGeoRectanglePrivate) +{ + initRectangleConversions(); +} + +/*! + Constructs a new geo rectangle centered at \a center with a + width in degrees of \a degreesWidth and a height in degrees of \a degreesHeight. + + If \a degreesHeight would take the geo rectangle beyond one of the poles, + the height of the geo rectangle will be truncated such that the geo rectangle + only extends up to the pole. The center of the geo rectangle will be + unchanged, and the height will be adjusted such that the center point is at + the center of the truncated geo rectangle. +*/ +QGeoRectangle::QGeoRectangle(const QGeoCoordinate ¢er, double degreesWidth, double degreesHeight) +{ + initRectangleConversions(); + d_ptr = new QGeoRectanglePrivate(center, center); + setWidth(degreesWidth); + setHeight(degreesHeight); +} + +/*! + Constructs a new geo rectangle with a top left coordinate \a topLeft and a bottom right + coordinate \a bottomRight. +*/ +QGeoRectangle::QGeoRectangle(const QGeoCoordinate &topLeft, const QGeoCoordinate &bottomRight) +{ + initRectangleConversions(); + d_ptr = new QGeoRectanglePrivate(topLeft, bottomRight); +} + +/*! + Constructs a new geo rectangle, of minimum size, containing all of the \a coordinates. +*/ +QGeoRectangle::QGeoRectangle(const QList &coordinates) +{ + initRectangleConversions(); + if (coordinates.isEmpty()) { + d_ptr = new QGeoRectanglePrivate; + } else { + const QGeoCoordinate &startCoordinate = coordinates.first(); + d_ptr = new QGeoRectanglePrivate(startCoordinate, startCoordinate); + + foreach (const QGeoCoordinate &coordinate, coordinates) { + d_ptr->extendShape(coordinate); + } + } +} + +/*! + Constructs a geo rectangle from the contents of \a other. +*/ +QGeoRectangle::QGeoRectangle(const QGeoRectangle &other) +: QGeoShape(other) +{ + initRectangleConversions(); +} + +/*! + Constructs a geo rectangle from the contents of \a other. +*/ +QGeoRectangle::QGeoRectangle(const QGeoShape &other) +: QGeoShape(other) +{ + initRectangleConversions(); + if (type() != QGeoShape::RectangleType) + d_ptr = new QGeoRectanglePrivate; +} + +/*! + Destroys this geo rectangle. +*/ +QGeoRectangle::~QGeoRectangle() +{ +} + +/*! + Assigns \a other to this geo rectangle and returns a reference to this geo rectangle. +*/ +QGeoRectangle &QGeoRectangle::operator=(const QGeoRectangle &other) +{ + QGeoShape::operator=(other); + return *this; +} + +/*! + Returns whether this geo rectangle is equal to \a other. +*/ +bool QGeoRectangle::operator==(const QGeoRectangle &other) const +{ + Q_D(const QGeoRectangle); + + return *d == *other.d_func(); +} + +/*! + Returns whether this geo rectangle is not equal to \a other. +*/ +bool QGeoRectangle::operator!=(const QGeoRectangle &other) const +{ + Q_D(const QGeoRectangle); + + return !(*d == *other.d_func()); +} + +bool QGeoRectanglePrivate::isValid() const +{ + return topLeft.isValid() && bottomRight.isValid() && + topLeft.latitude() >= bottomRight.latitude(); +} + +bool QGeoRectanglePrivate::isEmpty() const +{ + if (!isValid()) + return true; + + return topLeft.latitude() == bottomRight.latitude() || + topLeft.longitude() == bottomRight.longitude(); +} + +/*! + Sets the top left coordinate of this geo rectangle to \a topLeft. +*/ +void QGeoRectangle::setTopLeft(const QGeoCoordinate &topLeft) +{ + Q_D(QGeoRectangle); + + d->topLeft = topLeft; +} + +/*! + Returns the top left coordinate of this geo rectangle. +*/ +QGeoCoordinate QGeoRectangle::topLeft() const +{ + Q_D(const QGeoRectangle); + + return d->topLeft; +} + +/*! + Sets the top right coordinate of this geo rectangle to \a topRight. +*/ +void QGeoRectangle::setTopRight(const QGeoCoordinate &topRight) +{ + Q_D(QGeoRectangle); + + d->topLeft.setLatitude(topRight.latitude()); + d->bottomRight.setLongitude(topRight.longitude()); +} + +/*! + Returns the top right coordinate of this geo rectangle. +*/ +QGeoCoordinate QGeoRectangle::topRight() const +{ + // TODO remove? + if (!isValid()) + return QGeoCoordinate(); + + Q_D(const QGeoRectangle); + + return QGeoCoordinate(d->topLeft.latitude(), d->bottomRight.longitude()); +} + +/*! + Sets the bottom left coordinate of this geo rectangle to \a bottomLeft. +*/ +void QGeoRectangle::setBottomLeft(const QGeoCoordinate &bottomLeft) +{ + Q_D(QGeoRectangle); + + d->bottomRight.setLatitude(bottomLeft.latitude()); + d->topLeft.setLongitude(bottomLeft.longitude()); +} + +/*! + Returns the bottom left coordinate of this geo rectangle. +*/ +QGeoCoordinate QGeoRectangle::bottomLeft() const +{ + // TODO remove? + if (!isValid()) + return QGeoCoordinate(); + + Q_D(const QGeoRectangle); + + return QGeoCoordinate(d->bottomRight.latitude(), d->topLeft.longitude()); +} + +/*! + Sets the bottom right coordinate of this geo rectangle to \a bottomRight. +*/ +void QGeoRectangle::setBottomRight(const QGeoCoordinate &bottomRight) +{ + Q_D(QGeoRectangle); + + d->bottomRight = bottomRight; +} + +/*! + Returns the bottom right coordinate of this geo rectangle. +*/ +QGeoCoordinate QGeoRectangle::bottomRight() const +{ + Q_D(const QGeoRectangle); + + return d->bottomRight; +} + +/*! + Sets the center of this geo rectangle to \a center. + + If this causes the geo rectangle to cross on of the poles the height of the + geo rectangle will be truncated such that the geo rectangle only extends up + to the pole. The center of the geo rectangle will be unchanged, and the + height will be adjusted such that the center point is at the center of the + truncated geo rectangle. + +*/ +void QGeoRectangle::setCenter(const QGeoCoordinate ¢er) +{ + Q_D(QGeoRectangle); + + if (!isValid()) { + d->topLeft = center; + d->bottomRight = center; + return; + } + double width = this->width(); + double height = this->height(); + + double tlLat = center.latitude() + height / 2.0; + double tlLon = center.longitude() - width / 2.0; + double brLat = center.latitude() - height / 2.0; + double brLon = center.longitude() + width / 2.0; + + if (tlLon < -180.0) + tlLon += 360.0; + if (tlLon > 180.0) + tlLon -= 360.0; + + if (brLon < -180.0) + brLon += 360.0; + if (brLon > 180.0) + brLon -= 360.0; + + if (tlLat > 90.0) { + brLat = 2 * center.latitude() - 90.0; + tlLat = 90.0; + } + + if (tlLat < -90.0) { + brLat = -90.0; + tlLat = -90.0; + } + + if (brLat > 90.0) { + tlLat = 90.0; + brLat = 90.0; + } + + if (brLat < -90.0) { + tlLat = 2 * center.latitude() + 90.0; + brLat = -90.0; + } + + if (width == 360.0) { + tlLon = -180.0; + brLon = 180.0; + } + + d->topLeft = QGeoCoordinate(tlLat, tlLon); + d->bottomRight = QGeoCoordinate(brLat, brLon); +} + +/*! + Returns the center of this geo rectangle. Equivalent to QGeoShape::center(). +*/ +QGeoCoordinate QGeoRectangle::center() const +{ + Q_D(const QGeoRectangle); + + return d->center(); +} + +/*! + Sets the width of this geo rectangle in degrees to \a degreesWidth. +*/ +void QGeoRectangle::setWidth(double degreesWidth) +{ + if (!isValid()) + return; + + if (degreesWidth < 0.0) + return; + + Q_D(QGeoRectangle); + + if (degreesWidth >= 360.0) { + d->topLeft.setLongitude(-180.0); + d->bottomRight.setLongitude(180.0); + return; + } + + double tlLat = d->topLeft.latitude(); + double brLat = d->bottomRight.latitude(); + + QGeoCoordinate c = center(); + + double tlLon = c.longitude() - degreesWidth / 2.0; + + if (tlLon < -180.0) + tlLon += 360.0; + if (tlLon > 180.0) + tlLon -= 360.0; + + double brLon = c.longitude() + degreesWidth / 2.0; + + if (brLon < -180.0) + brLon += 360.0; + if (brLon > 180.0) + brLon -= 360.0; + + d->topLeft = QGeoCoordinate(tlLat, tlLon); + d->bottomRight = QGeoCoordinate(brLat, brLon); +} + +/*! + Returns the width of this geo rectangle in degrees. + + The return value is undefined if this geo rectangle is invalid. +*/ +double QGeoRectangle::width() const +{ + if (!isValid()) + return qQNaN(); + + Q_D(const QGeoRectangle); + + double result = d->bottomRight.longitude() - d->topLeft.longitude(); + if (result < 0.0) + result += 360.0; + if (result > 360.0) + result -= 360.0; + + return result; +} + +/*! + Sets the height of this geo rectangle in degrees to \a degreesHeight. +*/ +void QGeoRectangle::setHeight(double degreesHeight) +{ + if (!isValid()) + return; + + if (degreesHeight < 0.0) + return; + + if (degreesHeight >= 180.0) { + degreesHeight = 180.0; + } + + Q_D(QGeoRectangle); + + double tlLon = d->topLeft.longitude(); + double brLon = d->bottomRight.longitude(); + + QGeoCoordinate c = center(); + + double tlLat = c.latitude() + degreesHeight / 2.0; + double brLat = c.latitude() - degreesHeight / 2.0; + + if (tlLat > 90.0) { + brLat = 2* c.latitude() - 90.0; + tlLat = 90.0; + } + + if (tlLat < -90.0) { + brLat = -90.0; + tlLat = -90.0; + } + + if (brLat > 90.0) { + tlLat = 90.0; + brLat = 90.0; + } + + if (brLat < -90.0) { + tlLat = 2 * c.latitude() + 90.0; + brLat = -90.0; + } + + d->topLeft = QGeoCoordinate(tlLat, tlLon); + d->bottomRight = QGeoCoordinate(brLat, brLon); +} + +/*! + Returns the height of this geo rectangle in degrees. + + The return value is undefined if this geo rectangle is invalid. +*/ +double QGeoRectangle::height() const +{ + if (!isValid()) + return qQNaN(); + + Q_D(const QGeoRectangle); + + double result = d->topLeft.latitude() - d->bottomRight.latitude(); + if (result < 0.0) + result = qQNaN(); + return result; +} + +bool QGeoRectanglePrivate::contains(const QGeoCoordinate &coordinate) const +{ + if (!isValid() || !coordinate.isValid()) + return false; + + double left = topLeft.longitude(); + double right = bottomRight.longitude(); + double top = topLeft.latitude(); + double bottom = bottomRight.latitude(); + + double lon = coordinate.longitude(); + double lat = coordinate.latitude(); + + if (lat > top) + return false; + if (lat < bottom) + return false; + + if ((lat == 90.0) && (top == 90.0)) + return true; + + if ((lat == -90.0) && (bottom == -90.0)) + return true; + + if (left <= right) { + if ((lon < left) || (lon > right)) + return false; + } else { + if ((lon < left) && (lon > right)) + return false; + } + + return true; +} + +QGeoCoordinate QGeoRectanglePrivate::center() const +{ + if (!isValid()) + return QGeoCoordinate(); + + double cLat = (topLeft.latitude() + bottomRight.latitude()) / 2.0; + double cLon = (bottomRight.longitude() + topLeft.longitude()) / 2.0; + + if (topLeft.longitude() > bottomRight.longitude()) + cLon = cLon - 180.0; + + if (cLon < -180.0) + cLon += 360.0; + if (cLon > 180.0) + cLon -= 360.0; + + return QGeoCoordinate(cLat, cLon); +} + +/*! + Returns whether the geo rectangle \a rectangle is contained within this + geo rectangle. +*/ +bool QGeoRectangle::contains(const QGeoRectangle &rectangle) const +{ + Q_D(const QGeoRectangle); + + return (d->contains(rectangle.topLeft()) + && d->contains(rectangle.topRight()) + && d->contains(rectangle.bottomLeft()) + && d->contains(rectangle.bottomRight())); +} + +/*! + Returns whether the geo rectangle \a rectangle intersects this geo rectangle. + + If the top or bottom edges of both geo rectangles are at one of the poles + the geo rectangles are considered to be intersecting, since the longitude + is irrelevant when the edges are at the pole. +*/ +bool QGeoRectangle::intersects(const QGeoRectangle &rectangle) const +{ + Q_D(const QGeoRectangle); + + double left1 = d->topLeft.longitude(); + double right1 = d->bottomRight.longitude(); + double top1 = d->topLeft.latitude(); + double bottom1 = d->bottomRight.latitude(); + + double left2 = rectangle.d_func()->topLeft.longitude(); + double right2 = rectangle.d_func()->bottomRight.longitude(); + double top2 = rectangle.d_func()->topLeft.latitude(); + double bottom2 = rectangle.d_func()->bottomRight.latitude(); + + if (top1 < bottom2) + return false; + + if (bottom1 > top2) + return false; + + if ((top1 == 90.0) && (top1 == top2)) + return true; + + if ((bottom1 == -90.0) && (bottom1 == bottom2)) + return true; + + if (left1 < right1) { + if (left2 < right2) { + if ((left1 > right2) || (right1 < left2)) + return false; + } else { + if ((left1 > right2) && (right1 < left2)) + return false; + } + } else { + if (left2 < right2) { + if ((left2 > right1) && (right2 < left1)) + return false; + } else { + // if both wrap then they have to intersect + } + } + + return true; +} + +/*! + Translates this geo rectangle by \a degreesLatitude northwards and \a + degreesLongitude eastwards. + + Negative values of \a degreesLatitude and \a degreesLongitude correspond to + southward and westward translation respectively. + + If the translation would have caused the geo rectangle to cross a pole the + geo rectangle will be translated until the top or bottom edge of the geo rectangle + touches the pole but not further. +*/ +void QGeoRectangle::translate(double degreesLatitude, double degreesLongitude) +{ + // TODO handle dlat, dlon larger than 360 degrees + + Q_D(QGeoRectangle); + + double tlLat = d->topLeft.latitude(); + double tlLon = d->topLeft.longitude(); + double brLat = d->bottomRight.latitude(); + double brLon = d->bottomRight.longitude(); + + if ((tlLat != 90.0) || (brLat != -90.0)) { + tlLat += degreesLatitude; + brLat += degreesLatitude; + } + + if ( (tlLon != -180.0) || (brLon != 180.0) ) { + tlLon += degreesLongitude; + brLon += degreesLongitude; + } + + if (tlLon < -180.0) + tlLon += 360.0; + if (tlLon > 180.0) + tlLon -= 360.0; + + if (brLon < -180.0) + brLon += 360.0; + if (brLon > 180.0) + brLon -= 360.0; + + if (tlLat > 90.0) + tlLat = 90.0; + + if (tlLat < -90.0) + tlLat = -90.0; + + if (brLat > 90.0) + brLat = 90.0; + + if (brLat < -90.0) + brLat = -90.0; + + d->topLeft = QGeoCoordinate(tlLat, tlLon); + d->bottomRight = QGeoCoordinate(brLat, brLon); +} + +/*! + Returns a copy of this geo rectangle translated by \a degreesLatitude northwards and \a + degreesLongitude eastwards. + + Negative values of \a degreesLatitude and \a degreesLongitude correspond to + southward and westward translation respectively. + + \sa translate() +*/ +QGeoRectangle QGeoRectangle::translated(double degreesLatitude, double degreesLongitude) const +{ + QGeoRectangle result(*this); + result.translate(degreesLatitude, degreesLongitude); + return result; +} + +/*! + Returns the smallest geo rectangle which contains both this geo rectangle and \a rectangle. + + If the centers of the two geo rectangles are separated by exactly 180.0 degrees then the + width is set to 360.0 degrees with the leftmost longitude set to -180.0 degrees and the + rightmost longitude set to 180.0 degrees. This is done to ensure that the result is + independent of the order of the operands. + +*/ +QGeoRectangle QGeoRectangle::united(const QGeoRectangle &rectangle) const +{ + QGeoRectangle result(*this); + result |= rectangle; + return result; +} + +/*! + Extends the rectangle in the smallest possible way to include \a coordinate in + the shape. + + Both the rectangle and coordinate needs to be valid. If the rectangle already covers + the coordinate noting happens. + +*/ +void QGeoRectanglePrivate::extendShape(const QGeoCoordinate &coordinate) +{ + if (!isValid() || !coordinate.isValid() || contains(coordinate)) + return; + + double left = topLeft.longitude(); + double right = bottomRight.longitude(); + double top = topLeft.latitude(); + double bottom = bottomRight.latitude(); + + double inputLat = coordinate.latitude(); + double inputLon = coordinate.longitude(); + + top = qMax(top, inputLat); + bottom = qMin(bottom, inputLat); + + bool wrap = left > right; + + if (wrap && inputLon > right && inputLon < left) { + if (qAbs(left - inputLon) < qAbs(right - inputLon)) + left = inputLon; + else + right = inputLon; + } else if (!wrap) { + if (inputLon < left) { + if (360 - (right - inputLon) < left - inputLon) + right = inputLon; + else + left = inputLon; + } else if (inputLon > right) { + if (360 - (inputLon - left) < inputLon - right) + left = inputLon; + else + right = inputLon; + } + } + topLeft = QGeoCoordinate(top, left); + bottomRight = QGeoCoordinate(bottom, right); +} + +/*! + \fn QGeoRectangle QGeoRectangle::operator|(const QGeoRectangle &rectangle) const + + Returns the smallest geo rectangle which contains both this geo rectangle and \a rectangle. + + If the centers of the two geo rectangles are separated by exactly 180.0 degrees then the + width is set to 360.0 degrees with the leftmost longitude set to -180.0 degrees and the + rightmost longitude set to 180.0 degrees. This is done to ensure that the result is + independent of the order of the operands. + +*/ + +/*! + Returns the smallest geo rectangle which contains both this geo rectangle and \a rectangle. + + If the centers of the two geo rectangles are separated by exactly 180.0 degrees then the + width is set to 360.0 degrees with the leftmost longitude set to -180.0 degrees and the + rightmost longitude set to 180.0 degrees. This is done to ensure that the result is + independent of the order of the operands. + +*/ +QGeoRectangle &QGeoRectangle::operator|=(const QGeoRectangle &rectangle) +{ + // If non-intersecting goes for most narrow box + + Q_D(QGeoRectangle); + + double left1 = d->topLeft.longitude(); + double right1 = d->bottomRight.longitude(); + double top1 = d->topLeft.latitude(); + double bottom1 = d->bottomRight.latitude(); + + double left2 = rectangle.d_func()->topLeft.longitude(); + double right2 = rectangle.d_func()->bottomRight.longitude(); + double top2 = rectangle.d_func()->topLeft.latitude(); + double bottom2 = rectangle.d_func()->bottomRight.latitude(); + + double top = qMax(top1, top2); + double bottom = qMin(bottom1, bottom2); + + double left = 0.0; + double right = 0.0; + + bool wrap1 = (left1 > right1); + bool wrap2 = (left2 > right2); + + if ((wrap1 && wrap2) || (!wrap1 && !wrap2)) { + + double w = qAbs((left1 + right1 - left2 - right2) / 2.0); + + if (w < 180.0) { + left = qMin(left1, left2); + right = qMax(right1, right2); + } else if (w > 180.0) { + left = qMax(left1, left2); + right = qMin(right1, right2); + } else { + left = -180.0; + right = 180.0; + } + + } else { + double wrapLeft = 0.0; + double wrapRight = 0.0; + double nonWrapLeft = 0.0; + double nonWrapRight = 0.0; + + if (wrap1) { + wrapLeft = left1; + wrapRight = right1; + nonWrapLeft = left2; + nonWrapRight = right2; + } else { + wrapLeft = left2; + wrapRight = right2; + nonWrapLeft = left1; + nonWrapRight = right1; + } + + bool joinWrapLeft = (nonWrapRight >= wrapLeft); + bool joinWrapRight = (nonWrapLeft <= wrapRight); + + if (joinWrapLeft) { + if (joinWrapRight) { + left = -180.0; + right = 180.0; + } else { + left = nonWrapLeft; + right = wrapRight; + } + } else { + if (joinWrapRight) { + left = wrapLeft; + right = nonWrapRight; + } else { + double wrapRightDistance = nonWrapLeft - wrapRight; + double wrapLeftDistance = wrapLeft - nonWrapRight; + + if (wrapLeftDistance == wrapRightDistance) { + left = -180.0; + right = 180.0; + } else if (wrapLeftDistance < wrapRightDistance) { + left = nonWrapLeft; + right = wrapRight; + } else { + left = wrapLeft; + right = nonWrapRight; + } + } + } + } + + if (((left1 == -180) && (right1 == 180.0)) + || ((left2 == -180) && (right2 == 180.0))) { + left = -180; + right = 180; + } + + d->topLeft = QGeoCoordinate(top, left); + d->bottomRight = QGeoCoordinate(bottom, right); + + return *this; +} + +/*! + Returns the geo rectangle properties as a string. + + \since 5.5 +*/ +QString QGeoRectangle::toString() const +{ + if (type() != QGeoShape::RectangleType) { + qWarning("Not a rectangle a %d\n", type()); + return QStringLiteral("QGeoRectangle(not a rectangle)"); + } + + return QStringLiteral("QGeoRectangle({%1, %2}, {%3, %4})") + .arg(topLeft().latitude()) + .arg(topLeft().longitude()) + .arg(bottomRight().latitude()) + .arg(bottomRight().longitude()); +} + +/******************************************************************************* +*******************************************************************************/ + +QGeoRectanglePrivate::QGeoRectanglePrivate() +: QGeoShapePrivate(QGeoShape::RectangleType) +{ +} + +QGeoRectanglePrivate::QGeoRectanglePrivate(const QGeoCoordinate &topLeft, + const QGeoCoordinate &bottomRight) +: QGeoShapePrivate(QGeoShape::RectangleType), topLeft(topLeft), bottomRight(bottomRight) +{ +} + +QGeoRectanglePrivate::QGeoRectanglePrivate(const QGeoRectanglePrivate &other) +: QGeoShapePrivate(QGeoShape::RectangleType), topLeft(other.topLeft), + bottomRight(other.bottomRight) +{ +} + +QGeoRectanglePrivate::~QGeoRectanglePrivate() {} + +QGeoShapePrivate *QGeoRectanglePrivate::clone() const +{ + return new QGeoRectanglePrivate(*this); +} + +bool QGeoRectanglePrivate::operator==(const QGeoShapePrivate &other) const +{ + if (!QGeoShapePrivate::operator==(other)) + return false; + + const QGeoRectanglePrivate &otherBox = static_cast(other); + + return topLeft == otherBox.topLeft && bottomRight == otherBox.bottomRight; +} + +QT_END_NAMESPACE + diff --git a/src/positioning/qgeorectangle.h b/src/positioning/qgeorectangle.h new file mode 100644 index 0000000..7e92173 --- /dev/null +++ b/src/positioning/qgeorectangle.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEORECTANGLE_H +#define QGEORECTANGLE_H + +#include + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; +class QGeoRectanglePrivate; + +class Q_POSITIONING_EXPORT QGeoRectangle : public QGeoShape +{ + Q_GADGET + Q_PROPERTY(QGeoCoordinate bottomLeft READ bottomLeft WRITE setBottomLeft) + Q_PROPERTY(QGeoCoordinate bottomRight READ bottomRight WRITE setBottomRight) + Q_PROPERTY(QGeoCoordinate topLeft READ topLeft WRITE setTopLeft) + Q_PROPERTY(QGeoCoordinate topRight READ topRight WRITE setTopRight) + Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter) + Q_PROPERTY(double height READ height WRITE setHeight) + Q_PROPERTY(double width READ width WRITE setWidth) + +public: + QGeoRectangle(); + QGeoRectangle(const QGeoCoordinate ¢er, double degreesWidth, double degreesHeight); + QGeoRectangle(const QGeoCoordinate &topLeft, const QGeoCoordinate &bottomRight); + QGeoRectangle(const QList &coordinates); + QGeoRectangle(const QGeoRectangle &other); + QGeoRectangle(const QGeoShape &other); + + ~QGeoRectangle(); + + QGeoRectangle &operator=(const QGeoRectangle &other); + + using QGeoShape::operator==; + bool operator==(const QGeoRectangle &other) const; + + using QGeoShape::operator!=; + bool operator!=(const QGeoRectangle &other) const; + + void setTopLeft(const QGeoCoordinate &topLeft); + QGeoCoordinate topLeft() const; + + void setTopRight(const QGeoCoordinate &topRight); + QGeoCoordinate topRight() const; + + void setBottomLeft(const QGeoCoordinate &bottomLeft); + QGeoCoordinate bottomLeft() const; + + void setBottomRight(const QGeoCoordinate &bottomRight); + QGeoCoordinate bottomRight() const; + + void setCenter(const QGeoCoordinate ¢er); + QGeoCoordinate center() const; + + void setWidth(double degreesWidth); + double width() const; + + void setHeight(double degreesHeight); + double height() const; + + using QGeoShape::contains; + bool contains(const QGeoRectangle &rectangle) const; + bool intersects(const QGeoRectangle &rectangle) const; + + void translate(double degreesLatitude, double degreesLongitude); + QGeoRectangle translated(double degreesLatitude, double degreesLongitude) const; + + QGeoRectangle united(const QGeoRectangle &rectangle) const; + QGeoRectangle operator|(const QGeoRectangle &rectangle) const; + QGeoRectangle &operator|=(const QGeoRectangle &rectangle); + + Q_INVOKABLE QString toString() const; + +private: + inline QGeoRectanglePrivate *d_func(); + inline const QGeoRectanglePrivate *d_func() const; +}; + +Q_DECLARE_TYPEINFO(QGeoRectangle, Q_MOVABLE_TYPE); + +inline QGeoRectangle QGeoRectangle::operator|(const QGeoRectangle &rectangle) const +{ + return united(rectangle); +} + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoRectangle) + +#endif + diff --git a/src/positioning/qgeorectangle_p.h b/src/positioning/qgeorectangle_p.h new file mode 100644 index 0000000..188e554 --- /dev/null +++ b/src/positioning/qgeorectangle_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEORECTANGLE_P_H +#define QGEORECTANGLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeoshape_p.h" +#include "qgeocoordinate.h" + +QT_BEGIN_NAMESPACE + +class QGeoRectanglePrivate : public QGeoShapePrivate +{ +public: + QGeoRectanglePrivate(); + QGeoRectanglePrivate(const QGeoCoordinate &topLeft, const QGeoCoordinate &bottomRight); + QGeoRectanglePrivate(const QGeoRectanglePrivate &other); + ~QGeoRectanglePrivate(); + + bool isValid() const Q_DECL_OVERRIDE; + bool isEmpty() const Q_DECL_OVERRIDE; + bool contains(const QGeoCoordinate &coordinate) const Q_DECL_OVERRIDE; + + QGeoCoordinate center() const Q_DECL_OVERRIDE; + + void extendShape(const QGeoCoordinate &coordinate) Q_DECL_OVERRIDE; + + QGeoShapePrivate *clone() const Q_DECL_OVERRIDE; + + bool operator==(const QGeoShapePrivate &other) const Q_DECL_OVERRIDE; + + QGeoCoordinate topLeft; + QGeoCoordinate bottomRight; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeosatelliteinfo.cpp b/src/positioning/qgeosatelliteinfo.cpp new file mode 100644 index 0000000..9168183 --- /dev/null +++ b/src/positioning/qgeosatelliteinfo.cpp @@ -0,0 +1,314 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgeosatelliteinfo.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoSatelliteInfoPrivate +{ +public: + int signal; + int satId; + QGeoSatelliteInfo::SatelliteSystem system; + QHash doubleAttribs; +}; + + +/*! + \class QGeoSatelliteInfo + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QGeoSatelliteInfo class contains basic information about a satellite. + + \sa QGeoSatelliteInfoSource +*/ + +/*! + \enum QGeoSatelliteInfo::Attribute + Defines the attributes for the satellite information. + \value Elevation The elevation of the satellite, in degrees. + \value Azimuth The azimuth to true north, in degrees. +*/ + +/*! + \enum QGeoSatelliteInfo::SatelliteSystem + Defines the GNSS system of the satellite. + \value Undefined Not defined. + \value GPS Global Positioning System (USA). + \value GLONASS Global Positioning System (Russia). + +*/ + + +/*! + Creates a satellite information object. +*/ +QGeoSatelliteInfo::QGeoSatelliteInfo() + : d(new QGeoSatelliteInfoPrivate) +{ + d->signal = -1; + d->satId = -1; + d->system = QGeoSatelliteInfo::Undefined; +} + +/*! + Creates a satellite information object with the values of \a other. +*/ + +QGeoSatelliteInfo::QGeoSatelliteInfo(const QGeoSatelliteInfo &other) + : d(new QGeoSatelliteInfoPrivate) +{ + operator=(other); +} + +/*! + Destroys a satellite information object. +*/ +QGeoSatelliteInfo::~QGeoSatelliteInfo() +{ + delete d; +} + +/*! + Assigns the values from \a other to this object. +*/ +QGeoSatelliteInfo &QGeoSatelliteInfo::operator=(const QGeoSatelliteInfo & other) +{ + if (this == &other) + return *this; + + d->signal = other.d->signal; + d->satId = other.d->satId; + d->system = other.d->system; + d->doubleAttribs = other.d->doubleAttribs; + return *this; +} + +/*! + Returns true if all the information for this satellite + are the same as those of \a other. +*/ +bool QGeoSatelliteInfo::operator==(const QGeoSatelliteInfo &other) const +{ + return d->signal == other.d->signal + && d->satId == other.d->satId + && d->system == other.d->system + && d->doubleAttribs == other.d->doubleAttribs; +} + +/*! + \fn bool QGeoSatelliteInfo::operator!=(const QGeoSatelliteInfo &other) const; + + Returns true if any of the information for this satellite + are not the same as those of \a other. +*/ + + +/*! + Sets the Satellite System (GPS, GLONASS, ...) to \a system. +*/ +void QGeoSatelliteInfo::setSatelliteSystem(SatelliteSystem system) +{ + d->system = system; +} + +/*! + Returns the Satellite System (GPS, GLONASS, ...) +*/ +QGeoSatelliteInfo::SatelliteSystem QGeoSatelliteInfo::satelliteSystem() const +{ + return d->system; +} + +/*! + Sets the satellite identifier number to \a satId. + + The satellite identifier number can be used to identify a satellite inside the satellite system. + For satellite system GPS the satellite identifier number represents the PRN (Pseudo-random noise) number. + For satellite system GLONASS the satellite identifier number represents the slot number. +*/ +void QGeoSatelliteInfo::setSatelliteIdentifier(int satId) +{ + d->satId = satId; +} + +/*! + Returns the satellite identifier number. + + The satellite identifier number can be used to identify a satellite inside the satellite system. + For satellite system GPS the satellite identifier number represents the PRN (Pseudo-random noise) number. + For satellite system GLONASS the satellite identifier number represents the slot number. +*/ +int QGeoSatelliteInfo::satelliteIdentifier() const +{ + return d->satId; +} + +/*! + Sets the signal strength to \a signalStrength, in decibels. +*/ +void QGeoSatelliteInfo::setSignalStrength(int signalStrength) +{ + d->signal = signalStrength; +} + +/*! + Returns the signal strength, or -1 if the value has not been set. +*/ +int QGeoSatelliteInfo::signalStrength() const +{ + return d->signal; +} + +/*! + Sets the value for \a attribute to \a value. +*/ +void QGeoSatelliteInfo::setAttribute(Attribute attribute, qreal value) +{ + d->doubleAttribs[int(attribute)] = value; +} + +/*! + Returns the value of the specified \a attribute as a qreal value. + + Returns -1 if the value has not been set. + + \sa hasAttribute(), setAttribute() +*/ +qreal QGeoSatelliteInfo::attribute(Attribute attribute) const +{ + if (d->doubleAttribs.contains(int(attribute))) + return d->doubleAttribs[int(attribute)]; + return -1; +} + +/*! + Removes the specified \a attribute and its value. +*/ +void QGeoSatelliteInfo::removeAttribute(Attribute attribute) +{ + d->doubleAttribs.remove(int(attribute)); +} + +/*! + Returns true if the specified \a attribute is present in this update. +*/ +bool QGeoSatelliteInfo::hasAttribute(Attribute attribute) const +{ + return d->doubleAttribs.contains(int(attribute)); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QGeoSatelliteInfo &info) +{ + QDebugStateSaver saver(dbg); + dbg.nospace() << "QGeoSatelliteInfo(system=" << info.d->system; + dbg << ", satId=" << info.d->satId; + dbg << ", signal-strength=" << info.d->signal; + + + QList attribs = info.d->doubleAttribs.keys(); + for (int i = 0; i < attribs.count(); ++i) { + dbg << ", "; + switch (attribs[i]) { + case QGeoSatelliteInfo::Elevation: + dbg << "Elevation="; + break; + case QGeoSatelliteInfo::Azimuth: + dbg << "Azimuth="; + break; + } + dbg << info.d->doubleAttribs[attribs[i]]; + } + dbg << ')'; + return dbg; +} +#endif + +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QGeoSatelliteInfo &info) + \relates QGeoSatelliteInfo + + Writes the given \a info to the specified \a stream. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink + +*/ + +QDataStream &operator<<(QDataStream &stream, const QGeoSatelliteInfo &info) +{ + stream << info.d->signal; + stream << info.d->doubleAttribs; + stream << info.d->satId; + stream << info.d->system; + return stream; +} +#endif + +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator>>(QDataStream &stream, QGeoSatelliteInfo &info) + \relates QGeoSatelliteInfo + + Reads satellite information from the specified \a stream into the given + \a info. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>(QDataStream &stream, QGeoSatelliteInfo &info) +{ + int system; + stream >> info.d->signal; + stream >> info.d->doubleAttribs; + stream >> info.d->satId; + stream >> system; + info.d->system = (QGeoSatelliteInfo::SatelliteSystem)system; + return stream; +} +#endif + +QT_END_NAMESPACE diff --git a/src/positioning/qgeosatelliteinfo.h b/src/positioning/qgeosatelliteinfo.h new file mode 100644 index 0000000..e68d8d9 --- /dev/null +++ b/src/positioning/qgeosatelliteinfo.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOSATELLITEINFO_H +#define QGEOSATELLITEINFO_H + +#include + +QT_BEGIN_NAMESPACE + +class QDebug; +class QDataStream; + +class QGeoSatelliteInfoPrivate; +class Q_POSITIONING_EXPORT QGeoSatelliteInfo +{ +public: + enum Attribute { + Elevation, + Azimuth + }; + + enum SatelliteSystem { + Undefined = 0x00, + GPS = 0x01, + GLONASS = 0x02 + }; + + QGeoSatelliteInfo(); + QGeoSatelliteInfo(const QGeoSatelliteInfo &other); + ~QGeoSatelliteInfo(); + + QGeoSatelliteInfo &operator=(const QGeoSatelliteInfo &other); + + bool operator==(const QGeoSatelliteInfo &other) const; + inline bool operator!=(const QGeoSatelliteInfo &other) const { + return !operator==(other); + } + + void setSatelliteSystem(SatelliteSystem system); + SatelliteSystem satelliteSystem() const; + + void setSatelliteIdentifier(int satId); + int satelliteIdentifier() const; + + void setSignalStrength(int signalStrength); + int signalStrength() const; + + void setAttribute(Attribute attribute, qreal value); + qreal attribute(Attribute attribute) const; + void removeAttribute(Attribute attribute); + + bool hasAttribute(Attribute attribute) const; + +private: +#ifndef QT_NO_DEBUG_STREAM + friend Q_POSITIONING_EXPORT QDebug operator<<(QDebug dbg, const QGeoSatelliteInfo &info); +#endif +#ifndef QT_NO_DATASTREAM + friend Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &stream, const QGeoSatelliteInfo &info); + friend Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &stream, QGeoSatelliteInfo &info); +#endif + QGeoSatelliteInfoPrivate *d; +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_POSITIONING_EXPORT QDebug operator<<(QDebug dbg, const QGeoSatelliteInfo &info); +#endif + +#ifndef QT_NO_DATASTREAM +Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &stream, const QGeoSatelliteInfo &info); +Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &stream, QGeoSatelliteInfo &info); +#endif + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeosatelliteinfosource.cpp b/src/positioning/qgeosatelliteinfosource.cpp new file mode 100644 index 0000000..297f484 --- /dev/null +++ b/src/positioning/qgeosatelliteinfosource.cpp @@ -0,0 +1,350 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include "qgeopositioninfosourcefactory.h" +#include "qgeopositioninfosource_p.h" +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoSatelliteInfoSource + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QGeoSatelliteInfoSource class is an abstract base class for the distribution of satellite information updates. + + The static function QGeoSatelliteInfoSource::createDefaultSource() creates a default + satellite data source that is appropriate for the platform, if one is + available. Otherwise, available QGeoPositionInfoSourceFactory plugins will + be checked for one that has a satellite data source available. + + Call startUpdates() and stopUpdates() to start and stop regular updates, + or requestUpdate() to request a single update. + When an update is available, satellitesInViewUpdated() and/or + satellitesInUseUpdated() will be emitted. + + If regular satellite updates are required, setUpdateInterval() can be used + to specify how often these updates should be emitted. If no interval is + specified, updates are simply provided whenever they are available. + For example: + + \code + // Emit updates every 10 seconds if available + QGeoSatelliteInfoSource *source = QGeoSatelliteInfoSource::createDefaultSource(0); + if (source) + source->setUpdateInterval(10000); + \endcode + + To remove an update interval that was previously set, call + setUpdateInterval() with a value of 0. + + Note that the satellite source may have a minimum value requirement for + update intervals, as returned by minimumUpdateInterval(). +*/ + +class QGeoSatelliteInfoSourcePrivate +{ +public: + int interval; + QString providerName; +}; + +/*! + Creates a satellite source with the specified \a parent. +*/ +QGeoSatelliteInfoSource::QGeoSatelliteInfoSource(QObject *parent) + : QObject(parent), + d(new QGeoSatelliteInfoSourcePrivate) +{ + d->interval = 0; +} + +/*! + Destroys the satellite source. +*/ +QGeoSatelliteInfoSource::~QGeoSatelliteInfoSource() +{ + delete d; +} + +/*! + Returns the unique name of the satellite source implementation in use. + + This is the same name that can be passed to createSource() in order to + create a new instance of a particular satellite source implementation. +*/ +QString QGeoSatelliteInfoSource::sourceName() const +{ + return d->providerName; +} + + +/*! + \property QGeoSatelliteInfoSource::updateInterval + \brief This property holds the requested interval in milliseconds between each update. + + If the update interval is not set (or is set to 0) the + source will provide updates as often as necessary. + + If the update interval is set, the source will provide updates at an + interval as close to the requested interval as possible. If the requested + interval is less than the minimumUpdateInterval(), + the minimum interval is used instead. + + Changes to the update interval will happen as soon as is practical, however the + time the change takes may vary between implementations. Whether or not the elapsed + time from the previous interval is counted as part of the new interval is also + implementation dependent. + + The default value for this property is 0. + + Note: Subclass implementations must call the base implementation of + setUpdateInterval() so that updateInterval() returns the correct value. +*/ +void QGeoSatelliteInfoSource::setUpdateInterval(int msec) +{ + d->interval = msec; +} + +int QGeoSatelliteInfoSource::updateInterval() const +{ + return d->interval; +} + + + +/*! + Creates and returns a source with the specified \a parent that reads + from the system's default source of satellite update information, or the + highest priority available plugin. + + Returns 0 if the system has no default satellite source, no valid plugins + could be found or the user does not have the permission to access the satellite data. +*/ +QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(QObject *parent) +{ + QList plugins = QGeoPositionInfoSourcePrivate::pluginsSorted(); + foreach (const QJsonObject &obj, plugins) { + if (obj.value(QStringLiteral("Satellite")).isBool() + && obj.value(QStringLiteral("Satellite")).toBool()) + { + const QString testableKey = QStringLiteral("Testable"); + if (obj.contains(testableKey) && !obj.value(testableKey).toBool()) { + static bool inTest = qEnvironmentVariableIsSet("QT_QTESTLIB_RUNNING"); + if (inTest) + continue; + } + QGeoPositionInfoSourcePrivate d; + d.metaData = obj; + d.loadPlugin(); + QGeoSatelliteInfoSource *s = 0; + if (d.factory) + s = d.factory->satelliteInfoSource(parent); + if (s) + s->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString(); + return s; + } + } + + return 0; +} + +/*! + Creates and returns a source with the given \a parent, + by loading the plugin named \a sourceName. + + Returns 0 if the plugin cannot be found. +*/ +QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createSource(const QString &sourceName, QObject *parent) +{ + QHash plugins = QGeoPositionInfoSourcePrivate::plugins(); + if (plugins.contains(sourceName)) { + QGeoPositionInfoSourcePrivate d; + d.metaData = plugins.value(sourceName); + d.loadPlugin(); + QGeoSatelliteInfoSource *src = 0; + if (d.factory) + src = d.factory->satelliteInfoSource(parent); + if (src) + src->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString(); + return src; + } + + return 0; +} + +/*! + Returns a list of available source plugins, including the default system + backend if one is available. +*/ +QStringList QGeoSatelliteInfoSource::availableSources() +{ + QStringList plugins; + const QHash meta = QGeoPositionInfoSourcePrivate::plugins(); + for (auto it = meta.cbegin(), end = meta.cend(); it != end; ++it) { + if (it.value().value(QStringLiteral("Satellite")).isBool() + && it.value().value(QStringLiteral("Satellite")).toBool()) { + plugins << it.key(); + } + } + + return plugins; +} + +/*! + \fn void QGeoSatelliteInfoSource::satellitesInViewUpdated(const QList &satellites); + + If startUpdates() or requestUpdate() is called, this signal is emitted + when an update is available on the satellites that are + currently in view. + + The \a satellites parameter holds the satellites currently in view. +*/ + +/*! + \fn void QGeoSatelliteInfoSource::satellitesInUseUpdated(const QList &satellites); + + If startUpdates() or requestUpdate() is called, this signal is emitted + when an update is available on the number of satellites that are + currently in use. + + These are the satellites that are used to get a "fix" - that + is, those used to determine the current position. + + The \a satellites parameter holds the satellites currently in use. +*/ + +/*! + \property QGeoSatelliteInfoSource::minimumUpdateInterval + \brief This property holds the minimum time (in milliseconds) required to retrieve a satellite update. + + This is the minimum value accepted by setUpdateInterval() and + requestUpdate(). +*/ + + +/*! + \fn virtual void QGeoSatelliteInfoSource::startUpdates() = 0; + + Starts emitting updates at regular intervals. The updates will be + provided whenever new satellite information becomes available. + + If satellite information cannot be retrieved or some other + form of timeout has occurred the satellitesInViewUpdated() + and satellitesInUseUpdated() signals may be emitted with + empty parameter lists. + + \sa satellitesInViewUpdated(), satellitesInUseUpdated() +*/ + +/*! + \fn virtual void QGeoSatelliteInfoSource::stopUpdates() = 0; + + Stops emitting updates at regular intervals. +*/ + +/*! + \fn virtual void QGeoSatelliteInfoSource::requestUpdate(int timeout = 0); + + Attempts to get the current satellite information and emit + satellitesInViewUpdated() and satellitesInUseUpdated() with this + information. If the current satellite information cannot be found + within the given \a timeout (in milliseconds) or if \a timeout is less than the value returned by + minimumUpdateInterval(), requestTimeout() is + emitted. + + If the timeout is zero, the timeout defaults to a reasonable timeout + period as appropriate for the source. + + This does nothing if another update request is in progress. However + it can be called even if startUpdates() has already been called and + regular updates are in progress. +*/ + +/*! + \fn void QGeoSatelliteInfoSource::requestTimeout(); + + Emitted if requestUpdate() was called and the current satellite + information could not be retrieved within the specified timeout. + + While the triggering of this signal may be considered an error condition, + it does not imply the emission of the \c error() signal. Only the emission of + \c requestTimeout() is required to indicate a timeout. +*/ + +/*! + \fn QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSource::error() const = 0 + + Returns the last error that occurred. + + This signal is not emitted when a requestTimeout() has occurred. +*/ + +/*! + \fn void QGeoSatelliteInfoSource::error(QGeoSatelliteInfoSource::Error satelliteError) + + This signal is emitted after an error occurred. The \a satelliteError + parameter describes the type of error that occurred. + +*/ + +/*! + \enum QGeoSatelliteInfoSource::Error + + The Error enumeration represents the errors which can occur. + + \value AccessError The connection setup to the satellite backend failed because the + application lacked the required privileges. + \value ClosedError The satellite backend closed the connection, which happens for example in case + the user is switching location services to off. This object becomes invalid and should be deleted. + A new satellite source can be created by calling createDefaultSource() later on. + \value NoError No error has occurred. + \value UnknownSourceError An unidentified error occurred. + */ + + +#include "moc_qgeosatelliteinfosource.cpp" + +QT_END_NAMESPACE diff --git a/src/positioning/qgeosatelliteinfosource.h b/src/positioning/qgeosatelliteinfosource.h new file mode 100644 index 0000000..391eefc --- /dev/null +++ b/src/positioning/qgeosatelliteinfosource.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGEOSATELLITEINFOSOURCE_H +#define QGEOSATELLITEINFOSOURCE_H + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoSatelliteInfoSourcePrivate; +class Q_POSITIONING_EXPORT QGeoSatelliteInfoSource : public QObject +{ + Q_OBJECT + Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval) + Q_PROPERTY(int minimumUpdateInterval READ minimumUpdateInterval) + +public: + enum Error { + AccessError = 0, + ClosedError = 1, + NoError = 2, + UnknownSourceError = -1 + }; + Q_ENUMS(Error) + + explicit QGeoSatelliteInfoSource(QObject *parent); + virtual ~QGeoSatelliteInfoSource(); + + static QGeoSatelliteInfoSource *createDefaultSource(QObject *parent); + static QGeoSatelliteInfoSource *createSource(const QString &sourceName, QObject *parent); + static QStringList availableSources(); + + QString sourceName() const; + + virtual void setUpdateInterval(int msec); + int updateInterval() const; + virtual int minimumUpdateInterval() const = 0; + virtual Error error() const = 0; + +public Q_SLOTS: + virtual void startUpdates() = 0; + virtual void stopUpdates() = 0; + + virtual void requestUpdate(int timeout = 0) = 0; + +Q_SIGNALS: + void satellitesInViewUpdated(const QList &satellites); + void satellitesInUseUpdated(const QList &satellites); + void requestTimeout(); + void error(QGeoSatelliteInfoSource::Error); + +private: + Q_DISABLE_COPY(QGeoSatelliteInfoSource) + QGeoSatelliteInfoSourcePrivate *d; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qgeoshape.cpp b/src/positioning/qgeoshape.cpp new file mode 100644 index 0000000..bac3760 --- /dev/null +++ b/src/positioning/qgeoshape.cpp @@ -0,0 +1,377 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoshape.h" +#include "qgeoshape_p.h" +#include "qgeorectangle.h" +#include "qgeocircle.h" + +#ifndef QT_NO_DEBUG_STREAM +#include +#endif + +#ifndef QT_NO_DATASTREAM +#include +#endif + +QT_BEGIN_NAMESPACE + +QGeoShapePrivate::QGeoShapePrivate(QGeoShape::ShapeType type) +: type(type) +{ +} + +QGeoShapePrivate::~QGeoShapePrivate() +{ +} + +bool QGeoShapePrivate::operator==(const QGeoShapePrivate &other) const +{ + return type == other.type; +} + +/*! + \class QGeoShape + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QGeoShape class defines a geographic area. + + This class is the base class for classes which specify a geographic + area. + + For the sake of consistency, subclasses should describe the specific + details of the associated areas in terms of QGeoCoordinate instances + and distances in meters. + + This class is a \l Q_GADGET since Qt 5.5. It can be + \l{Cpp_value_integration_positioning}{directly used from C++ and QML}. +*/ + +/*! + \enum QGeoShape::ShapeType + + Describes the type of the shape. + + \value UnknownType A shape of unknown type. + \value RectangleType A rectangular shape. + \value CircleType A circular shape. +*/ + +/*! + \property QGeoShape::type + \brief This property holds the type of this geo shape. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoShape::isValid + \brief This property holds the validity of the geo shape. + + A geo shape is considered to be invalid if some of the data that is required to + unambiguously describe the geo shape has not been set or has been set to an + unsuitable value depending on the subclass of this object. The default constructed + objects of this type are invalid. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ + +/*! + \property QGeoShape::isEmpty + \brief This property defines whether this geo shape is empty. + + An empty geo shape is a region which has a geometrical area of 0. + + While this property is introduced in Qt 5.5, the related accessor functions + exist since the first version of this class. + + \since 5.5 +*/ +inline QGeoShapePrivate *QGeoShape::d_func() +{ + return static_cast(d_ptr.data()); +} + +inline const QGeoShapePrivate *QGeoShape::d_func() const +{ + return static_cast(d_ptr.constData()); +} + +/*! + Constructs a new invalid geo shape of \l UnknownType. +*/ +QGeoShape::QGeoShape() +{ +} + +/*! + Constructs a new geo shape which is a copy of \a other. +*/ +QGeoShape::QGeoShape(const QGeoShape &other) +: d_ptr(other.d_ptr) +{ +} + +/*! + \internal +*/ +QGeoShape::QGeoShape(QGeoShapePrivate *d) +: d_ptr(d) +{ +} + +/*! + Destroys this geo shape. +*/ +QGeoShape::~QGeoShape() +{ +} + +/*! + Returns the type of this geo shape. +*/ +QGeoShape::ShapeType QGeoShape::type() const +{ + Q_D(const QGeoShape); + + if (d) + return d->type; + else + return UnknownType; +} + +/*! + Returns whether this geo shape is valid. + +*/ +bool QGeoShape::isValid() const +{ + Q_D(const QGeoShape); + + if (d) + return d->isValid(); + else + return false; +} + +/*! + Returns whether this geo shape is empty. + + An empty geo shape is a region which has a geometrical area of 0. +*/ +bool QGeoShape::isEmpty() const +{ + Q_D(const QGeoShape); + + if (d) + return d->isEmpty(); + else + return true; +} + +/*! + Returns whether the coordinate \a coordinate is contained within this geo shape. +*/ +bool QGeoShape::contains(const QGeoCoordinate &coordinate) const +{ + Q_D(const QGeoShape); + + if (d) + return d->contains(coordinate); + else + return false; +} + +/*! + Returns the coordinate located at the geometric center of the geo shape. + + \since 5.5 +*/ +QGeoCoordinate QGeoShape::center() const +{ + Q_D(const QGeoShape); + + if (d) + return d->center(); + else + return QGeoCoordinate(); +} + +/*! + Extends the geo shape to also cover the coordinate \a coordinate +*/ +void QGeoShape::extendShape(const QGeoCoordinate &coordinate) +{ + Q_D(QGeoShape); + + if (d) + d->extendShape(coordinate); +} + + +/*! + Returns true if the \a other geo shape is equivalent to this geo shape, otherwise returns + false. +*/ +bool QGeoShape::operator==(const QGeoShape &other) const +{ + Q_D(const QGeoShape); + + if (d == other.d_func()) + return true; + + if (!d || !(other.d_func())) + return false; + + return *d == *other.d_func(); +} + +/*! + Returns true if the \a other geo shape is not equivalent to this geo shape, otherwise returns + false. +*/ +bool QGeoShape::operator!=(const QGeoShape &other) const +{ + return !(*this == other); +} + +/*! + Assigns \a other to this geo shape and returns a reference to this geo shape. +*/ +QGeoShape &QGeoShape::operator=(const QGeoShape &other) +{ + if (this == &other) + return *this; + + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns a string representation of this geo shape. + + \since 5.5 +*/ +QString QGeoShape::toString() const +{ + return QStringLiteral("QGeoShape(%1)").arg(type()); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QGeoShape &shape) +{ + QDebugStateSaver saver(dbg); + dbg.nospace() << "QGeoShape("; + switch (shape.type()) { + case QGeoShape::UnknownType: + dbg << "Unknown"; + break; + case QGeoShape::RectangleType: + dbg << "Rectangle"; + break; + case QGeoShape::CircleType: + dbg << "Circle"; + } + + dbg << ')'; + + return dbg; +} +#endif + +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &stream, const QGeoShape &shape) +{ + stream << quint32(shape.type()); + switch (shape.type()) { + case QGeoShape::UnknownType: + break; + case QGeoShape::RectangleType: { + QGeoRectangle r = shape; + stream << r.topLeft() << r.bottomRight(); + break; + } + case QGeoShape::CircleType: { + QGeoCircle c = shape; + stream << c.center() << c.radius(); + break; + } + } + + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QGeoShape &shape) +{ + quint32 type; + stream >> type; + + switch (type) { + case QGeoShape::UnknownType: + shape = QGeoShape(); + break; + case QGeoShape::RectangleType: { + QGeoCoordinate tl; + QGeoCoordinate br; + stream >> tl >> br; + shape = QGeoRectangle(tl, br); + break; + } + case QGeoShape::CircleType: { + QGeoCoordinate c; + qreal r; + stream >> c >> r; + shape = QGeoCircle(c, r); + break; + } + } + + return stream; +} +#endif + +QT_END_NAMESPACE diff --git a/src/positioning/qgeoshape.h b/src/positioning/qgeoshape.h new file mode 100644 index 0000000..f8a3035 --- /dev/null +++ b/src/positioning/qgeoshape.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSHAPE_H +#define QGEOSHAPE_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QDebug; +class QGeoShapePrivate; + +class Q_POSITIONING_EXPORT QGeoShape +{ + Q_GADGET + Q_PROPERTY(ShapeType type READ type) + Q_PROPERTY(bool isValid READ isValid) + Q_PROPERTY(bool isEmpty READ isEmpty) + Q_ENUMS(ShapeType) + +public: + QGeoShape(); + QGeoShape(const QGeoShape &other); + ~QGeoShape(); + + enum ShapeType { + UnknownType, + RectangleType, + CircleType + }; + + ShapeType type() const; + + bool isValid() const; + bool isEmpty() const; + Q_INVOKABLE bool contains(const QGeoCoordinate &coordinate) const; + + QGeoCoordinate center() const; + + void extendShape(const QGeoCoordinate &coordinate); + + bool operator==(const QGeoShape &other) const; + bool operator!=(const QGeoShape &other) const; + + QGeoShape &operator=(const QGeoShape &other); + + Q_INVOKABLE QString toString() const; +protected: + QGeoShape(QGeoShapePrivate *d); + + QSharedDataPointer d_ptr; + +private: + inline QGeoShapePrivate *d_func(); + inline const QGeoShapePrivate *d_func() const; +}; + +Q_DECLARE_TYPEINFO(QGeoShape, Q_MOVABLE_TYPE); + +#ifndef QT_NO_DEBUG_STREAM +Q_POSITIONING_EXPORT QDebug operator<<(QDebug, const QGeoShape &); +#endif + +#ifndef QT_NO_DATASTREAM +Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &stream, const QGeoShape &shape); +Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &stream, QGeoShape &shape); +#endif + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoShape) + +#endif + diff --git a/src/positioning/qgeoshape_p.h b/src/positioning/qgeoshape_p.h new file mode 100644 index 0000000..275886f --- /dev/null +++ b/src/positioning/qgeoshape_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSHAPE_P_H +#define QGEOSHAPE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include "qgeoshape.h" + +QT_BEGIN_NAMESPACE + +class QGeoShapePrivate : public QSharedData +{ +public: + explicit QGeoShapePrivate(QGeoShape::ShapeType type); + virtual ~QGeoShapePrivate(); + + virtual bool isValid() const = 0; + virtual bool isEmpty() const = 0; + virtual bool contains(const QGeoCoordinate &coordinate) const = 0; + + virtual QGeoCoordinate center() const = 0; + + virtual void extendShape(const QGeoCoordinate &coordinate) = 0; + + virtual QGeoShapePrivate *clone() const = 0; + + virtual bool operator==(const QGeoShapePrivate &other) const; + + QGeoShape::ShapeType type; +}; + +// don't use the copy constructor when detaching from a QSharedDataPointer, use virtual clone() +// call instead. +template <> +Q_INLINE_TEMPLATE QGeoShapePrivate *QSharedDataPointer::clone() +{ + return d->clone(); +} + +QT_END_NAMESPACE + +#endif + diff --git a/src/positioning/qlocationdata_simulator.cpp b/src/positioning/qlocationdata_simulator.cpp new file mode 100644 index 0000000..3045b86 --- /dev/null +++ b/src/positioning/qlocationdata_simulator.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlocationdata_simulator_p.h" + +#include + +QT_BEGIN_NAMESPACE + +QGeoPositionInfoData::QGeoPositionInfoData() + : latitude(0.0), + longitude(0.0), + altitude(0.0), + direction(0.0), + groundSpeed(0.0), + verticalSpeed(0.0), + magneticVariation(0.0), + horizontalAccuracy(0.0), + verticalAccuracy(0.0), + dateTime(), + minimumInterval(0), + enabled(false) {} + +QGeoSatelliteInfoData::SatelliteInfo::SatelliteInfo() + : azimuth(0.0), + elevation(0.0), + signalStrength(0), + inUse(false), + satelliteSystem(Undefined), + satelliteIdentifier(0) {} + +void qt_registerLocationTypes() +{ + qRegisterMetaTypeStreamOperators("QGeoPositionInfoData"); + qRegisterMetaTypeStreamOperators("QGeoSatelliteInfoData"); + qRegisterMetaTypeStreamOperators("QGeoSatelliteInfoData::SatelliteInfo"); +} + +QDataStream &operator<<(QDataStream &out, const QGeoPositionInfoData &s) +{ + out << s.latitude << s.longitude << s.altitude; + out << s.direction << s.groundSpeed << s.verticalSpeed << s.magneticVariation << s.horizontalAccuracy << s.verticalAccuracy; + out << s.dateTime; + out << s.minimumInterval << s.enabled; + return out; +} + +QDataStream &operator>>(QDataStream &in, QGeoPositionInfoData &s) +{ + in >> s.latitude >> s.longitude >> s.altitude; + in >> s.direction >> s.groundSpeed >> s.verticalSpeed >> s.magneticVariation >> s.horizontalAccuracy >> s.verticalAccuracy; + in >> s.dateTime; + in >> s.minimumInterval >> s.enabled; + return in; +} + +QDataStream &operator<<(QDataStream &out, const QGeoSatelliteInfoData &s) +{ + out << s.satellites; + return out; +} + +QDataStream &operator>>(QDataStream &in, QGeoSatelliteInfoData &s) +{ + in >> s.satellites; + return in; +} + +QDataStream &operator<<(QDataStream &out, const QGeoSatelliteInfoData::SatelliteInfo &s) +{ + out << s.azimuth << s.elevation << s.signalStrength << s.inUse << static_cast(s.satelliteSystem) << s.satelliteIdentifier; + return out; +} + +QDataStream &operator>>(QDataStream &in, QGeoSatelliteInfoData::SatelliteInfo &s) +{ + qint32 satelliteSystem; + in >> s.azimuth >> s.elevation >> s.signalStrength >> s.inUse >> satelliteSystem >> s.satelliteIdentifier; + s.satelliteSystem = static_cast(satelliteSystem); + return in; +} + +QT_END_NAMESPACE diff --git a/src/positioning/qlocationdata_simulator_p.h b/src/positioning/qlocationdata_simulator_p.h new file mode 100644 index 0000000..47f3acf --- /dev/null +++ b/src/positioning/qlocationdata_simulator_p.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFODATA_SIMULATOR_P_H +#define QGEOPOSITIONINFODATA_SIMULATOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +// +// DO NOT REMOVE +// ------------- +// +// This header file contains structures used to serialize communication between +// simulator's client and server implementations, it is included by simulator +// positioning plugin. + +#include "qpositioningglobal_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +struct Q_POSITIONING_PRIVATE_EXPORT QGeoPositionInfoData +{ + QGeoPositionInfoData(); + + // Coordinate information + double latitude; + double longitude; + double altitude; + + // Attributes + // ### transmit whether attributes are set or not + qreal direction; + qreal groundSpeed; + qreal verticalSpeed; + qreal magneticVariation; + qreal horizontalAccuracy; + qreal verticalAccuracy; + + // DateTime info + QDateTime dateTime; + + int minimumInterval; + bool enabled; +}; + +struct Q_POSITIONING_PRIVATE_EXPORT QGeoSatelliteInfoData +{ + struct SatelliteInfo + { + SatelliteInfo(); + + // This enum duplicates the SatelliteSystem enum defined in qgeosatelliteinfo.h, which cannot be + // included as this file must compile with Qt4 (it is used by Qt Simulator) + enum SatelliteSystem + { + Undefined = 0x00, + GPS = 0x01, + GLONASS = 0x02 + }; + + qreal azimuth; + qreal elevation; + int signalStrength; + bool inUse; + SatelliteSystem satelliteSystem; + int satelliteIdentifier; + }; + + QList satellites; +}; + +Q_POSITIONING_PRIVATE_EXPORT void qt_registerLocationTypes(); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &out, const QGeoPositionInfoData &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &in, QGeoPositionInfoData &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &out, const QGeoSatelliteInfoData &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &in, QGeoSatelliteInfoData &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &out, const QGeoSatelliteInfoData::SatelliteInfo &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &in, QGeoSatelliteInfoData::SatelliteInfo &s); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoPositionInfoData) +Q_DECLARE_METATYPE(QGeoSatelliteInfoData) +Q_DECLARE_METATYPE(QGeoSatelliteInfoData::SatelliteInfo) + +#endif // QGEOPOSITIONINFODATA_SIMULATOR_P_H diff --git a/src/positioning/qlocationutils.cpp b/src/positioning/qlocationutils.cpp new file mode 100644 index 0000000..829f1bb --- /dev/null +++ b/src/positioning/qlocationutils.cpp @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qlocationutils_p.h" +#include "qgeopositioninfo.h" + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +// converts e.g. 15306.0235 from NMEA sentence to 153.100392 +static double qlocationutils_nmeaDegreesToDecimal(double nmeaDegrees) +{ + double deg; + double min = 100.0 * modf(nmeaDegrees / 100.0, °); + return deg + (min / 60.0); +} + +static void qlocationutils_readGga(const char *data, int size, QGeoPositionInfo *info, double uere, + bool *hasFix) +{ + QByteArray sentence(data, size); + QList parts = sentence.split(','); + QGeoCoordinate coord; + + if (hasFix && parts.count() > 6 && parts[6].count() > 0) + *hasFix = parts[6].toInt() > 0; + + if (parts.count() > 1 && parts[1].count() > 0) { + QTime time; + if (QLocationUtils::getNmeaTime(parts[1], &time)) + info->setTimestamp(QDateTime(QDate(), time, Qt::UTC)); + } + + if (parts.count() > 5 && parts[3].count() == 1 && parts[5].count() == 1) { + double lat; + double lng; + if (QLocationUtils::getNmeaLatLong(parts[2], parts[3][0], parts[4], parts[5][0], &lat, &lng)) { + coord.setLatitude(lat); + coord.setLongitude(lng); + } + } + + if (parts.count() > 8 && !parts[8].isEmpty()) { + bool hasHdop = false; + double hdop = parts[8].toDouble(&hasHdop); + if (hasHdop) + info->setAttribute(QGeoPositionInfo::HorizontalAccuracy, 2 * hdop * uere); + } + + if (parts.count() > 9 && parts[9].count() > 0) { + bool hasAlt = false; + double alt = parts[9].toDouble(&hasAlt); + if (hasAlt) + coord.setAltitude(alt); + } + + if (coord.type() != QGeoCoordinate::InvalidCoordinate) + info->setCoordinate(coord); +} + +static void qlocationutils_readGsa(const char *data, int size, QGeoPositionInfo *info, double uere, + bool *hasFix) +{ + QList parts = QByteArray::fromRawData(data, size).split(','); + + if (hasFix && parts.count() > 2 && !parts[2].isEmpty()) + *hasFix = parts[2].toInt() > 0; + + if (parts.count() > 16 && !parts[16].isEmpty()) { + bool hasHdop = false; + double hdop = parts[16].toDouble(&hasHdop); + if (hasHdop) + info->setAttribute(QGeoPositionInfo::HorizontalAccuracy, 2 * hdop * uere); + } + + if (parts.count() > 17 && !parts[17].isEmpty()) { + bool hasVdop = false; + double vdop = parts[17].toDouble(&hasVdop); + if (hasVdop) + info->setAttribute(QGeoPositionInfo::VerticalAccuracy, 2 * vdop * uere); + } +} + +static void qlocationutils_readGll(const char *data, int size, QGeoPositionInfo *info, bool *hasFix) +{ + QByteArray sentence(data, size); + QList parts = sentence.split(','); + QGeoCoordinate coord; + + if (hasFix && parts.count() > 6 && parts[6].count() > 0) + *hasFix = (parts[6][0] == 'A'); + + if (parts.count() > 5 && parts[5].count() > 0) { + QTime time; + if (QLocationUtils::getNmeaTime(parts[5], &time)) + info->setTimestamp(QDateTime(QDate(), time, Qt::UTC)); + } + + if (parts.count() > 4 && parts[2].count() == 1 && parts[4].count() == 1) { + double lat; + double lng; + if (QLocationUtils::getNmeaLatLong(parts[1], parts[2][0], parts[3], parts[4][0], &lat, &lng)) { + coord.setLatitude(lat); + coord.setLongitude(lng); + } + } + + if (coord.type() != QGeoCoordinate::InvalidCoordinate) + info->setCoordinate(coord); +} + +static void qlocationutils_readRmc(const char *data, int size, QGeoPositionInfo *info, bool *hasFix) +{ + QByteArray sentence(data, size); + QList parts = sentence.split(','); + QGeoCoordinate coord; + QDate date; + QTime time; + + if (hasFix && parts.count() > 2 && parts[2].count() > 0) + *hasFix = (parts[2][0] == 'A'); + + if (parts.count() > 9 && parts[9].count() == 6) { + date = QDate::fromString(QString::fromLatin1(parts[9]), QStringLiteral("ddMMyy")); + if (date.isValid()) + date = date.addYears(100); // otherwise starts from 1900 + else + date = QDate(); + } + + if (parts.count() > 1 && parts[1].count() > 0) + QLocationUtils::getNmeaTime(parts[1], &time); + + if (parts.count() > 6 && parts[4].count() == 1 && parts[6].count() == 1) { + double lat; + double lng; + if (QLocationUtils::getNmeaLatLong(parts[3], parts[4][0], parts[5], parts[6][0], &lat, &lng)) { + coord.setLatitude(lat); + coord.setLongitude(lng); + } + } + + bool parsed = false; + double value = 0.0; + if (parts.count() > 7 && parts[7].count() > 0) { + value = parts[7].toDouble(&parsed); + if (parsed) + info->setAttribute(QGeoPositionInfo::GroundSpeed, qreal(value * 1.852 / 3.6)); // knots -> m/s + } + if (parts.count() > 8 && parts[8].count() > 0) { + value = parts[8].toDouble(&parsed); + if (parsed) + info->setAttribute(QGeoPositionInfo::Direction, qreal(value)); + } + if (parts.count() > 11 && parts[11].count() == 1 + && (parts[11][0] == 'E' || parts[11][0] == 'W')) { + value = parts[10].toDouble(&parsed); + if (parsed) { + if (parts[11][0] == 'W') + value *= -1; + info->setAttribute(QGeoPositionInfo::MagneticVariation, qreal(value)); + } + } + + if (coord.type() != QGeoCoordinate::InvalidCoordinate) + info->setCoordinate(coord); + + info->setTimestamp(QDateTime(date, time, Qt::UTC)); +} + +static void qlocationutils_readVtg(const char *data, int size, QGeoPositionInfo *info, bool *hasFix) +{ + if (hasFix) + *hasFix = false; + + QByteArray sentence(data, size); + QList parts = sentence.split(','); + + bool parsed = false; + double value = 0.0; + if (parts.count() > 1 && parts[1].count() > 0) { + value = parts[1].toDouble(&parsed); + if (parsed) + info->setAttribute(QGeoPositionInfo::Direction, qreal(value)); + } + if (parts.count() > 7 && parts[7].count() > 0) { + value = parts[7].toDouble(&parsed); + if (parsed) + info->setAttribute(QGeoPositionInfo::GroundSpeed, qreal(value / 3.6)); // km/h -> m/s + } +} + +static void qlocationutils_readZda(const char *data, int size, QGeoPositionInfo *info, bool *hasFix) +{ + if (hasFix) + *hasFix = false; + + QByteArray sentence(data, size); + QList parts = sentence.split(','); + QDate date; + QTime time; + + if (parts.count() > 1 && parts[1].count() > 0) + QLocationUtils::getNmeaTime(parts[1], &time); + + if (parts.count() > 4 && parts[2].count() > 0 && parts[3].count() > 0 + && parts[4].count() == 4) { // must be full 4-digit year + int day = parts[2].toUInt(); + int month = parts[3].toUInt(); + int year = parts[4].toUInt(); + if (day > 0 && month > 0 && year > 0) + date.setDate(year, month, day); + } + + info->setTimestamp(QDateTime(date, time, Qt::UTC)); +} + +bool QLocationUtils::getPosInfoFromNmea(const char *data, int size, QGeoPositionInfo *info, + double uere, bool *hasFix) +{ + if (!info) + return false; + + if (hasFix) + *hasFix = false; + if (size < 6 || data[0] != '$' || !hasValidNmeaChecksum(data, size)) + return false; + + // Adjust size so that * and following characters are not parsed by the following functions. + for (int i = 0; i < size; ++i) { + if (data[i] == '*') { + size = i; + break; + } + } + + if (data[3] == 'G' && data[4] == 'G' && data[5] == 'A') { + // "$--GGA" sentence. + qlocationutils_readGga(data, size, info, uere, hasFix); + return true; + } + + if (data[3] == 'G' && data[4] == 'S' && data[5] == 'A') { + // "$--GSA" sentence. + qlocationutils_readGsa(data, size, info, uere, hasFix); + return true; + } + + if (data[3] == 'G' && data[4] == 'L' && data[5] == 'L') { + // "$--GLL" sentence. + qlocationutils_readGll(data, size, info, hasFix); + return true; + } + + if (data[3] == 'R' && data[4] == 'M' && data[5] == 'C') { + // "$--RMC" sentence. + qlocationutils_readRmc(data, size, info, hasFix); + return true; + } + + if (data[3] == 'V' && data[4] == 'T' && data[5] == 'G') { + // "$--VTG" sentence. + qlocationutils_readVtg(data, size, info, hasFix); + return true; + } + + if (data[3] == 'Z' && data[4] == 'D' && data[5] == 'A') { + // "$--ZDA" sentence. + qlocationutils_readZda(data, size, info, hasFix); + return true; + } + + return false; +} + +bool QLocationUtils::hasValidNmeaChecksum(const char *data, int size) +{ + int asteriskIndex = -1; + for (int i = 0; i < size; ++i) { + if (data[i] == '*') { + asteriskIndex = i; + break; + } + } + + const int CSUM_LEN = 2; + if (asteriskIndex < 0 || asteriskIndex + CSUM_LEN >= size) + return false; + + // XOR byte value of all characters between '$' and '*' + int result = 0; + for (int i = 1; i < asteriskIndex; ++i) + result ^= data[i]; + /* + char calc[CSUM_LEN + 1]; + ::snprintf(calc, CSUM_LEN + 1, "%02x", result); + return ::strncmp(calc, &data[asteriskIndex+1], 2) == 0; + */ + + QByteArray checkSumBytes(&data[asteriskIndex + 1], 2); + bool ok = false; + int checksum = checkSumBytes.toInt(&ok,16); + return ok && checksum == result; +} + +bool QLocationUtils::getNmeaTime(const QByteArray &bytes, QTime *time) +{ + int dotIndex = bytes.indexOf('.'); + QTime tempTime; + + if (dotIndex < 0) { + tempTime = QTime::fromString(QString::fromLatin1(bytes.constData()), + QStringLiteral("hhmmss")); + } else { + tempTime = QTime::fromString(QString::fromLatin1(bytes.mid(0, dotIndex)), + QStringLiteral("hhmmss")); + bool hasMsecs = false; + int midLen = qMin(3, bytes.size() - dotIndex - 1); + int msecs = bytes.mid(dotIndex + 1, midLen).toUInt(&hasMsecs); + if (hasMsecs) + tempTime = tempTime.addMSecs(msecs); + } + + if (tempTime.isValid()) { + *time = tempTime; + return true; + } + return false; +} + +bool QLocationUtils::getNmeaLatLong(const QByteArray &latString, char latDirection, const QByteArray &lngString, char lngDirection, double *lat, double *lng) +{ + if ((latDirection != 'N' && latDirection != 'S') + || (lngDirection != 'E' && lngDirection != 'W')) { + return false; + } + + bool hasLat = false; + bool hasLong = false; + double tempLat = latString.toDouble(&hasLat); + double tempLng = lngString.toDouble(&hasLong); + if (hasLat && hasLong) { + tempLat = qlocationutils_nmeaDegreesToDecimal(tempLat); + if (latDirection == 'S') + tempLat *= -1; + tempLng = qlocationutils_nmeaDegreesToDecimal(tempLng); + if (lngDirection == 'W') + tempLng *= -1; + + if (isValidLat(tempLat) && isValidLong(tempLng)) { + *lat = tempLat; + *lng = tempLng; + return true; + } + } + return false; +} + +QT_END_NAMESPACE + diff --git a/src/positioning/qlocationutils_p.h b/src/positioning/qlocationutils_p.h new file mode 100644 index 0000000..00c4d3e --- /dev/null +++ b/src/positioning/qlocationutils_p.h @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QLOCATIONUTILS_P_H +#define QLOCATIONUTILS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE +class QTime; +class QByteArray; + +class QGeoPositionInfo; +class QLocationUtils +{ +public: + enum CardinalDirection { + CardinalN, + CardinalE, + CardinalS, + CardinalW, + CardinalNE, + CardinalSE, + CardinalSW, + CardinalNW, + CardinalNNE, + CardinalENE, + CardinalESE, + CardinalSSE, + CardinalSSW, + CardinalWSW, + CardinalWNW, + CardinalNNW + }; + + inline static bool isValidLat(double lat) { + return lat >= -90 && lat <= 90; + } + inline static bool isValidLong(double lng) { + return lng >= -180 && lng <= 180; + } + + inline static double clipLat(double lat) { + if (lat > 90) + lat = 90; + else if (lat < -90) + lat = -90; + return lat; + } + + inline static double wrapLong(double lng) { + if (lng > 180) + lng -= 360; + else if (lng < -180) + lng += 360; + return lng; + } + + inline static CardinalDirection azimuthToCardinalDirection4(double azimuth) + { + azimuth = fmod(azimuth, 360.0); + if (azimuth < 45.0 || azimuth > 315.0 ) + return CardinalN; + else if (azimuth < 135.0) + return CardinalE; + else if (azimuth < 225.0) + return CardinalS; + else + return CardinalW; + } + + inline static CardinalDirection azimuthToCardinalDirection8(double azimuth) + { + azimuth = fmod(azimuth, 360.0); + if (azimuth < 22.5 || azimuth > 337.5 ) + return CardinalN; + else if (azimuth < 67.5) + return CardinalNE; + else if (azimuth < 112.5) + return CardinalE; + else if (azimuth < 157.5) + return CardinalSE; + else if (azimuth < 202.5) + return CardinalS; + + else if (azimuth < 247.5) + return CardinalSW; + else if (azimuth < 292.5) + return CardinalW; + else + return CardinalNW; + } + + inline static CardinalDirection azimuthToCardinalDirection16(double azimuth) + { + azimuth = fmod(azimuth, 360.0); + if (azimuth < 11.5 || azimuth > 348.75 ) + return CardinalN; + else if (azimuth < 33.75) + return CardinalNNE; + else if (azimuth < 56.25) + return CardinalNE; + else if (azimuth < 78.75) + return CardinalENE; + else if (azimuth < 101.25) + return CardinalE; + else if (azimuth < 123.75) + return CardinalESE; + else if (azimuth < 146.25) + return CardinalSE; + else if (azimuth < 168.75) + return CardinalSSE; + else if (azimuth < 191.25) + return CardinalS; + + else if (azimuth < 213.75) + return CardinalSSW; + else if (azimuth < 236.25) + return CardinalSW; + else if (azimuth < 258.75) + return CardinalWSW; + else if (azimuth < 281.25) + return CardinalW; + else if (azimuth < 303.75) + return CardinalWNW; + else if (azimuth < 326.25) + return CardinalNW; + else + return CardinalNNW; + } + + /* + Creates a QGeoPositionInfo from a GGA, GLL, RMC, VTG or ZDA sentence. + + Note: + - GGA and GLL sentences have time but not date so the update's + QDateTime object will have an invalid date. + - RMC reports date with a two-digit year so in this case the year + is assumed to be after the year 2000. + */ + Q_AUTOTEST_EXPORT static bool getPosInfoFromNmea(const char *data, int size, + QGeoPositionInfo *info, double uere, + bool *hasFix = 0); + + /* + Returns true if the given NMEA sentence has a valid checksum. + */ + Q_AUTOTEST_EXPORT static bool hasValidNmeaChecksum(const char *data, int size); + + /* + Returns time from a string in hhmmss or hhmmss.z+ format. + */ + Q_AUTOTEST_EXPORT static bool getNmeaTime(const QByteArray &bytes, QTime *time); + + /* + Accepts for example ("2734.7964", 'S', "15306.0124", 'E') and returns the + lat-long values. Fails if lat or long fail isValidLat() or isValidLong(). + */ + Q_AUTOTEST_EXPORT static bool getNmeaLatLong(const QByteArray &latString, char latDirection, const QByteArray &lngString, char lngDirection, double *lat, double *lon); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qnmeapositioninfosource.cpp b/src/positioning/qnmeapositioninfosource.cpp new file mode 100644 index 0000000..c5fde41 --- /dev/null +++ b/src/positioning/qnmeapositioninfosource.cpp @@ -0,0 +1,680 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qnmeapositioninfosource_p.h" +#include "qlocationutils_p.h" + +#include +#include +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +QNmeaRealTimeReader::QNmeaRealTimeReader(QNmeaPositionInfoSourcePrivate *sourcePrivate) + : QNmeaReader(sourcePrivate) +{ +} + +void QNmeaRealTimeReader::readAvailableData() +{ + while (m_proxy->m_device->canReadLine()){ + QGeoPositionInfo update; + bool hasFix = false; + + char buf[1024]; + qint64 size = m_proxy->m_device->readLine(buf, sizeof(buf)); + if (m_proxy->parsePosInfoFromNmeaData(buf, size, &update, &hasFix)) + m_proxy->notifyNewUpdate(&update, hasFix); + } +} + + +//============================================================ + +QNmeaSimulatedReader::QNmeaSimulatedReader(QNmeaPositionInfoSourcePrivate *sourcePrivate) + : QNmeaReader(sourcePrivate), + m_currTimerId(-1), + m_hasValidDateTime(false) +{ +} + +QNmeaSimulatedReader::~QNmeaSimulatedReader() +{ + if (m_currTimerId > 0) + killTimer(m_currTimerId); +} + +void QNmeaSimulatedReader::readAvailableData() +{ + if (m_currTimerId > 0) // we are already reading + return; + + if (!m_hasValidDateTime) { // first update + Q_ASSERT(m_proxy->m_device && (m_proxy->m_device->openMode() & QIODevice::ReadOnly)); + + if (!setFirstDateTime()) { + //m_proxy->notifyReachedEndOfFile(); + qWarning("QNmeaPositionInfoSource: cannot find NMEA sentence with valid date & time"); + return; + } + + m_hasValidDateTime = true; + simulatePendingUpdate(); + + } else { + // previously read to EOF, but now new data has arrived + processNextSentence(); + } +} + +bool QNmeaSimulatedReader::setFirstDateTime() +{ + // find the first update with valid date and time + QGeoPositionInfo update; + bool hasFix = false; + while (m_proxy->m_device->bytesAvailable() > 0) { + char buf[1024]; + qint64 size = m_proxy->m_device->readLine(buf, sizeof(buf)); + if (size <= 0) + continue; + bool ok = m_proxy->parsePosInfoFromNmeaData(buf, size, &update, &hasFix); + if (ok && update.timestamp().isValid()) { + QPendingGeoPositionInfo pending; + pending.info = update; + pending.hasFix = hasFix; + m_pendingUpdates.enqueue(pending); + return true; + } + } + return false; +} + +void QNmeaSimulatedReader::simulatePendingUpdate() +{ + if (m_pendingUpdates.size() > 0) { + // will be dequeued in processNextSentence() + QPendingGeoPositionInfo &pending = m_pendingUpdates.head(); + m_proxy->notifyNewUpdate(&pending.info, pending.hasFix); + } + + processNextSentence(); +} + +void QNmeaSimulatedReader::timerEvent(QTimerEvent *event) +{ + killTimer(event->timerId()); + m_currTimerId = -1; + simulatePendingUpdate(); +} + +void QNmeaSimulatedReader::processNextSentence() +{ + QGeoPositionInfo info; + bool hasFix = false; + int timeToNextUpdate = -1; + QTime prevTime; + if (m_pendingUpdates.size() > 0) + prevTime = m_pendingUpdates.head().info.timestamp().time(); + + // find the next update with a valid time (as long as the time is valid, + // we can calculate when the update should be emitted) + while (m_proxy->m_device && m_proxy->m_device->bytesAvailable() > 0) { + char buf[1024]; + qint64 size = m_proxy->m_device->readLine(buf, sizeof(buf)); + if (size <= 0) + continue; + if (m_proxy->parsePosInfoFromNmeaData(buf, size, &info, &hasFix)) { + QTime time = info.timestamp().time(); + if (time.isValid()) { + if (!prevTime.isValid()) { + timeToNextUpdate = 0; + break; + } + timeToNextUpdate = prevTime.msecsTo(time); + if (timeToNextUpdate >= 0) + break; + } else { + timeToNextUpdate = 0; + break; + } + } + } + + if (timeToNextUpdate < 0) + return; + + m_pendingUpdates.dequeue(); + + QPendingGeoPositionInfo pending; + pending.info = info; + pending.hasFix = hasFix; + m_pendingUpdates.enqueue(pending); + m_currTimerId = startTimer(timeToNextUpdate); +} + + +//============================================================ + + +QNmeaPositionInfoSourcePrivate::QNmeaPositionInfoSourcePrivate(QNmeaPositionInfoSource *parent, QNmeaPositionInfoSource::UpdateMode updateMode) + : QObject(parent), + m_updateMode(updateMode), + m_device(0), + m_invokedStart(false), + m_positionError(QGeoPositionInfoSource::UnknownSourceError), + m_userEquivalentRangeError(qQNaN()), + m_source(parent), + m_nmeaReader(0), + m_updateTimer(0), + m_requestTimer(0), + m_horizontalAccuracy(qQNaN()), + m_verticalAccuracy(qQNaN()), + m_noUpdateLastInterval(false), + m_updateTimeoutSent(false), + m_connectedReadyRead(false) +{ +} + +QNmeaPositionInfoSourcePrivate::~QNmeaPositionInfoSourcePrivate() +{ + delete m_nmeaReader; + delete m_updateTimer; +} + +bool QNmeaPositionInfoSourcePrivate::openSourceDevice() +{ + if (!m_device) { + qWarning("QNmeaPositionInfoSource: no QIODevice data source, call setDevice() first"); + return false; + } + + if (!m_device->isOpen() && !m_device->open(QIODevice::ReadOnly)) { + qWarning("QNmeaPositionInfoSource: cannot open QIODevice data source"); + return false; + } + + connect(m_device, SIGNAL(aboutToClose()), SLOT(sourceDataClosed())); + connect(m_device, SIGNAL(readChannelFinished()), SLOT(sourceDataClosed())); + connect(m_device, SIGNAL(destroyed()), SLOT(sourceDataClosed())); + + return true; +} + +void QNmeaPositionInfoSourcePrivate::sourceDataClosed() +{ + if (m_nmeaReader && m_device && m_device->bytesAvailable()) + m_nmeaReader->readAvailableData(); +} + +void QNmeaPositionInfoSourcePrivate::readyRead() +{ + if (m_nmeaReader) + m_nmeaReader->readAvailableData(); +} + +bool QNmeaPositionInfoSourcePrivate::initialize() +{ + if (m_nmeaReader) + return true; + + if (!openSourceDevice()) + return false; + + if (m_updateMode == QNmeaPositionInfoSource::RealTimeMode) + m_nmeaReader = new QNmeaRealTimeReader(this); + else + m_nmeaReader = new QNmeaSimulatedReader(this); + + return true; +} + +void QNmeaPositionInfoSourcePrivate::prepareSourceDevice() +{ + // some data may already be available + if (m_updateMode == QNmeaPositionInfoSource::SimulationMode) { + if (m_nmeaReader && m_device->bytesAvailable()) + m_nmeaReader->readAvailableData(); + } + + if (!m_connectedReadyRead) { + connect(m_device, SIGNAL(readyRead()), SLOT(readyRead())); + m_connectedReadyRead = true; + } +} + +bool QNmeaPositionInfoSourcePrivate::parsePosInfoFromNmeaData(const char *data, int size, + QGeoPositionInfo *posInfo, bool *hasFix) +{ + return m_source->parsePosInfoFromNmeaData(data, size, posInfo, hasFix); +} + +void QNmeaPositionInfoSourcePrivate::startUpdates() +{ + if (m_invokedStart) + return; + + m_invokedStart = true; + m_pendingUpdate = QGeoPositionInfo(); + m_noUpdateLastInterval = false; + + bool initialized = initialize(); + if (!initialized) + return; + + if (m_updateMode == QNmeaPositionInfoSource::RealTimeMode) { + // skip over any buffered data - we only want the newest data + if (m_device->bytesAvailable()) { + if (m_device->isSequential()) + m_device->readAll(); + else + m_device->seek(m_device->bytesAvailable()); + } + } + + if (m_updateTimer) + m_updateTimer->stop(); + + if (m_source->updateInterval() > 0) { + if (!m_updateTimer) + m_updateTimer = new QBasicTimer; + m_updateTimer->start(m_source->updateInterval(), this); + } + + if (initialized) + prepareSourceDevice(); +} + +void QNmeaPositionInfoSourcePrivate::stopUpdates() +{ + m_invokedStart = false; + if (m_updateTimer) + m_updateTimer->stop(); + m_pendingUpdate = QGeoPositionInfo(); + m_noUpdateLastInterval = false; +} + +void QNmeaPositionInfoSourcePrivate::requestUpdate(int msec) +{ + if (m_requestTimer && m_requestTimer->isActive()) + return; + + if (msec <= 0 || msec < m_source->minimumUpdateInterval()) { + emit m_source->updateTimeout(); + return; + } + + if (!m_requestTimer) { + m_requestTimer = new QTimer(this); + connect(m_requestTimer, SIGNAL(timeout()), SLOT(updateRequestTimeout())); + } + + bool initialized = initialize(); + if (!initialized) { + emit m_source->updateTimeout(); + return; + } + + m_requestTimer->start(msec); + + if (initialized) + prepareSourceDevice(); +} + +void QNmeaPositionInfoSourcePrivate::updateRequestTimeout() +{ + m_requestTimer->stop(); + emit m_source->updateTimeout(); +} + +void QNmeaPositionInfoSourcePrivate::notifyNewUpdate(QGeoPositionInfo *update, bool hasFix) +{ + // include before uncommenting + //qDebug() << "QNmeaPositionInfoSourcePrivate::notifyNewUpdate()" << update->timestamp() << hasFix << m_invokedStart << (m_requestTimer && m_requestTimer->isActive()); + + QDate date = update->timestamp().date(); + if (date.isValid()) { + m_currentDate = date; + } else { + // some sentence have time but no date + QTime time = update->timestamp().time(); + if (time.isValid() && m_currentDate.isValid()) + update->setTimestamp(QDateTime(m_currentDate, time, Qt::UTC)); + } + + // Some attributes are sent in separate NMEA sentences. Save and restore the accuracy + // measurements. + if (update->hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + m_horizontalAccuracy = update->attribute(QGeoPositionInfo::HorizontalAccuracy); + else if (!qIsNaN(m_horizontalAccuracy)) + update->setAttribute(QGeoPositionInfo::HorizontalAccuracy, m_horizontalAccuracy); + if (update->hasAttribute(QGeoPositionInfo::VerticalAccuracy)) + m_verticalAccuracy = update->attribute(QGeoPositionInfo::VerticalAccuracy); + else if (!qIsNaN(m_verticalAccuracy)) + update->setAttribute(QGeoPositionInfo::VerticalAccuracy, m_verticalAccuracy); + + if (hasFix && update->isValid()) { + if (m_requestTimer && m_requestTimer->isActive()) { + m_requestTimer->stop(); + emitUpdated(*update); + } else if (m_invokedStart) { + if (m_updateTimer && m_updateTimer->isActive()) { + // for periodic updates, only want the most recent update + m_pendingUpdate = *update; + if (m_noUpdateLastInterval) { + emitPendingUpdate(); + m_noUpdateLastInterval = false; + } + } else { + emitUpdated(*update); + } + } + m_lastUpdate = *update; + } +} + +void QNmeaPositionInfoSourcePrivate::timerEvent(QTimerEvent *) +{ + emitPendingUpdate(); +} + +void QNmeaPositionInfoSourcePrivate::emitPendingUpdate() +{ + if (m_pendingUpdate.isValid()) { + m_updateTimeoutSent = false; + m_noUpdateLastInterval = false; + emitUpdated(m_pendingUpdate); + m_pendingUpdate = QGeoPositionInfo(); + } else { + if (m_noUpdateLastInterval && !m_updateTimeoutSent) { + m_updateTimeoutSent = true; + m_pendingUpdate = QGeoPositionInfo(); + emit m_source->updateTimeout(); + } + m_noUpdateLastInterval = true; + } +} + +void QNmeaPositionInfoSourcePrivate::emitUpdated(const QGeoPositionInfo &update) +{ + m_lastUpdate = update; + emit m_source->positionUpdated(update); +} + +//========================================================= + +/*! + \class QNmeaPositionInfoSource + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.2 + + \brief The QNmeaPositionInfoSource class provides positional information using a NMEA data source. + + NMEA is a commonly used protocol for the specification of one's global + position at a certain point in time. The QNmeaPositionInfoSource class reads NMEA + data and uses it to provide positional data in the form of + QGeoPositionInfo objects. + + A QNmeaPositionInfoSource instance operates in either \l {RealTimeMode} or + \l {SimulationMode}. These modes allow NMEA data to be read from either a + live source of positional data, or replayed for simulation purposes from + previously recorded NMEA data. + + The source of NMEA data is set with setDevice(). + + Use startUpdates() to start receiving regular position updates and stopUpdates() to stop these + updates. If you only require updates occasionally, you can call requestUpdate() to request a + single update. + + In both cases the position information is received via the positionUpdated() signal and the + last known position can be accessed with lastKnownPosition(). + + QNmeaPositionInfoSource supports reporting the accuracy of the horizontal and vertical position. + To enable position accuracy reporting an estimate of the User Equivalent Range Error associated + with the NMEA source must be set with setUserEquivalentRangeError(). +*/ + + +/*! + \enum QNmeaPositionInfoSource::UpdateMode + Defines the available update modes. + + \value RealTimeMode Positional data is read and distributed from the data source as it becomes available. Use this mode if you are using a live source of positional data (for example, a GPS hardware device). + \value SimulationMode The data and time information in the NMEA source data is used to provide positional updates at the rate at which the data was originally recorded. Use this mode if the data source contains previously recorded NMEA data and you want to replay the data for simulation purposes. +*/ + + +/*! + Constructs a QNmeaPositionInfoSource instance with the given \a parent + and \a updateMode. +*/ +QNmeaPositionInfoSource::QNmeaPositionInfoSource(UpdateMode updateMode, QObject *parent) + : QGeoPositionInfoSource(parent), + d(new QNmeaPositionInfoSourcePrivate(this, updateMode)) +{ +} + +/*! + Destroys the position source. +*/ +QNmeaPositionInfoSource::~QNmeaPositionInfoSource() +{ + delete d; +} + +/*! + Sets the User Equivalent Range Error (UERE) to \a uere. The UERE is used in calculating an + estimate of the accuracy of the position information reported by the position info source. The + UERE should be set to a value appropriate for the GPS device which generated the NMEA stream. + + The true UERE value is calculated from multiple error sources including errors introduced by + the satellites and signal propogation delays through the atmosphere as well as errors + introduced by the receiving GPS equipment. For details on GPS accuracy see + \l {http://edu-observatory.org/gps/gps_accuracy.html}. + + A typical value for UERE is approximately 5.1. + + \since 5.3 + + \sa userEquivalentRangeError() +*/ +void QNmeaPositionInfoSource::setUserEquivalentRangeError(double uere) +{ + d->m_userEquivalentRangeError = uere; +} + +/*! + Returns the current User Equivalent Range Error (UERE). The UERE is used in calculating an + estimate of the accuracy of the position information reported by the position info source. The + default value is NaN which means no accuracy information will be provided. + + \since 5.3 + + \sa setUserEquivalentRangeError() +*/ +double QNmeaPositionInfoSource::userEquivalentRangeError() const +{ + return d->m_userEquivalentRangeError; +} + +/*! + Parses an NMEA sentence string into a QGeoPositionInfo. + + The default implementation will parse standard NMEA sentences. + This method should be reimplemented in a subclass whenever the need to deal with non-standard + NMEA sentences arises. + + The parser reads \a size bytes from \a data and uses that information to setup \a posInfo and + \a hasFix. If \a hasFix is set to false then \a posInfo may contain only the time or the date + and the time. + + Returns true if the sentence was succsesfully parsed, otherwise returns false and should not + modifiy \a posInfo or \a hasFix. +*/ +bool QNmeaPositionInfoSource::parsePosInfoFromNmeaData(const char *data, int size, + QGeoPositionInfo *posInfo, bool *hasFix) +{ + return QLocationUtils::getPosInfoFromNmea(data, size, posInfo, d->m_userEquivalentRangeError, + hasFix); +} + +/*! + Returns the update mode. +*/ +QNmeaPositionInfoSource::UpdateMode QNmeaPositionInfoSource::updateMode() const +{ + return d->m_updateMode; +} + +/*! + Sets the NMEA data source to \a device. If the device is not open, it + will be opened in QIODevice::ReadOnly mode. + + The source device can only be set once and must be set before calling + startUpdates() or requestUpdate(). + + \b {Note:} The \a device must emit QIODevice::readyRead() for the + source to be notified when data is available for reading. + QNmeaPositionInfoSource does not assume the ownership of the device, + and hence does not deallocate it upon destruction. +*/ +void QNmeaPositionInfoSource::setDevice(QIODevice *device) +{ + if (device != d->m_device) { + if (!d->m_device) + d->m_device = device; + else + qWarning("QNmeaPositionInfoSource: source device has already been set"); + } +} + +/*! + Returns the NMEA data source. +*/ +QIODevice *QNmeaPositionInfoSource::device() const +{ + return d->m_device; +} + +/*! + \reimp +*/ +void QNmeaPositionInfoSource::setUpdateInterval(int msec) +{ + int interval = msec; + if (interval != 0) + interval = qMax(msec, minimumUpdateInterval()); + QGeoPositionInfoSource::setUpdateInterval(interval); + if (d->m_invokedStart) { + d->stopUpdates(); + d->startUpdates(); + } +} + +/*! + \reimp +*/ +void QNmeaPositionInfoSource::startUpdates() +{ + d->startUpdates(); +} + +/*! + \reimp +*/ +void QNmeaPositionInfoSource::stopUpdates() +{ + d->stopUpdates(); +} + +/*! + \reimp +*/ +void QNmeaPositionInfoSource::requestUpdate(int msec) +{ + d->requestUpdate(msec == 0 ? 60000 * 5 : msec); +} + +/*! + \reimp +*/ +QGeoPositionInfo QNmeaPositionInfoSource::lastKnownPosition(bool) const +{ + // the bool value does not matter since we only use satellite positioning + return d->m_lastUpdate; +} + +/*! + \reimp +*/ +QGeoPositionInfoSource::PositioningMethods QNmeaPositionInfoSource::supportedPositioningMethods() const +{ + return SatellitePositioningMethods; +} + +/*! + \reimp +*/ +int QNmeaPositionInfoSource::minimumUpdateInterval() const +{ + return 100; +} + +/*! + \reimp +*/ +QGeoPositionInfoSource::Error QNmeaPositionInfoSource::error() const +{ + return d->m_positionError; +} + +void QNmeaPositionInfoSource::setError(QGeoPositionInfoSource::Error positionError) +{ + d->m_positionError = positionError; + emit QGeoPositionInfoSource::error(positionError); +} + +#include "moc_qnmeapositioninfosource.cpp" +#include "moc_qnmeapositioninfosource_p.cpp" + +QT_END_NAMESPACE diff --git a/src/positioning/qnmeapositioninfosource.h b/src/positioning/qnmeapositioninfosource.h new file mode 100644 index 0000000..d951f57 --- /dev/null +++ b/src/positioning/qnmeapositioninfosource.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QNMEAPOSITIONINFOSOURCE_H +#define QNMEAPOSITIONINFOSOURCE_H + +#include + +QT_BEGIN_NAMESPACE + +class QIODevice; + +class QNmeaPositionInfoSourcePrivate; +class Q_POSITIONING_EXPORT QNmeaPositionInfoSource : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + enum UpdateMode { + RealTimeMode = 1, + SimulationMode + }; + + explicit QNmeaPositionInfoSource(UpdateMode updateMode, QObject *parent = Q_NULLPTR); + ~QNmeaPositionInfoSource(); + + void setUserEquivalentRangeError(double uere); + double userEquivalentRangeError() const; + + UpdateMode updateMode() const; + + void setDevice(QIODevice *source); + QIODevice *device() const; + + void setUpdateInterval(int msec); + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + PositioningMethods supportedPositioningMethods() const; + int minimumUpdateInterval() const; + Error error() const; + + +public Q_SLOTS: + void startUpdates(); + void stopUpdates(); + void requestUpdate(int timeout = 0); + +protected: + virtual bool parsePosInfoFromNmeaData(const char *data, + int size, + QGeoPositionInfo *posInfo, + bool *hasFix); + +private: + Q_DISABLE_COPY(QNmeaPositionInfoSource) + friend class QNmeaPositionInfoSourcePrivate; + QNmeaPositionInfoSourcePrivate *d; + void setError(QGeoPositionInfoSource::Error positionError); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qnmeapositioninfosource_p.h b/src/positioning/qnmeapositioninfosource_p.h new file mode 100644 index 0000000..056de90 --- /dev/null +++ b/src/positioning/qnmeapositioninfosource_p.h @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QNMEAPOSITIONINFOSOURCE_P_H +#define QNMEAPOSITIONINFOSOURCE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qnmeapositioninfosource.h" +#include "qgeopositioninfo.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QBasicTimer; +class QTimerEvent; +class QTimer; + +class QNmeaReader; +struct QPendingGeoPositionInfo +{ + QGeoPositionInfo info; + bool hasFix; +}; + + +class QNmeaPositionInfoSourcePrivate : public QObject +{ + Q_OBJECT +public: + QNmeaPositionInfoSourcePrivate(QNmeaPositionInfoSource *parent, QNmeaPositionInfoSource::UpdateMode updateMode); + ~QNmeaPositionInfoSourcePrivate(); + + void startUpdates(); + void stopUpdates(); + void requestUpdate(int msec); + + bool parsePosInfoFromNmeaData(const char *data, + int size, + QGeoPositionInfo *posInfo, + bool *hasFix); + + void notifyNewUpdate(QGeoPositionInfo *update, bool fixStatus); + + QNmeaPositionInfoSource::UpdateMode m_updateMode; + QPointer m_device; + QGeoPositionInfo m_lastUpdate; + bool m_invokedStart; + QGeoPositionInfoSource::Error m_positionError; + double m_userEquivalentRangeError; + +public Q_SLOTS: + void readyRead(); + +protected: + void timerEvent(QTimerEvent *event); + +private Q_SLOTS: + void emitPendingUpdate(); + void sourceDataClosed(); + void updateRequestTimeout(); + +private: + bool openSourceDevice(); + bool initialize(); + void prepareSourceDevice(); + void emitUpdated(const QGeoPositionInfo &update); + + QNmeaPositionInfoSource *m_source; + QNmeaReader *m_nmeaReader; + QBasicTimer *m_updateTimer; + QGeoPositionInfo m_pendingUpdate; + QDate m_currentDate; + QTimer *m_requestTimer; + qreal m_horizontalAccuracy; + qreal m_verticalAccuracy; + bool m_noUpdateLastInterval; + bool m_updateTimeoutSent; + bool m_connectedReadyRead; +}; + + +class QNmeaReader +{ +public: + explicit QNmeaReader(QNmeaPositionInfoSourcePrivate *sourcePrivate) + : m_proxy(sourcePrivate) {} + virtual ~QNmeaReader() {} + + virtual void readAvailableData() = 0; + +protected: + QNmeaPositionInfoSourcePrivate *m_proxy; +}; + + +class QNmeaRealTimeReader : public QNmeaReader +{ +public: + explicit QNmeaRealTimeReader(QNmeaPositionInfoSourcePrivate *sourcePrivate); + virtual void readAvailableData(); +}; + + +class QNmeaSimulatedReader : public QObject, public QNmeaReader +{ + Q_OBJECT +public: + explicit QNmeaSimulatedReader(QNmeaPositionInfoSourcePrivate *sourcePrivate); + ~QNmeaSimulatedReader(); + virtual void readAvailableData(); + +protected: + virtual void timerEvent(QTimerEvent *event); + +private Q_SLOTS: + void simulatePendingUpdate(); + +private: + bool setFirstDateTime(); + void processNextSentence(); + + QQueue m_pendingUpdates; + int m_currTimerId; + bool m_hasValidDateTime; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/positioning/qpositioningglobal.h b/src/positioning/qpositioningglobal.h new file mode 100644 index 0000000..ea4de29 --- /dev/null +++ b/src/positioning/qpositioningglobal.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QPOSITIONINGGLOBAL_H +#define QPOSITIONINGGLOBAL_H + +#include + +QT_BEGIN_NAMESPACE + +#ifndef QT_STATIC +# if defined(QT_BUILD_POSITIONING_LIB) +# define Q_POSITIONING_EXPORT Q_DECL_EXPORT +# else +# define Q_POSITIONING_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_POSITIONING_EXPORT +#endif + + +QT_END_NAMESPACE + +#endif // QPOSITIONINGGLOBAL_H + diff --git a/src/positioning/qpositioningglobal_p.h b/src/positioning/qpositioningglobal_p.h new file mode 100644 index 0000000..747e450 --- /dev/null +++ b/src/positioning/qpositioningglobal_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QPOSITIONINGGLOBAL_P_H +#define QPOSITIONINGGLOBAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qpositioningglobal.h" + +QT_BEGIN_NAMESPACE + +#define Q_POSITIONING_PRIVATE_EXPORT Q_POSITIONING_EXPORT + +QT_END_NAMESPACE + +#endif // QPOSITIONINGGLOBAL_P_H + diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..4b9c498 --- /dev/null +++ b/src/src.pro @@ -0,0 +1,33 @@ +TEMPLATE = subdirs + +SUBDIRS += positioning +plugins.depends += positioning + +qtHaveModule(quick) { + SUBDIRS += 3rdparty + + SUBDIRS += location + location.depends += positioning 3rdparty + plugins.depends += location + + SUBDIRS += imports + imports.depends += positioning location +} + +SUBDIRS += plugins + +!android:contains(QT_CONFIG, private_tests) { + SUBDIRS += positioning_doc_snippets + positioning_doc_snippets.subdir = positioning/doc/snippets + + #plugin dependency required during static builds + positioning_doc_snippets.depends = positioning plugins + + qtHaveModule(quick) { + SUBDIRS += location_doc_snippets + location_doc_snippets.subdir = location/doc/snippets + + #plugin dependency required during static builds + location_doc_snippets.depends = location plugins + } +} diff --git a/sync.profile b/sync.profile new file mode 100644 index 0000000..fa9885a --- /dev/null +++ b/sync.profile @@ -0,0 +1,20 @@ +%modules = ( # path to module name map + "QtLocation" => "$basedir/src/location", + "QtPositioning" => "$basedir/src/positioning", +); +%moduleheaders = ( # restrict the module headers to those found in relative path +); +# Module dependencies. +# Every module that is required to build this module should have one entry. +# Each of the module version specifiers can take one of the following values: +# - A specific Git revision. +# - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch) +# - an empty string to use the same branch under test (dependencies will become "refs/heads/master" if we are in the master branch) +# +%dependencies = ( + "qtbase" => "", + "qtxmlpatterns" => "", + "qtdeclarative" => "", + "qtquickcontrols" => "", + "qtserialport" => "", +); diff --git a/tests/applications/positioning_backend/main.cpp b/tests/applications/positioning_backend/main.cpp new file mode 100644 index 0000000..930f1c9 --- /dev/null +++ b/tests/applications/positioning_backend/main.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "widget.h" +#include + +#include +#include +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + Widget *w1 = new Widget; + Widget *w2 = new Widget; + + QTabWidget tabWidget; + tabWidget.setTabPosition(QTabWidget::South); + + tabWidget.addTab(w1, "Instance 1"); + tabWidget.addTab(w2, "Instance 2"); + + tabWidget.show(); + return a.exec(); +} diff --git a/tests/applications/positioning_backend/positioning_backend.pro b/tests/applications/positioning_backend/positioning_backend.pro new file mode 100644 index 0000000..410dbc8 --- /dev/null +++ b/tests/applications/positioning_backend/positioning_backend.pro @@ -0,0 +1,14 @@ +QT += core gui positioning widgets + +TARGET = posbackendtesting +TEMPLATE = app + + +SOURCES += main.cpp\ + widget.cpp + +HEADERS += widget.h + +FORMS += widget.ui + +winrt: WINRT_MANIFEST.capabilities_device += location diff --git a/tests/applications/positioning_backend/widget.cpp b/tests/applications/positioning_backend/widget.cpp new file mode 100644 index 0000000..ecf9b7e --- /dev/null +++ b/tests/applications/positioning_backend/widget.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "widget.h" +#include "ui_widget.h" +#include +#include + +Widget::Widget(QWidget *parent) : + QWidget(parent), + ui(new Ui::Widget) +{ + ui->setupUi(this); + qDebug() << "Available:" << QGeoPositionInfoSource::availableSources(); + m_posSource = QGeoPositionInfoSource::createDefaultSource(this); + if (!m_posSource) + qFatal("No Position Source created!"); + connect(m_posSource, SIGNAL(positionUpdated(QGeoPositionInfo)), + this, SLOT(positionUpdated(QGeoPositionInfo))); + + connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), + this, SLOT(setInterval(int))); + connect(m_posSource, SIGNAL(updateTimeout()), + this, SLOT(positionTimedOut())); + + ui->groupBox->setLayout(ui->gridLayout); + ui->horizontalSlider->setMinimum(m_posSource->minimumUpdateInterval()); + ui->labelTimeOut->setVisible(false); + + connect(m_posSource, SIGNAL(error(QGeoPositionInfoSource::Error)), + this, SLOT(errorChanged(QGeoPositionInfoSource::Error))); +} + +void Widget::positionUpdated(QGeoPositionInfo gpsPos) +{ + QGeoCoordinate coord = gpsPos.coordinate(); + ui->labelLatitude->setText(QString::number(coord.latitude())); + ui->labelLongitude->setText(QString::number(coord.longitude())); + ui->labelAltitude->setText(QString::number(coord.altitude())); + ui->labelTimeStamp->setText(gpsPos.timestamp().toString()); + if (gpsPos.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + ui->labelHAccuracy->setText(QString::number(gpsPos.attribute(QGeoPositionInfo::HorizontalAccuracy))); + else + ui->labelHAccuracy->setText(QStringLiteral("N/A")); + + if (gpsPos.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) + ui->labelVAccuracy->setText(QString::number(gpsPos.attribute(QGeoPositionInfo::VerticalAccuracy))); + else + ui->labelVAccuracy->setText(QStringLiteral("N/A")); +} + +void Widget::positionTimedOut() +{ + ui->labelTimeOut->setVisible(true); +} + +void Widget::errorChanged(QGeoPositionInfoSource::Error err) +{ + ui->labelErrorState->setText(err == 3 ? QStringLiteral("OK") : QString::number(err)); +} + +Widget::~Widget() +{ + delete ui; +} + +void Widget::setInterval(int msec) +{ + m_posSource->setUpdateInterval(msec); +} + +void Widget::on_buttonRetrieve_clicked() +{ + // Requesting current position for _one_ time + m_posSource->requestUpdate(10000); +} + +void Widget::on_buttonStart_clicked() +{ + // Either start or stop the current position info source + bool running = ui->checkBox->isChecked(); + if (running) { + m_posSource->stopUpdates(); + ui->checkBox->setChecked(false); + } else { + m_posSource->startUpdates(); + ui->checkBox->setChecked(true); + } +} + +void Widget::on_radioButton_clicked() +{ + m_posSource->setPreferredPositioningMethods(QGeoPositionInfoSource::NoPositioningMethods); +} + +void Widget::on_radioButton_2_clicked() +{ + m_posSource->setPreferredPositioningMethods(QGeoPositionInfoSource::SatellitePositioningMethods); +} + +void Widget::on_radioButton_3_clicked() +{ + m_posSource->setPreferredPositioningMethods(QGeoPositionInfoSource::NonSatellitePositioningMethods); +} + +void Widget::on_radioButton_4_clicked() +{ + m_posSource->setPreferredPositioningMethods(QGeoPositionInfoSource::AllPositioningMethods); +} + +void Widget::on_buttonUpdateSupported_clicked() +{ + QGeoPositionInfoSource::PositioningMethods m = m_posSource->supportedPositioningMethods(); + QString text; + switch (m) { + case QGeoPositionInfoSource::NoPositioningMethods: + text = QStringLiteral("None"); + break; + case QGeoPositionInfoSource::SatellitePositioningMethods: + text = QStringLiteral("Satellite"); + break; + case QGeoPositionInfoSource::NonSatellitePositioningMethods: + text = QStringLiteral("Non Satellite"); + break; + case QGeoPositionInfoSource::AllPositioningMethods: + text = QStringLiteral("All"); + break; + } + + ui->labelSupported->setText(text); +} diff --git a/tests/applications/positioning_backend/widget.h b/tests/applications/positioning_backend/widget.h new file mode 100644 index 0000000..fc04c42 --- /dev/null +++ b/tests/applications/positioning_backend/widget.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef WIDGET_H +#define WIDGET_H + +#include +#include + +namespace Ui { + class Widget; +} + +class Widget : public QWidget +{ + Q_OBJECT + +public: + explicit Widget(QWidget *parent = 0); + ~Widget(); + +public slots: + void positionUpdated(QGeoPositionInfo gpsPos); + void setInterval(int msec); + void positionTimedOut(); + void errorChanged(QGeoPositionInfoSource::Error err); +private slots: + void on_buttonRetrieve_clicked(); + void on_buttonStart_clicked(); + void on_radioButton_2_clicked(); + void on_radioButton_clicked(); + void on_radioButton_3_clicked(); + void on_radioButton_4_clicked(); + + void on_buttonUpdateSupported_clicked(); + +private: + Ui::Widget *ui; + QGeoPositionInfoSource *m_posSource; +}; + +#endif // WIDGET_H diff --git a/tests/applications/positioning_backend/widget.ui b/tests/applications/positioning_backend/widget.ui new file mode 100644 index 0000000..d19497d --- /dev/null +++ b/tests/applications/positioning_backend/widget.ui @@ -0,0 +1,295 @@ + + + Widget + + + + 0 + 0 + 276 + 467 + + + + Widget + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Latitude: + + + + + + + N/A + + + + + + + Longitude: + + + + + + + N/A + + + + + + + Altitude: + + + + + + + N/A + + + + + + + TimeStamp: + + + + + + + N/A + + + + + + + Horizontal Accuracy: + + + + + + + N/A + + + + + + + Vertical Accuracy: + + + + + + + N/A + + + + + + + TimeOut: + + + + + + + true + + + !!!!!TimeOut!!!!! + + + + + + + Supported Methods: + + + + + + + Error State: + + + + + + + N/A + + + + + + + + + N/A + + + + + + + Update + + + + + + + + + + + Method + + + + + 43 + 21 + 243 + 71 + + + + + + + None + + + + + + + Satelite + + + true + + + + + + + Non-Satelite + + + + + + + All + + + + + + + + + + + + + Interval: + + + + + + + 50 + + + 10000 + + + Qt::Horizontal + + + + + + + 0 + + + + + + + + + false + + + Running + + + + + + + + + Start/Stop + + + + + + + Retrieve + + + + + + + + + + + + horizontalSlider + valueChanged(int) + labelInterval + setNum(int) + + + 217 + 137 + + + 386 + 138 + + + + + diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro new file mode 100644 index 0000000..e3236de --- /dev/null +++ b/tests/auto/auto.pro @@ -0,0 +1,83 @@ +TEMPLATE = subdirs + +qtHaveModule(location) { + + #Place unit tests + SUBDIRS += qplace \ + qplaceattribute \ + qplacecategory \ + qplacecontactdetail \ + qplacecontentrequest \ + qplacedetailsreply \ + qplaceeditorial \ + qplacematchreply \ + qplacematchrequest \ + qplaceimage \ + qplaceratings \ + qplaceresult \ + qproposedsearchresult \ + qplacereply \ + qplacereview \ + qplacesearchrequest \ + qplacesupplier \ + qplacesearchresult \ + qplacesearchreply \ + qplacesearchsuggestionreply \ + qplaceuser \ + qplacemanager \ + qplacemanager_nokia \ + qplacemanager_unsupported \ + placesplugin_unsupported + + #misc tests + SUBDIRS += qmlinterface \ + cmake \ + doublevectors + + #Map and Navigation tests + SUBDIRS += geotestplugin \ + qgeocodingmanagerplugins \ + qgeocameracapabilities\ + qgeocameradata \ + qgeocodereply \ + qgeocodingmanager \ + qgeomaneuver \ + qgeotiledmapscene \ + qgeoroute \ + qgeoroutereply \ + qgeorouterequest \ + qgeoroutesegment \ + qgeoroutingmanager \ + qgeoroutingmanagerplugins \ + qgeoserviceprovider \ + qgeotiledmap \ + qgeotilespec \ + qgeoroutexmlparser \ + maptype \ + nokia_services \ + qgeocameratiles + + qtHaveModule(quick) { + SUBDIRS += declarative_core \ + declarative_geoshape + + !mac: SUBDIRS += declarative_ui + } +} + + +SUBDIRS += \ + positionplugin \ + positionplugintest \ + qgeoaddress \ + qgeoareamonitor \ + qgeoshape \ + qgeorectangle \ + qgeocircle \ + qgeocoordinate \ + qgeolocation \ + qgeopositioninfo \ + qgeopositioninfosource \ + qgeosatelliteinfo \ + qgeosatelliteinfosource \ + qnmeapositioninfosource diff --git a/tests/auto/bic/data/QtPositioning.5.3.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtPositioning.5.3.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..d29c24a --- /dev/null +++ b/tests/auto/bic/data/QtPositioning.5.3.0.linux-gcc-amd64.txt @@ -0,0 +1,3822 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f95f2df8f00) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f95f2df8f60) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f95f1d8fb40) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f95f1d8fba0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f95f1d26820) 0 empty + std::input_iterator_tag (0x0x7f95f1d8fc00) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f95f1d26888) 0 empty + std::forward_iterator_tag (0x0x7f95f1d268f0) 0 empty + std::input_iterator_tag (0x0x7f95f1d8fc60) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f95f1d26958) 0 empty + std::bidirectional_iterator_tag (0x0x7f95f1d269c0) 0 empty + std::forward_iterator_tag (0x0x7f95f1d26a28) 0 empty + std::input_iterator_tag (0x0x7f95f1d8fcc0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f95f1de9840) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f95f1de9a80) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f95f1de9b40) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f95f1de9ba0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f95f1de9c60) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f95f1de9cc0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f95f1eab180) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f95f1eab1e0) 0 + +Vtable for std::exception +std::exception::_ZTVSt9exception: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt9exception) +16 (int (*)(...))std::exception::~exception +24 (int (*)(...))std::exception::~exception +32 (int (*)(...))std::exception::what + +Class std::exception + size=8 align=8 + base size=8 base align=8 +std::exception (0x0x7f95f1eab240) 0 nearly-empty + vptr=((& std::exception::_ZTVSt9exception) + 16u) + +Vtable for std::bad_exception +std::bad_exception::_ZTVSt13bad_exception: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt13bad_exception) +16 (int (*)(...))std::bad_exception::~bad_exception +24 (int (*)(...))std::bad_exception::~bad_exception +32 (int (*)(...))std::bad_exception::what + +Class std::bad_exception + size=8 align=8 + base size=8 base align=8 +std::bad_exception (0x0x7f95f1d26d68) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f95f1eab2a0) 0 nearly-empty + primary-for std::bad_exception (0x0x7f95f1d26d68) + +Vtable for std::bad_alloc +std::bad_alloc::_ZTVSt9bad_alloc: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt9bad_alloc) +16 (int (*)(...))std::bad_alloc::~bad_alloc +24 (int (*)(...))std::bad_alloc::~bad_alloc +32 (int (*)(...))std::bad_alloc::what + +Class std::bad_alloc + size=8 align=8 + base size=8 base align=8 +std::bad_alloc (0x0x7f95f1d26dd0) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f95f1eab300) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f95f1d26dd0) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f95f1eab360) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f95f0cb36c0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f95f0cb3720) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7f95f0cb3900) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f95f0a18060) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f95f0a180c0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f95f0a18120) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f95f0a18180) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f95f0a182a0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f95f06ee3a8) 0 + QAtomicInteger (0x0x7f95f06ee410) 0 + QBasicAtomicInteger (0x0x7f95f0a18d80) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f95f04f5ea0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f95f069fde0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f95f05ca548) 0 + QGenericArgument (0x0x7f95f069fe40) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f95f0304000) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f95f0304120) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f95f0304360) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f95f03043c0) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f95f03044e0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f95f0304540) 0 + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7f95f03048a0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f95f0304900) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f95f0304a80) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f95f0304ea0) 0 + +Vtable for __cxxabiv1::__forced_unwind +__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE) +16 (int (*)(...))__cxxabiv1::__forced_unwind::~__forced_unwind +24 (int (*)(...))__cxxabiv1::__forced_unwind::~__forced_unwind +32 (int (*)(...))__cxa_pure_virtual + +Class __cxxabiv1::__forced_unwind + size=8 align=8 + base size=8 base align=8 +__cxxabiv1::__forced_unwind (0x0x7f95f0304f00) 0 nearly-empty + vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16u) + +Class sched_param + size=4 align=4 + base size=4 base align=4 +sched_param (0x0x7f95f02039c0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f95f0203a20) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f95f0203ae0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f95f0203b40) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f95f0203ba0) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f95f0203c00) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f95f0203d20) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f95f0203d80) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f95eff0a4e0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f95eff0a660) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f95eff0a720) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f95eff0a6c0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f95eff0a8a0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f95eff0ab40) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f95eff0ad20) 0 + +Vtable for std::locale::facet +std::locale::facet::_ZTVNSt6locale5facetE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6locale5facetE) +16 (int (*)(...))std::locale::facet::~facet +24 (int (*)(...))std::locale::facet::~facet + +Class std::locale::facet + size=16 align=8 + base size=12 base align=8 +std::locale::facet (0x0x7f95eff0ad80) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f95eff0ade0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f95eff0ae40) 0 + +Vtable for std::ios_base::failure +std::ios_base::failure::_ZTVNSt8ios_base7failureE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt8ios_base7failureE) +16 (int (*)(...))std::ios_base::failure::~failure +24 (int (*)(...))std::ios_base::failure::~failure +32 (int (*)(...))std::ios_base::failure::what + +Class std::ios_base::failure + size=16 align=8 + base size=16 base align=8 +std::ios_base::failure (0x0x7f95eff0e000) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureE) + 16u) + std::exception (0x0x7f95efbc92a0) 0 nearly-empty + primary-for std::ios_base::failure (0x0x7f95eff0e000) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f95efbc9300) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f95efbc9360) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f95efbc93c0) 0 empty + +Vtable for std::ios_base +std::ios_base::_ZTVSt8ios_base: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt8ios_base) +16 (int (*)(...))std::ios_base::~ios_base +24 (int (*)(...))std::ios_base::~ios_base + +Class std::ios_base + size=216 align=8 + base size=216 base align=8 +std::ios_base (0x0x7f95efbc9240) 0 + vptr=((& std::ios_base::_ZTVSt8ios_base) + 16u) + +Class std::ctype_base + size=1 align=1 + base size=0 base align=1 +std::ctype_base (0x0x7f95efbc9540) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f95efbc9c00) 0 empty + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSo: 2u entries +0 ((& std::basic_ostream::_ZTVSo) + 24u) +8 ((& std::basic_ostream::_ZTVSo) + 64u) + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2u entries +0 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64u) + +VTT for std::basic_istream +std::basic_istream::_ZTTSi: 2u entries +0 ((& std::basic_istream::_ZTVSi) + 24u) +8 ((& std::basic_istream::_ZTVSi) + 64u) + +VTT for std::basic_istream +std::basic_istream::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2u entries +0 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64u) + +Construction vtable for std::basic_istream (0x0x7f95ef810a90 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd0_Si: 10u entries +0 24u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISi) +24 (int (*)(...))std::basic_istream<_CharT, _Traits>::~basic_istream > +32 (int (*)(...))std::basic_istream<_CharT, _Traits>::~basic_istream > +40 18446744073709551592u +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISi) +64 (int (*)(...))std::basic_istream::_ZTv0_n24_NSiD1Ev +72 (int (*)(...))std::basic_istream::_ZTv0_n24_NSiD0Ev + +Construction vtable for std::basic_ostream (0x0x7f95ef810b60 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd16_So: 10u entries +0 8u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISo) +24 (int (*)(...))std::basic_ostream<_CharT, _Traits>::~basic_ostream > +32 (int (*)(...))std::basic_ostream<_CharT, _Traits>::~basic_ostream > +40 18446744073709551608u +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISo) +64 (int (*)(...))std::basic_ostream::_ZTv0_n24_NSoD1Ev +72 (int (*)(...))std::basic_ostream::_ZTv0_n24_NSoD0Ev + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSd: 7u entries +0 ((& std::basic_iostream::_ZTVSd) + 24u) +8 ((& std::basic_iostream::_ZTCSd0_Si) + 24u) +16 ((& std::basic_iostream::_ZTCSd0_Si) + 64u) +24 ((& std::basic_iostream::_ZTCSd16_So) + 24u) +32 ((& std::basic_iostream::_ZTCSd16_So) + 64u) +40 ((& std::basic_iostream::_ZTVSd) + 104u) +48 ((& std::basic_iostream::_ZTVSd) + 64u) + +Construction vtable for std::basic_istream (0x0x7f95ef810e38 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10u entries +0 24u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +24 (int (*)(...))std::basic_istream<_CharT, _Traits>::~basic_istream > +32 (int (*)(...))std::basic_istream<_CharT, _Traits>::~basic_istream > +40 18446744073709551592u +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +64 (int (*)(...))std::basic_istream::_ZTv0_n24_NSt13basic_istreamIwSt11char_traitsIwEED1Ev +72 (int (*)(...))std::basic_istream::_ZTv0_n24_NSt13basic_istreamIwSt11char_traitsIwEED0Ev + +Construction vtable for std::basic_ostream (0x0x7f95ef810f08 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10u entries +0 8u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +24 (int (*)(...))std::basic_ostream<_CharT, _Traits>::~basic_ostream > +32 (int (*)(...))std::basic_ostream<_CharT, _Traits>::~basic_ostream > +40 18446744073709551608u +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +64 (int (*)(...))std::basic_ostream::_ZTv0_n24_NSt13basic_ostreamIwSt11char_traitsIwEED1Ev +72 (int (*)(...))std::basic_ostream::_ZTv0_n24_NSt13basic_ostreamIwSt11char_traitsIwEED0Ev + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7u entries +0 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24u) +16 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64u) +24 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24u) +32 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64u) +40 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104u) +48 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64u) + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f95ef8b0000) 0 + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f95ef8b0300) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f95ef8b02a0) 0 + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f95ef8b06c0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f95ef6a5420) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f95ef67d208) 0 + std::iterator (0x0x7f95ef6a54e0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f95ef67d270) 0 + std::_Bit_iterator_base (0x0x7f95ef67d2d8) 0 + std::iterator (0x0x7f95ef6a5540) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f95ef67d340) 0 + std::_Bit_iterator_base (0x0x7f95ef67d3a8) 0 + std::iterator (0x0x7f95ef6a55a0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f95ef6a5960) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f95ef6a5d80) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f95ef6a5e40) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f95ef6a5f00) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f95ef180360) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f95ef1806c0) 0 + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f95ef180ae0) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f95ef180cc0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f95ef180d80) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f95eeff3060) 0 + +Vtable for QObjectData +QObjectData::_ZTV11QObjectData: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QObjectData) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))__cxa_pure_virtual + +Class QObjectData + size=48 align=8 + base size=48 base align=8 +QObjectData (0x0x7f95eeff31e0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f95eeff3360) 0 empty + +Vtable for QObject +QObject::_ZTV7QObject: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QObject) +16 (int (*)(...))QObject::metaObject +24 (int (*)(...))QObject::qt_metacast +32 (int (*)(...))QObject::qt_metacall +40 (int (*)(...))QObject::~QObject +48 (int (*)(...))QObject::~QObject +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QObject + size=16 align=8 + base size=16 base align=8 +QObject (0x0x7f95eeff3300) 0 + vptr=((& QObject::_ZTV7QObject) + 16u) + +Vtable for QObjectUserData +QObjectUserData::_ZTV15QObjectUserData: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QObjectUserData) +16 (int (*)(...))QObjectUserData::~QObjectUserData +24 (int (*)(...))QObjectUserData::~QObjectUserData + +Class QObjectUserData + size=8 align=8 + base size=8 base align=8 +QObjectUserData (0x0x7f95eeff3660) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f95eeff36c0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f95eeff3780) 0 empty + +Vtable for QAbstractAnimation +QAbstractAnimation::_ZTV18QAbstractAnimation: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractAnimation) +16 (int (*)(...))QAbstractAnimation::metaObject +24 (int (*)(...))QAbstractAnimation::qt_metacast +32 (int (*)(...))QAbstractAnimation::qt_metacall +40 (int (*)(...))QAbstractAnimation::~QAbstractAnimation +48 (int (*)(...))QAbstractAnimation::~QAbstractAnimation +56 (int (*)(...))QAbstractAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QAbstractAnimation + size=16 align=8 + base size=16 base align=8 +QAbstractAnimation (0x0x7f95ef204dd0) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f95eeff3720) 0 + primary-for QAbstractAnimation (0x0x7f95ef204dd0) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f95eeff3840) 0 empty + +Vtable for QAnimationDriver +QAnimationDriver::_ZTV16QAnimationDriver: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QAnimationDriver) +16 (int (*)(...))QAnimationDriver::metaObject +24 (int (*)(...))QAnimationDriver::qt_metacast +32 (int (*)(...))QAnimationDriver::qt_metacall +40 (int (*)(...))QAnimationDriver::~QAnimationDriver +48 (int (*)(...))QAnimationDriver::~QAnimationDriver +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAnimationDriver::advance +120 (int (*)(...))QAnimationDriver::elapsed +128 (int (*)(...))QAnimationDriver::start +136 (int (*)(...))QAnimationDriver::stop + +Class QAnimationDriver + size=16 align=8 + base size=16 base align=8 +QAnimationDriver (0x0x7f95ef204e38) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f95eeff37e0) 0 + primary-for QAnimationDriver (0x0x7f95ef204e38) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f95eeff3900) 0 empty + +Vtable for QAnimationGroup +QAnimationGroup::_ZTV15QAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAnimationGroup) +16 (int (*)(...))QAnimationGroup::metaObject +24 (int (*)(...))QAnimationGroup::qt_metacast +32 (int (*)(...))QAnimationGroup::qt_metacall +40 (int (*)(...))QAnimationGroup::~QAnimationGroup +48 (int (*)(...))QAnimationGroup::~QAnimationGroup +56 (int (*)(...))QAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QAnimationGroup + size=16 align=8 + base size=16 base align=8 +QAnimationGroup (0x0x7f95ef204ea0) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f95ef204f08) 0 + primary-for QAnimationGroup (0x0x7f95ef204ea0) + QObject (0x0x7f95eeff38a0) 0 + primary-for QAbstractAnimation (0x0x7f95ef204f08) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f95eeff39c0) 0 empty + +Vtable for QParallelAnimationGroup +QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QParallelAnimationGroup) +16 (int (*)(...))QParallelAnimationGroup::metaObject +24 (int (*)(...))QParallelAnimationGroup::qt_metacast +32 (int (*)(...))QParallelAnimationGroup::qt_metacall +40 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup +48 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup +56 (int (*)(...))QParallelAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QParallelAnimationGroup::duration +120 (int (*)(...))QParallelAnimationGroup::updateCurrentTime +128 (int (*)(...))QParallelAnimationGroup::updateState +136 (int (*)(...))QParallelAnimationGroup::updateDirection + +Class QParallelAnimationGroup + size=16 align=8 + base size=16 base align=8 +QParallelAnimationGroup (0x0x7f95ef204f70) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f95eecee000) 0 + primary-for QParallelAnimationGroup (0x0x7f95ef204f70) + QAbstractAnimation (0x0x7f95eecee068) 0 + primary-for QAnimationGroup (0x0x7f95eecee000) + QObject (0x0x7f95eeff3960) 0 + primary-for QAbstractAnimation (0x0x7f95eecee068) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f95eeff3a80) 0 empty + +Vtable for QPauseAnimation +QPauseAnimation::_ZTV15QPauseAnimation: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QPauseAnimation) +16 (int (*)(...))QPauseAnimation::metaObject +24 (int (*)(...))QPauseAnimation::qt_metacast +32 (int (*)(...))QPauseAnimation::qt_metacall +40 (int (*)(...))QPauseAnimation::~QPauseAnimation +48 (int (*)(...))QPauseAnimation::~QPauseAnimation +56 (int (*)(...))QPauseAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QPauseAnimation::duration +120 (int (*)(...))QPauseAnimation::updateCurrentTime +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QPauseAnimation + size=16 align=8 + base size=16 base align=8 +QPauseAnimation (0x0x7f95eecee0d0) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f95eecee138) 0 + primary-for QPauseAnimation (0x0x7f95eecee0d0) + QObject (0x0x7f95eeff3a20) 0 + primary-for QAbstractAnimation (0x0x7f95eecee138) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f95eeff3c60) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f95eeff3e40) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f95eeff3f00) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f95eee232a0) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7f95eee23240) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f95eee23300) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f95eee237e0) 0 empty + +Vtable for QIODevice +QIODevice::_ZTV9QIODevice: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QIODevice) +16 (int (*)(...))QIODevice::metaObject +24 (int (*)(...))QIODevice::qt_metacast +32 (int (*)(...))QIODevice::qt_metacall +40 (int (*)(...))QIODevice::~QIODevice +48 (int (*)(...))QIODevice::~QIODevice +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QIODevice::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QIODevice::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))__cxa_pure_virtual +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))__cxa_pure_virtual + +Class QIODevice + size=16 align=8 + base size=16 base align=8 +QIODevice (0x0x7f95eeceea28) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f95eee23780) 0 + primary-for QIODevice (0x0x7f95eeceea28) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f95eee23900) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f95eee239c0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f95eee23b40) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f95eee23ae0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f95eeceebc8) 0 + QList (0x0x7f95eee23cc0) 0 + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f95ee8fe000) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f95ee8fe0c0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f95ee8fe060) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f95ee8fe120) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f95eee23f60) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f95ee8fe3c0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f95ee8fe480) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f95ee8fe420) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f95ee8fe540) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f95ee8fe4e0) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f95eea14120) 0 empty + +Vtable for QVariantAnimation +QVariantAnimation::_ZTV17QVariantAnimation: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QVariantAnimation) +16 (int (*)(...))QVariantAnimation::metaObject +24 (int (*)(...))QVariantAnimation::qt_metacast +32 (int (*)(...))QVariantAnimation::qt_metacall +40 (int (*)(...))QVariantAnimation::~QVariantAnimation +48 (int (*)(...))QVariantAnimation::~QVariantAnimation +56 (int (*)(...))QVariantAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QVariantAnimation::duration +120 (int (*)(...))QVariantAnimation::updateCurrentTime +128 (int (*)(...))QVariantAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection +144 (int (*)(...))QVariantAnimation::updateCurrentValue +152 (int (*)(...))QVariantAnimation::interpolated + +Class QVariantAnimation + size=16 align=8 + base size=16 base align=8 +QVariantAnimation (0x0x7f95ee9cc5b0) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f95ee9cc618) 0 + primary-for QVariantAnimation (0x0x7f95ee9cc5b0) + QObject (0x0x7f95eea140c0) 0 + primary-for QAbstractAnimation (0x0x7f95ee9cc618) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f95eea141e0) 0 empty + +Vtable for QPropertyAnimation +QPropertyAnimation::_ZTV18QPropertyAnimation: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QPropertyAnimation) +16 (int (*)(...))QPropertyAnimation::metaObject +24 (int (*)(...))QPropertyAnimation::qt_metacast +32 (int (*)(...))QPropertyAnimation::qt_metacall +40 (int (*)(...))QPropertyAnimation::~QPropertyAnimation +48 (int (*)(...))QPropertyAnimation::~QPropertyAnimation +56 (int (*)(...))QPropertyAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QVariantAnimation::duration +120 (int (*)(...))QVariantAnimation::updateCurrentTime +128 (int (*)(...))QPropertyAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection +144 (int (*)(...))QPropertyAnimation::updateCurrentValue +152 (int (*)(...))QVariantAnimation::interpolated + +Class QPropertyAnimation + size=16 align=8 + base size=16 base align=8 +QPropertyAnimation (0x0x7f95ee9cc6e8) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f95ee9cc750) 0 + primary-for QPropertyAnimation (0x0x7f95ee9cc6e8) + QAbstractAnimation (0x0x7f95ee9cc7b8) 0 + primary-for QVariantAnimation (0x0x7f95ee9cc750) + QObject (0x0x7f95eea14180) 0 + primary-for QAbstractAnimation (0x0x7f95ee9cc7b8) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f95eea142a0) 0 empty + +Vtable for QSequentialAnimationGroup +QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QSequentialAnimationGroup) +16 (int (*)(...))QSequentialAnimationGroup::metaObject +24 (int (*)(...))QSequentialAnimationGroup::qt_metacast +32 (int (*)(...))QSequentialAnimationGroup::qt_metacall +40 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup +48 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup +56 (int (*)(...))QSequentialAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSequentialAnimationGroup::duration +120 (int (*)(...))QSequentialAnimationGroup::updateCurrentTime +128 (int (*)(...))QSequentialAnimationGroup::updateState +136 (int (*)(...))QSequentialAnimationGroup::updateDirection + +Class QSequentialAnimationGroup + size=16 align=8 + base size=16 base align=8 +QSequentialAnimationGroup (0x0x7f95ee9cc820) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f95ee9cc888) 0 + primary-for QSequentialAnimationGroup (0x0x7f95ee9cc820) + QAbstractAnimation (0x0x7f95ee9cc8f0) 0 + primary-for QAnimationGroup (0x0x7f95ee9cc888) + QObject (0x0x7f95eea14240) 0 + primary-for QAbstractAnimation (0x0x7f95ee9cc8f0) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f95eea14360) 0 + +Vtable for QTextCodec +QTextCodec::_ZTV10QTextCodec: 9u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QTextCodec) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))QTextCodec::aliases +32 (int (*)(...))__cxa_pure_virtual +40 (int (*)(...))__cxa_pure_virtual +48 (int (*)(...))__cxa_pure_virtual +56 (int (*)(...))QTextCodec::~QTextCodec +64 (int (*)(...))QTextCodec::~QTextCodec + +Class QTextCodec + size=8 align=8 + base size=8 base align=8 +QTextCodec (0x0x7f95eea14300) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f95eea14480) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f95eea144e0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f95eea14540) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f95eea147e0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f95eea14960) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f95eea14de0) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f95ee7cd5a0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f95ee7cd6c0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f95ee7cd7e0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f95ee7cd960) 0 empty + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f95ee7cda20) 0 empty + +Vtable for QBuffer +QBuffer::_ZTV7QBuffer: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QBuffer) +16 (int (*)(...))QBuffer::metaObject +24 (int (*)(...))QBuffer::qt_metacast +32 (int (*)(...))QBuffer::qt_metacall +40 (int (*)(...))QBuffer::~QBuffer +48 (int (*)(...))QBuffer::~QBuffer +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QBuffer::connectNotify +104 (int (*)(...))QBuffer::disconnectNotify +112 (int (*)(...))QIODevice::isSequential +120 (int (*)(...))QBuffer::open +128 (int (*)(...))QBuffer::close +136 (int (*)(...))QBuffer::pos +144 (int (*)(...))QBuffer::size +152 (int (*)(...))QBuffer::seek +160 (int (*)(...))QBuffer::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QBuffer::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBuffer::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBuffer::writeData + +Class QBuffer + size=16 align=8 + base size=16 base align=8 +QBuffer (0x0x7f95ee9ccf08) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f95ee9ccf70) 0 + primary-for QBuffer (0x0x7f95ee9ccf08) + QObject (0x0x7f95ee7cd9c0) 0 + primary-for QIODevice (0x0x7f95ee9ccf70) + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f95ee7cda80) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f95ee7cdd80) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f95ee7cdde0) 0 + +Vtable for QTextStream +QTextStream::_ZTV11QTextStream: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTextStream) +16 (int (*)(...))QTextStream::~QTextStream +24 (int (*)(...))QTextStream::~QTextStream + +Class QTextStream + size=16 align=8 + base size=16 base align=8 +QTextStream (0x0x7f95ee7cdea0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f95ee59f180) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f95ee59f3c0) 0 + +Class QDebug::Stream + size=72 align=8 + base size=72 base align=8 +QDebug::Stream (0x0x7f95ee59fa20) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f95ee59f9c0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f95ee59fb40) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f95ee59fc00) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f95ee59fcc0) 0 empty + +Vtable for QFileDevice +QFileDevice::_ZTV11QFileDevice: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QFileDevice) +16 (int (*)(...))QFileDevice::metaObject +24 (int (*)(...))QFileDevice::qt_metacast +32 (int (*)(...))QFileDevice::qt_metacall +40 (int (*)(...))QFileDevice::~QFileDevice +48 (int (*)(...))QFileDevice::~QFileDevice +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFileDevice::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QFileDevice::fileName +248 (int (*)(...))QFileDevice::resize +256 (int (*)(...))QFileDevice::permissions +264 (int (*)(...))QFileDevice::setPermissions + +Class QFileDevice + size=16 align=8 + base size=16 base align=8 +QFileDevice (0x0x7f95ee5a2208) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f95ee5a2270) 0 + primary-for QFileDevice (0x0x7f95ee5a2208) + QObject (0x0x7f95ee59fc60) 0 + primary-for QIODevice (0x0x7f95ee5a2270) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f95ee59fe40) 0 empty + +Vtable for QFile +QFile::_ZTV5QFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI5QFile) +16 (int (*)(...))QFile::metaObject +24 (int (*)(...))QFile::qt_metacast +32 (int (*)(...))QFile::qt_metacall +40 (int (*)(...))QFile::~QFile +48 (int (*)(...))QFile::~QFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QFile::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFile::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QFile::fileName +248 (int (*)(...))QFile::resize +256 (int (*)(...))QFile::permissions +264 (int (*)(...))QFile::setPermissions + +Class QFile + size=16 align=8 + base size=16 base align=8 +QFile (0x0x7f95ee5a23a8) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f95ee5a2410) 0 + primary-for QFile (0x0x7f95ee5a23a8) + QIODevice (0x0x7f95ee5a2478) 0 + primary-for QFileDevice (0x0x7f95ee5a2410) + QObject (0x0x7f95ee59fde0) 0 + primary-for QIODevice (0x0x7f95ee5a2478) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f95ee59ff60) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f95ee371240) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f95ee371540) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f95ee371720) 0 empty + +Vtable for QFileSelector +QFileSelector::_ZTV13QFileSelector: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QFileSelector) +16 (int (*)(...))QFileSelector::metaObject +24 (int (*)(...))QFileSelector::qt_metacast +32 (int (*)(...))QFileSelector::qt_metacall +40 (int (*)(...))QFileSelector::~QFileSelector +48 (int (*)(...))QFileSelector::~QFileSelector +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QFileSelector + size=16 align=8 + base size=16 base align=8 +QFileSelector (0x0x7f95ee5a2958) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f95ee3716c0) 0 + primary-for QFileSelector (0x0x7f95ee5a2958) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f95ee3717e0) 0 empty + +Vtable for QFileSystemWatcher +QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFileSystemWatcher) +16 (int (*)(...))QFileSystemWatcher::metaObject +24 (int (*)(...))QFileSystemWatcher::qt_metacast +32 (int (*)(...))QFileSystemWatcher::qt_metacall +40 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher +48 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QFileSystemWatcher + size=16 align=8 + base size=16 base align=8 +QFileSystemWatcher (0x0x7f95ee5a29c0) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f95ee371780) 0 + primary-for QFileSystemWatcher (0x0x7f95ee5a29c0) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f95ee371840) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f95ee371960) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f95ee3719c0) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f95ee371ba0) 0 empty + +Vtable for QProcess +QProcess::_ZTV8QProcess: 31u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI8QProcess) +16 (int (*)(...))QProcess::metaObject +24 (int (*)(...))QProcess::qt_metacast +32 (int (*)(...))QProcess::qt_metacall +40 (int (*)(...))QProcess::~QProcess +48 (int (*)(...))QProcess::~QProcess +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QProcess::isSequential +120 (int (*)(...))QProcess::open +128 (int (*)(...))QProcess::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QProcess::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QProcess::bytesAvailable +184 (int (*)(...))QProcess::bytesToWrite +192 (int (*)(...))QProcess::canReadLine +200 (int (*)(...))QProcess::waitForReadyRead +208 (int (*)(...))QProcess::waitForBytesWritten +216 (int (*)(...))QProcess::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QProcess::writeData +240 (int (*)(...))QProcess::setupChildProcess + +Class QProcess + size=16 align=8 + base size=16 base align=8 +QProcess (0x0x7f95ee5a2a90) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f95ee5a2af8) 0 + primary-for QProcess (0x0x7f95ee5a2a90) + QObject (0x0x7f95ee371b40) 0 + primary-for QIODevice (0x0x7f95ee5a2af8) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f95ee371c00) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f95ee371d80) 0 empty + +Vtable for QSaveFile +QSaveFile::_ZTV9QSaveFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QSaveFile) +16 (int (*)(...))QSaveFile::metaObject +24 (int (*)(...))QSaveFile::qt_metacast +32 (int (*)(...))QSaveFile::qt_metacall +40 (int (*)(...))QSaveFile::~QSaveFile +48 (int (*)(...))QSaveFile::~QSaveFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QSaveFile::open +128 (int (*)(...))QSaveFile::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFileDevice::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QSaveFile::writeData +240 (int (*)(...))QSaveFile::fileName +248 (int (*)(...))QFileDevice::resize +256 (int (*)(...))QFileDevice::permissions +264 (int (*)(...))QFileDevice::setPermissions + +Class QSaveFile + size=16 align=8 + base size=16 base align=8 +QSaveFile (0x0x7f95ee5a2b60) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f95ee5a2bc8) 0 + primary-for QSaveFile (0x0x7f95ee5a2b60) + QIODevice (0x0x7f95ee5a2c30) 0 + primary-for QFileDevice (0x0x7f95ee5a2bc8) + QObject (0x0x7f95ee371d20) 0 + primary-for QIODevice (0x0x7f95ee5a2c30) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f95ee371e40) 0 empty + +Vtable for QSettings +QSettings::_ZTV9QSettings: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QSettings) +16 (int (*)(...))QSettings::metaObject +24 (int (*)(...))QSettings::qt_metacast +32 (int (*)(...))QSettings::qt_metacall +40 (int (*)(...))QSettings::~QSettings +48 (int (*)(...))QSettings::~QSettings +56 (int (*)(...))QSettings::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSettings + size=16 align=8 + base size=16 base align=8 +QSettings (0x0x7f95ee5a2c98) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f95ee371de0) 0 + primary-for QSettings (0x0x7f95ee5a2c98) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f95ee371ea0) 0 empty + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f95ee0f2000) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f95ee0f2120) 0 empty + +Vtable for QTemporaryFile +QTemporaryFile::_ZTV14QTemporaryFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QTemporaryFile) +16 (int (*)(...))QTemporaryFile::metaObject +24 (int (*)(...))QTemporaryFile::qt_metacast +32 (int (*)(...))QTemporaryFile::qt_metacall +40 (int (*)(...))QTemporaryFile::~QTemporaryFile +48 (int (*)(...))QTemporaryFile::~QTemporaryFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QTemporaryFile::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFile::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QTemporaryFile::fileName +248 (int (*)(...))QFile::resize +256 (int (*)(...))QFile::permissions +264 (int (*)(...))QFile::setPermissions + +Class QTemporaryFile + size=16 align=8 + base size=16 base align=8 +QTemporaryFile (0x0x7f95ee5a2dd0) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f95ee5a2e38) 0 + primary-for QTemporaryFile (0x0x7f95ee5a2dd0) + QFileDevice (0x0x7f95ee5a2ea0) 0 + primary-for QFile (0x0x7f95ee5a2e38) + QIODevice (0x0x7f95ee5a2f08) 0 + primary-for QFileDevice (0x0x7f95ee5a2ea0) + QObject (0x0x7f95ee0f20c0) 0 + primary-for QIODevice (0x0x7f95ee5a2f08) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f95ee0f2240) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f95ee0f2660) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f95ee0f27e0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f95ee0f2900) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f95ee0f2a80) 0 empty + +Vtable for QAbstractItemModel +QAbstractItemModel::_ZTV18QAbstractItemModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractItemModel) +16 (int (*)(...))QAbstractItemModel::metaObject +24 (int (*)(...))QAbstractItemModel::qt_metacast +32 (int (*)(...))QAbstractItemModel::qt_metacall +40 (int (*)(...))QAbstractItemModel::~QAbstractItemModel +48 (int (*)(...))QAbstractItemModel::~QAbstractItemModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractItemModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractItemModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractItemModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractItemModel + size=16 align=8 + base size=16 base align=8 +QAbstractItemModel (0x0x7f95ee1602d8) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f95ee0f2a20) 0 + primary-for QAbstractItemModel (0x0x7f95ee1602d8) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f95ee0f2d80) 0 empty + +Vtable for QAbstractTableModel +QAbstractTableModel::_ZTV19QAbstractTableModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTableModel) +16 (int (*)(...))QAbstractTableModel::metaObject +24 (int (*)(...))QAbstractTableModel::qt_metacast +32 (int (*)(...))QAbstractTableModel::qt_metacall +40 (int (*)(...))QAbstractTableModel::~QAbstractTableModel +48 (int (*)(...))QAbstractTableModel::~QAbstractTableModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractTableModel::index +120 (int (*)(...))QAbstractTableModel::parent +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractTableModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractTableModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractTableModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractTableModel + size=16 align=8 + base size=16 base align=8 +QAbstractTableModel (0x0x7f95ee160410) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f95ee160478) 0 + primary-for QAbstractTableModel (0x0x7f95ee160410) + QObject (0x0x7f95ee0f2d20) 0 + primary-for QAbstractItemModel (0x0x7f95ee160478) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f95ee0f2e40) 0 empty + +Vtable for QAbstractListModel +QAbstractListModel::_ZTV18QAbstractListModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractListModel) +16 (int (*)(...))QAbstractListModel::metaObject +24 (int (*)(...))QAbstractListModel::qt_metacast +32 (int (*)(...))QAbstractListModel::qt_metacall +40 (int (*)(...))QAbstractListModel::~QAbstractListModel +48 (int (*)(...))QAbstractListModel::~QAbstractListModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractListModel::index +120 (int (*)(...))QAbstractListModel::parent +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QAbstractListModel::columnCount +152 (int (*)(...))QAbstractListModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractListModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractListModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractListModel + size=16 align=8 + base size=16 base align=8 +QAbstractListModel (0x0x7f95ee1604e0) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f95ee160548) 0 + primary-for QAbstractListModel (0x0x7f95ee1604e0) + QObject (0x0x7f95ee0f2de0) 0 + primary-for QAbstractItemModel (0x0x7f95ee160548) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f95ee0f2f00) 0 empty + +Vtable for QAbstractProxyModel +QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractProxyModel) +16 (int (*)(...))QAbstractProxyModel::metaObject +24 (int (*)(...))QAbstractProxyModel::qt_metacast +32 (int (*)(...))QAbstractProxyModel::qt_metacall +40 (int (*)(...))QAbstractProxyModel::~QAbstractProxyModel +48 (int (*)(...))QAbstractProxyModel::~QAbstractProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractProxyModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QAbstractProxyModel::headerData +184 (int (*)(...))QAbstractProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QAbstractProxyModel::mimeTypes +216 (int (*)(...))QAbstractProxyModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractItemModel::dropMimeData +240 (int (*)(...))QAbstractProxyModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QAbstractProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QAbstractProxyModel::setSourceModel +392 (int (*)(...))__cxa_pure_virtual +400 (int (*)(...))__cxa_pure_virtual +408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource +416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource + +Class QAbstractProxyModel + size=16 align=8 + base size=16 base align=8 +QAbstractProxyModel (0x0x7f95ee1605b0) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f95ee160618) 0 + primary-for QAbstractProxyModel (0x0x7f95ee1605b0) + QObject (0x0x7f95ee0f2ea0) 0 + primary-for QAbstractItemModel (0x0x7f95ee160618) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f95edee8000) 0 empty + +Vtable for QIdentityProxyModel +QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QIdentityProxyModel) +16 (int (*)(...))QIdentityProxyModel::metaObject +24 (int (*)(...))QIdentityProxyModel::qt_metacast +32 (int (*)(...))QIdentityProxyModel::qt_metacall +40 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel +48 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QIdentityProxyModel::index +120 (int (*)(...))QIdentityProxyModel::parent +128 (int (*)(...))QIdentityProxyModel::sibling +136 (int (*)(...))QIdentityProxyModel::rowCount +144 (int (*)(...))QIdentityProxyModel::columnCount +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QIdentityProxyModel::headerData +184 (int (*)(...))QAbstractProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QAbstractProxyModel::mimeTypes +216 (int (*)(...))QAbstractProxyModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QIdentityProxyModel::dropMimeData +240 (int (*)(...))QAbstractProxyModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QIdentityProxyModel::insertRows +264 (int (*)(...))QIdentityProxyModel::insertColumns +272 (int (*)(...))QIdentityProxyModel::removeRows +280 (int (*)(...))QIdentityProxyModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QAbstractProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QIdentityProxyModel::match +352 (int (*)(...))QAbstractProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QIdentityProxyModel::setSourceModel +392 (int (*)(...))QIdentityProxyModel::mapToSource +400 (int (*)(...))QIdentityProxyModel::mapFromSource +408 (int (*)(...))QIdentityProxyModel::mapSelectionToSource +416 (int (*)(...))QIdentityProxyModel::mapSelectionFromSource + +Class QIdentityProxyModel + size=16 align=8 + base size=16 base align=8 +QIdentityProxyModel (0x0x7f95ee160680) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f95ee1606e8) 0 + primary-for QIdentityProxyModel (0x0x7f95ee160680) + QAbstractItemModel (0x0x7f95ee160750) 0 + primary-for QAbstractProxyModel (0x0x7f95ee1606e8) + QObject (0x0x7f95ee0f2f60) 0 + primary-for QAbstractItemModel (0x0x7f95ee160750) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f95edee8060) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f95edee81e0) 0 empty + +Vtable for QItemSelectionModel +QItemSelectionModel::_ZTV19QItemSelectionModel: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QItemSelectionModel) +16 (int (*)(...))QItemSelectionModel::metaObject +24 (int (*)(...))QItemSelectionModel::qt_metacast +32 (int (*)(...))QItemSelectionModel::qt_metacall +40 (int (*)(...))QItemSelectionModel::~QItemSelectionModel +48 (int (*)(...))QItemSelectionModel::~QItemSelectionModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QItemSelectionModel::setCurrentIndex +120 (int (*)(...))QItemSelectionModel::select +128 (int (*)(...))QItemSelectionModel::select +136 (int (*)(...))QItemSelectionModel::clear +144 (int (*)(...))QItemSelectionModel::reset +152 (int (*)(...))QItemSelectionModel::clearCurrentIndex + +Class QItemSelectionModel + size=16 align=8 + base size=16 base align=8 +QItemSelectionModel (0x0x7f95ee160820) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f95edee8180) 0 + primary-for QItemSelectionModel (0x0x7f95ee160820) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f95ee160958) 0 + QList (0x0x7f95edee83c0) 0 + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f95edee8480) 0 empty + +Vtable for QSortFilterProxyModel +QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QSortFilterProxyModel) +16 (int (*)(...))QSortFilterProxyModel::metaObject +24 (int (*)(...))QSortFilterProxyModel::qt_metacast +32 (int (*)(...))QSortFilterProxyModel::qt_metacall +40 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel +48 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSortFilterProxyModel::index +120 (int (*)(...))QSortFilterProxyModel::parent +128 (int (*)(...))QSortFilterProxyModel::sibling +136 (int (*)(...))QSortFilterProxyModel::rowCount +144 (int (*)(...))QSortFilterProxyModel::columnCount +152 (int (*)(...))QSortFilterProxyModel::hasChildren +160 (int (*)(...))QSortFilterProxyModel::data +168 (int (*)(...))QSortFilterProxyModel::setData +176 (int (*)(...))QSortFilterProxyModel::headerData +184 (int (*)(...))QSortFilterProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QSortFilterProxyModel::mimeTypes +216 (int (*)(...))QSortFilterProxyModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QSortFilterProxyModel::dropMimeData +240 (int (*)(...))QSortFilterProxyModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QSortFilterProxyModel::insertRows +264 (int (*)(...))QSortFilterProxyModel::insertColumns +272 (int (*)(...))QSortFilterProxyModel::removeRows +280 (int (*)(...))QSortFilterProxyModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QSortFilterProxyModel::fetchMore +312 (int (*)(...))QSortFilterProxyModel::canFetchMore +320 (int (*)(...))QSortFilterProxyModel::flags +328 (int (*)(...))QSortFilterProxyModel::sort +336 (int (*)(...))QSortFilterProxyModel::buddy +344 (int (*)(...))QSortFilterProxyModel::match +352 (int (*)(...))QSortFilterProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QSortFilterProxyModel::setSourceModel +392 (int (*)(...))QSortFilterProxyModel::mapToSource +400 (int (*)(...))QSortFilterProxyModel::mapFromSource +408 (int (*)(...))QSortFilterProxyModel::mapSelectionToSource +416 (int (*)(...))QSortFilterProxyModel::mapSelectionFromSource +424 (int (*)(...))QSortFilterProxyModel::filterAcceptsRow +432 (int (*)(...))QSortFilterProxyModel::filterAcceptsColumn +440 (int (*)(...))QSortFilterProxyModel::lessThan + +Class QSortFilterProxyModel + size=16 align=8 + base size=16 base align=8 +QSortFilterProxyModel (0x0x7f95ee1609c0) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f95ee160a28) 0 + primary-for QSortFilterProxyModel (0x0x7f95ee1609c0) + QAbstractItemModel (0x0x7f95ee160a90) 0 + primary-for QAbstractProxyModel (0x0x7f95ee160a28) + QObject (0x0x7f95edee8420) 0 + primary-for QAbstractItemModel (0x0x7f95ee160a90) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f95edee8540) 0 empty + +Vtable for QStringListModel +QStringListModel::_ZTV16QStringListModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QStringListModel) +16 (int (*)(...))QStringListModel::metaObject +24 (int (*)(...))QStringListModel::qt_metacast +32 (int (*)(...))QStringListModel::qt_metacall +40 (int (*)(...))QStringListModel::~QStringListModel +48 (int (*)(...))QStringListModel::~QStringListModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractListModel::index +120 (int (*)(...))QAbstractListModel::parent +128 (int (*)(...))QStringListModel::sibling +136 (int (*)(...))QStringListModel::rowCount +144 (int (*)(...))QAbstractListModel::columnCount +152 (int (*)(...))QAbstractListModel::hasChildren +160 (int (*)(...))QStringListModel::data +168 (int (*)(...))QStringListModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractListModel::dropMimeData +240 (int (*)(...))QStringListModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QStringListModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QStringListModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QStringListModel::flags +328 (int (*)(...))QStringListModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QStringListModel + size=24 align=8 + base size=24 base align=8 +QStringListModel (0x0x7f95ee160af8) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f95ee160b60) 0 + primary-for QStringListModel (0x0x7f95ee160af8) + QAbstractItemModel (0x0x7f95ee160bc8) 0 + primary-for QAbstractListModel (0x0x7f95ee160b60) + QObject (0x0x7f95edee84e0) 0 + primary-for QAbstractItemModel (0x0x7f95ee160bc8) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f95edee85a0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f95edee8660) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f95edee8780) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f95edee87e0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f95edee8720) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f95edee8840) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f95edee88a0) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f95edee8960) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f95edee89c0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f95edee8900) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f95edee8ae0) 0 empty + +Vtable for QEventLoop +QEventLoop::_ZTV10QEventLoop: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QEventLoop) +16 (int (*)(...))QEventLoop::metaObject +24 (int (*)(...))QEventLoop::qt_metacast +32 (int (*)(...))QEventLoop::qt_metacall +40 (int (*)(...))QEventLoop::~QEventLoop +48 (int (*)(...))QEventLoop::~QEventLoop +56 (int (*)(...))QEventLoop::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QEventLoop + size=16 align=8 + base size=16 base align=8 +QEventLoop (0x0x7f95ee160c30) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f95edee8a80) 0 + primary-for QEventLoop (0x0x7f95ee160c30) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f95edee8c00) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f95edee8cc0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f95edee8d20) 0 + +Vtable for QAbstractEventDispatcher +QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher) +16 (int (*)(...))QAbstractEventDispatcher::metaObject +24 (int (*)(...))QAbstractEventDispatcher::qt_metacast +32 (int (*)(...))QAbstractEventDispatcher::qt_metacall +40 (int (*)(...))QAbstractEventDispatcher::~QAbstractEventDispatcher +48 (int (*)(...))QAbstractEventDispatcher::~QAbstractEventDispatcher +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual +184 (int (*)(...))__cxa_pure_virtual +192 (int (*)(...))__cxa_pure_virtual +200 (int (*)(...))__cxa_pure_virtual +208 (int (*)(...))QAbstractEventDispatcher::startingUp +216 (int (*)(...))QAbstractEventDispatcher::closingDown + +Class QAbstractEventDispatcher + size=16 align=8 + base size=16 base align=8 +QAbstractEventDispatcher (0x0x7f95ee160d68) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f95edee8c60) 0 + primary-for QAbstractEventDispatcher (0x0x7f95ee160d68) + +Vtable for QAbstractNativeEventFilter +QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter) +16 (int (*)(...))QAbstractNativeEventFilter::~QAbstractNativeEventFilter +24 (int (*)(...))QAbstractNativeEventFilter::~QAbstractNativeEventFilter +32 (int (*)(...))__cxa_pure_virtual + +Class QAbstractNativeEventFilter + size=16 align=8 + base size=16 base align=8 +QAbstractNativeEventFilter (0x0x7f95edee8d80) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f95edee8de0) 0 + +Vtable for QEvent +QEvent::_ZTV6QEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QEvent) +16 (int (*)(...))QEvent::~QEvent +24 (int (*)(...))QEvent::~QEvent + +Class QEvent + size=24 align=8 + base size=20 base align=8 +QEvent (0x0x7f95edee8f00) 0 + vptr=((& QEvent::_ZTV6QEvent) + 16u) + +Vtable for QTimerEvent +QTimerEvent::_ZTV11QTimerEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTimerEvent) +16 (int (*)(...))QTimerEvent::~QTimerEvent +24 (int (*)(...))QTimerEvent::~QTimerEvent + +Class QTimerEvent + size=24 align=8 + base size=24 base align=8 +QTimerEvent (0x0x7f95ee160e38) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f95edee8f60) 0 + primary-for QTimerEvent (0x0x7f95ee160e38) + +Vtable for QChildEvent +QChildEvent::_ZTV11QChildEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QChildEvent) +16 (int (*)(...))QChildEvent::~QChildEvent +24 (int (*)(...))QChildEvent::~QChildEvent + +Class QChildEvent + size=32 align=8 + base size=32 base align=8 +QChildEvent (0x0x7f95ee160ea0) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f95edd19000) 0 + primary-for QChildEvent (0x0x7f95ee160ea0) + +Vtable for QDynamicPropertyChangeEvent +QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI27QDynamicPropertyChangeEvent) +16 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent +24 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent + +Class QDynamicPropertyChangeEvent + size=32 align=8 + base size=32 base align=8 +QDynamicPropertyChangeEvent (0x0x7f95ee160f08) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f95edd19060) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f95ee160f08) + +Vtable for QDeferredDeleteEvent +QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QDeferredDeleteEvent) +16 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent +24 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent + +Class QDeferredDeleteEvent + size=24 align=8 + base size=24 base align=8 +QDeferredDeleteEvent (0x0x7f95ee160f70) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f95edd190c0) 0 + primary-for QDeferredDeleteEvent (0x0x7f95ee160f70) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f95edd19180) 0 empty + +Vtable for QCoreApplication +QCoreApplication::_ZTV16QCoreApplication: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QCoreApplication) +16 (int (*)(...))QCoreApplication::metaObject +24 (int (*)(...))QCoreApplication::qt_metacast +32 (int (*)(...))QCoreApplication::qt_metacall +40 (int (*)(...))QCoreApplication::~QCoreApplication +48 (int (*)(...))QCoreApplication::~QCoreApplication +56 (int (*)(...))QCoreApplication::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QCoreApplication::notify +120 (int (*)(...))QCoreApplication::compressEvent + +Class QCoreApplication + size=16 align=8 + base size=16 base align=8 +QCoreApplication (0x0x7f95edd27000) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f95edd19120) 0 + primary-for QCoreApplication (0x0x7f95edd27000) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f95edd191e0) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f95edd19240) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f95edd19360) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f95edd19480) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f95edd194e0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f95edd19660) 0 empty + +Vtable for QMimeData +QMimeData::_ZTV9QMimeData: 17u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QMimeData) +16 (int (*)(...))QMimeData::metaObject +24 (int (*)(...))QMimeData::qt_metacast +32 (int (*)(...))QMimeData::qt_metacall +40 (int (*)(...))QMimeData::~QMimeData +48 (int (*)(...))QMimeData::~QMimeData +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QMimeData::hasFormat +120 (int (*)(...))QMimeData::formats +128 (int (*)(...))QMimeData::retrieveData + +Class QMimeData + size=16 align=8 + base size=16 base align=8 +QMimeData (0x0x7f95edd27270) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f95edd19600) 0 + primary-for QMimeData (0x0x7f95edd27270) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f95edd19720) 0 empty + +Vtable for QObjectCleanupHandler +QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QObjectCleanupHandler) +16 (int (*)(...))QObjectCleanupHandler::metaObject +24 (int (*)(...))QObjectCleanupHandler::qt_metacast +32 (int (*)(...))QObjectCleanupHandler::qt_metacall +40 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler +48 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QObjectCleanupHandler + size=24 align=8 + base size=24 base align=8 +QObjectCleanupHandler (0x0x7f95edd272d8) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f95edd196c0) 0 + primary-for QObjectCleanupHandler (0x0x7f95edd272d8) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f95edd19960) 0 empty + +Vtable for QSharedMemory +QSharedMemory::_ZTV13QSharedMemory: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QSharedMemory) +16 (int (*)(...))QSharedMemory::metaObject +24 (int (*)(...))QSharedMemory::qt_metacast +32 (int (*)(...))QSharedMemory::qt_metacall +40 (int (*)(...))QSharedMemory::~QSharedMemory +48 (int (*)(...))QSharedMemory::~QSharedMemory +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSharedMemory + size=16 align=8 + base size=16 base align=8 +QSharedMemory (0x0x7f95edd27340) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f95edd19900) 0 + primary-for QSharedMemory (0x0x7f95edd27340) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f95edd19a20) 0 empty + +Vtable for QSignalMapper +QSignalMapper::_ZTV13QSignalMapper: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QSignalMapper) +16 (int (*)(...))QSignalMapper::metaObject +24 (int (*)(...))QSignalMapper::qt_metacast +32 (int (*)(...))QSignalMapper::qt_metacall +40 (int (*)(...))QSignalMapper::~QSignalMapper +48 (int (*)(...))QSignalMapper::~QSignalMapper +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSignalMapper + size=16 align=8 + base size=16 base align=8 +QSignalMapper (0x0x7f95edd273a8) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f95edd199c0) 0 + primary-for QSignalMapper (0x0x7f95edd273a8) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f95edd19ae0) 0 empty + +Vtable for QSocketNotifier +QSocketNotifier::_ZTV15QSocketNotifier: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QSocketNotifier) +16 (int (*)(...))QSocketNotifier::metaObject +24 (int (*)(...))QSocketNotifier::qt_metacast +32 (int (*)(...))QSocketNotifier::qt_metacall +40 (int (*)(...))QSocketNotifier::~QSocketNotifier +48 (int (*)(...))QSocketNotifier::~QSocketNotifier +56 (int (*)(...))QSocketNotifier::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSocketNotifier + size=16 align=8 + base size=16 base align=8 +QSocketNotifier (0x0x7f95edd27410) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f95edd19a80) 0 + primary-for QSocketNotifier (0x0x7f95edd27410) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f95edd19b40) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f95edd19c60) 0 empty + +Vtable for QTimer +QTimer::_ZTV6QTimer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QTimer) +16 (int (*)(...))QTimer::metaObject +24 (int (*)(...))QTimer::qt_metacast +32 (int (*)(...))QTimer::qt_metacall +40 (int (*)(...))QTimer::~QTimer +48 (int (*)(...))QTimer::~QTimer +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QTimer::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QTimer + size=32 align=8 + base size=29 base align=8 +QTimer (0x0x7f95edd27478) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f95edd19c00) 0 + primary-for QTimer (0x0x7f95edd27478) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f95edd19d80) 0 empty + +Vtable for QTranslator +QTranslator::_ZTV11QTranslator: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTranslator) +16 (int (*)(...))QTranslator::metaObject +24 (int (*)(...))QTranslator::qt_metacast +32 (int (*)(...))QTranslator::qt_metacall +40 (int (*)(...))QTranslator::~QTranslator +48 (int (*)(...))QTranslator::~QTranslator +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QTranslator::translate +120 (int (*)(...))QTranslator::isEmpty + +Class QTranslator + size=16 align=8 + base size=16 base align=8 +QTranslator (0x0x7f95edd274e0) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f95edd19d20) 0 + primary-for QTranslator (0x0x7f95edd274e0) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f95edd19de0) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f95edd19f60) 0 + +Vtable for QFactoryInterface +QFactoryInterface::_ZTV17QFactoryInterface: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QFactoryInterface) +16 (int (*)(...))QFactoryInterface::~QFactoryInterface +24 (int (*)(...))QFactoryInterface::~QFactoryInterface +32 (int (*)(...))__cxa_pure_virtual + +Class QFactoryInterface + size=8 align=8 + base size=8 base align=8 +QFactoryInterface (0x0x7f95edead000) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f95edead120) 0 empty + +Vtable for QLibrary +QLibrary::_ZTV8QLibrary: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI8QLibrary) +16 (int (*)(...))QLibrary::metaObject +24 (int (*)(...))QLibrary::qt_metacast +32 (int (*)(...))QLibrary::qt_metacall +40 (int (*)(...))QLibrary::~QLibrary +48 (int (*)(...))QLibrary::~QLibrary +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QLibrary + size=32 align=8 + base size=25 base align=8 +QLibrary (0x0x7f95edd275b0) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f95edead0c0) 0 + primary-for QLibrary (0x0x7f95edd275b0) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f95edead240) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f95edead3c0) 0 empty + +Vtable for QPluginLoader +QPluginLoader::_ZTV13QPluginLoader: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QPluginLoader) +16 (int (*)(...))QPluginLoader::metaObject +24 (int (*)(...))QPluginLoader::qt_metacast +32 (int (*)(...))QPluginLoader::qt_metacall +40 (int (*)(...))QPluginLoader::~QPluginLoader +48 (int (*)(...))QPluginLoader::~QPluginLoader +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QPluginLoader + size=32 align=8 + base size=25 base align=8 +QPluginLoader (0x0x7f95edd27750) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f95edead360) 0 + primary-for QPluginLoader (0x0x7f95edd27750) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f95edead420) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f95edead5a0) 0 empty + +Vtable for QAbstractState +QAbstractState::_ZTV14QAbstractState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QAbstractState) +16 (int (*)(...))QAbstractState::metaObject +24 (int (*)(...))QAbstractState::qt_metacast +32 (int (*)(...))QAbstractState::qt_metacall +40 (int (*)(...))QAbstractState::~QAbstractState +48 (int (*)(...))QAbstractState::~QAbstractState +56 (int (*)(...))QAbstractState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QAbstractState + size=16 align=8 + base size=16 base align=8 +QAbstractState (0x0x7f95edd27820) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f95edead540) 0 + primary-for QAbstractState (0x0x7f95edd27820) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f95edead660) 0 empty + +Vtable for QAbstractTransition +QAbstractTransition::_ZTV19QAbstractTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTransition) +16 (int (*)(...))QAbstractTransition::metaObject +24 (int (*)(...))QAbstractTransition::qt_metacast +32 (int (*)(...))QAbstractTransition::qt_metacall +40 (int (*)(...))QAbstractTransition::~QAbstractTransition +48 (int (*)(...))QAbstractTransition::~QAbstractTransition +56 (int (*)(...))QAbstractTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QAbstractTransition + size=16 align=8 + base size=16 base align=8 +QAbstractTransition (0x0x7f95edd27888) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f95edead600) 0 + primary-for QAbstractTransition (0x0x7f95edd27888) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f95edead720) 0 empty + +Vtable for QEventTransition +QEventTransition::_ZTV16QEventTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QEventTransition) +16 (int (*)(...))QEventTransition::metaObject +24 (int (*)(...))QEventTransition::qt_metacast +32 (int (*)(...))QEventTransition::qt_metacall +40 (int (*)(...))QEventTransition::~QEventTransition +48 (int (*)(...))QEventTransition::~QEventTransition +56 (int (*)(...))QEventTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QEventTransition::eventTest +120 (int (*)(...))QEventTransition::onTransition + +Class QEventTransition + size=16 align=8 + base size=16 base align=8 +QEventTransition (0x0x7f95edd278f0) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f95edd27958) 0 + primary-for QEventTransition (0x0x7f95edd278f0) + QObject (0x0x7f95edead6c0) 0 + primary-for QAbstractTransition (0x0x7f95edd27958) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f95edead7e0) 0 empty + +Vtable for QFinalState +QFinalState::_ZTV11QFinalState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QFinalState) +16 (int (*)(...))QFinalState::metaObject +24 (int (*)(...))QFinalState::qt_metacast +32 (int (*)(...))QFinalState::qt_metacall +40 (int (*)(...))QFinalState::~QFinalState +48 (int (*)(...))QFinalState::~QFinalState +56 (int (*)(...))QFinalState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFinalState::onEntry +120 (int (*)(...))QFinalState::onExit + +Class QFinalState + size=16 align=8 + base size=16 base align=8 +QFinalState (0x0x7f95edd279c0) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f95edd27a28) 0 + primary-for QFinalState (0x0x7f95edd279c0) + QObject (0x0x7f95edead780) 0 + primary-for QAbstractState (0x0x7f95edd27a28) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f95edead8a0) 0 empty + +Vtable for QHistoryState +QHistoryState::_ZTV13QHistoryState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QHistoryState) +16 (int (*)(...))QHistoryState::metaObject +24 (int (*)(...))QHistoryState::qt_metacast +32 (int (*)(...))QHistoryState::qt_metacall +40 (int (*)(...))QHistoryState::~QHistoryState +48 (int (*)(...))QHistoryState::~QHistoryState +56 (int (*)(...))QHistoryState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QHistoryState::onEntry +120 (int (*)(...))QHistoryState::onExit + +Class QHistoryState + size=16 align=8 + base size=16 base align=8 +QHistoryState (0x0x7f95edd27a90) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f95edd27af8) 0 + primary-for QHistoryState (0x0x7f95edd27a90) + QObject (0x0x7f95edead840) 0 + primary-for QAbstractState (0x0x7f95edd27af8) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f95edead960) 0 empty + +Vtable for QSignalTransition +QSignalTransition::_ZTV17QSignalTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QSignalTransition) +16 (int (*)(...))QSignalTransition::metaObject +24 (int (*)(...))QSignalTransition::qt_metacast +32 (int (*)(...))QSignalTransition::qt_metacall +40 (int (*)(...))QSignalTransition::~QSignalTransition +48 (int (*)(...))QSignalTransition::~QSignalTransition +56 (int (*)(...))QSignalTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSignalTransition::eventTest +120 (int (*)(...))QSignalTransition::onTransition + +Class QSignalTransition + size=16 align=8 + base size=16 base align=8 +QSignalTransition (0x0x7f95edd27b60) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f95edd27bc8) 0 + primary-for QSignalTransition (0x0x7f95edd27b60) + QObject (0x0x7f95edead900) 0 + primary-for QAbstractTransition (0x0x7f95edd27bc8) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f95edeada20) 0 empty + +Vtable for QState +QState::_ZTV6QState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QState) +16 (int (*)(...))QState::metaObject +24 (int (*)(...))QState::qt_metacast +32 (int (*)(...))QState::qt_metacall +40 (int (*)(...))QState::~QState +48 (int (*)(...))QState::~QState +56 (int (*)(...))QState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QState::onEntry +120 (int (*)(...))QState::onExit + +Class QState + size=16 align=8 + base size=16 base align=8 +QState (0x0x7f95edd27c30) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f95edd27c98) 0 + primary-for QState (0x0x7f95edd27c30) + QObject (0x0x7f95edead9c0) 0 + primary-for QAbstractState (0x0x7f95edd27c98) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f95edeadb40) 0 empty + +Vtable for QStateMachine::SignalEvent +QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN13QStateMachine11SignalEventE) +16 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent +24 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent + +Class QStateMachine::SignalEvent + size=48 align=8 + base size=48 base align=8 +QStateMachine::SignalEvent (0x0x7f95edd27e38) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f95edeadba0) 0 + primary-for QStateMachine::SignalEvent (0x0x7f95edd27e38) + +Vtable for QStateMachine::WrappedEvent +QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN13QStateMachine12WrappedEventE) +16 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent +24 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent + +Class QStateMachine::WrappedEvent + size=40 align=8 + base size=40 base align=8 +QStateMachine::WrappedEvent (0x0x7f95edd27ea0) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f95edeadc00) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f95edd27ea0) + +Vtable for QStateMachine +QStateMachine::_ZTV13QStateMachine: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QStateMachine) +16 (int (*)(...))QStateMachine::metaObject +24 (int (*)(...))QStateMachine::qt_metacast +32 (int (*)(...))QStateMachine::qt_metacall +40 (int (*)(...))QStateMachine::~QStateMachine +48 (int (*)(...))QStateMachine::~QStateMachine +56 (int (*)(...))QStateMachine::event +64 (int (*)(...))QStateMachine::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QStateMachine::onEntry +120 (int (*)(...))QStateMachine::onExit +128 (int (*)(...))QStateMachine::beginSelectTransitions +136 (int (*)(...))QStateMachine::endSelectTransitions +144 (int (*)(...))QStateMachine::beginMicrostep +152 (int (*)(...))QStateMachine::endMicrostep + +Class QStateMachine + size=16 align=8 + base size=16 base align=8 +QStateMachine (0x0x7f95edd27d00) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f95edd27d68) 0 + primary-for QStateMachine (0x0x7f95edd27d00) + QAbstractState (0x0x7f95edd27dd0) 0 + primary-for QState (0x0x7f95edd27d68) + QObject (0x0x7f95edeadae0) 0 + primary-for QAbstractState (0x0x7f95edd27dd0) + +Vtable for QException +QException::_ZTV10QException: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QException) +16 (int (*)(...))QException::~QException +24 (int (*)(...))QException::~QException +32 (int (*)(...))std::exception::what +40 (int (*)(...))QException::raise +48 (int (*)(...))QException::clone + +Class QException + size=8 align=8 + base size=8 base align=8 +QException (0x0x7f95edd27f08) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f95edeadc60) 0 nearly-empty + primary-for QException (0x0x7f95edd27f08) + +Vtable for QUnhandledException +QUnhandledException::_ZTV19QUnhandledException: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QUnhandledException) +16 (int (*)(...))QUnhandledException::~QUnhandledException +24 (int (*)(...))QUnhandledException::~QUnhandledException +32 (int (*)(...))std::exception::what +40 (int (*)(...))QUnhandledException::raise +48 (int (*)(...))QUnhandledException::clone + +Class QUnhandledException + size=8 align=8 + base size=8 base align=8 +QUnhandledException (0x0x7f95edd27f70) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f95edbb5000) 0 nearly-empty + primary-for QUnhandledException (0x0x7f95edd27f70) + std::exception (0x0x7f95edeadcc0) 0 nearly-empty + primary-for QException (0x0x7f95edbb5000) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f95edeadd20) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f95edeadde0) 0 + +Vtable for QRunnable +QRunnable::_ZTV9QRunnable: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QRunnable) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))QRunnable::~QRunnable +32 (int (*)(...))QRunnable::~QRunnable + +Class QRunnable + size=16 align=8 + base size=12 base align=8 +QRunnable (0x0x7f95edeade40) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f95edeadea0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f95edbb51a0) 0 + QBasicMutex (0x0x7f95edbed000) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f95edbed060) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f95edbed0c0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f95edbed120) 0 + +Vtable for QtPrivate::ResultStoreBase +QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9QtPrivate15ResultStoreBaseE) +16 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase +24 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase + +Class QtPrivate::ResultStoreBase + size=48 align=8 + base size=44 base align=8 +QtPrivate::ResultStoreBase (0x0x7f95edbed2a0) 0 + vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16u) + +Vtable for QFutureInterfaceBase +QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QFutureInterfaceBase) +16 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase +24 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase + +Class QFutureInterfaceBase + size=16 align=8 + base size=16 base align=8 +QFutureInterfaceBase (0x0x7f95edbed360) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f95edbed6c0) 0 empty + +Vtable for QFutureWatcherBase +QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFutureWatcherBase) +16 (int (*)(...))QFutureWatcherBase::metaObject +24 (int (*)(...))QFutureWatcherBase::qt_metacast +32 (int (*)(...))QFutureWatcherBase::qt_metacall +40 (int (*)(...))QFutureWatcherBase::~QFutureWatcherBase +48 (int (*)(...))QFutureWatcherBase::~QFutureWatcherBase +56 (int (*)(...))QFutureWatcherBase::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QFutureWatcherBase::connectNotify +104 (int (*)(...))QFutureWatcherBase::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QFutureWatcherBase + size=16 align=8 + base size=16 base align=8 +QFutureWatcherBase (0x0x7f95edbb5a90) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f95edbed660) 0 + primary-for QFutureWatcherBase (0x0x7f95edbb5a90) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f95edbed7e0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f95edbed840) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f95edbed8a0) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f95edbed900) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f95edbed9c0) 0 empty + +Vtable for QThread +QThread::_ZTV7QThread: 15u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QThread) +16 (int (*)(...))QThread::metaObject +24 (int (*)(...))QThread::qt_metacast +32 (int (*)(...))QThread::qt_metacall +40 (int (*)(...))QThread::~QThread +48 (int (*)(...))QThread::~QThread +56 (int (*)(...))QThread::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QThread::run + +Class QThread + size=16 align=8 + base size=16 base align=8 +QThread (0x0x7f95edbb5e38) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f95edbed960) 0 + primary-for QThread (0x0x7f95edbb5e38) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f95edbeda80) 0 empty + +Vtable for QThreadPool +QThreadPool::_ZTV11QThreadPool: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QThreadPool) +16 (int (*)(...))QThreadPool::metaObject +24 (int (*)(...))QThreadPool::qt_metacast +32 (int (*)(...))QThreadPool::qt_metacall +40 (int (*)(...))QThreadPool::~QThreadPool +48 (int (*)(...))QThreadPool::~QThreadPool +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QThreadPool + size=16 align=8 + base size=16 base align=8 +QThreadPool (0x0x7f95edbb5ea0) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f95edbeda20) 0 + primary-for QThreadPool (0x0x7f95edbb5ea0) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f95edbedae0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f95edbedba0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f95ed9a7180) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f95ed9a71e0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f95ed9a7360) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f95ed9a7300) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f95ed9a74e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f95ed9a75a0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f95ed9a7780) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f95ed9a7900) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f95ed9a7960) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f95ed9a79c0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f95ed9a7a20) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f95ed9a7b40) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f95ed9a7c60) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f95ed9a7d80) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7f95ed9a7ea0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f95ed75a240) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f95ed75a360) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f95ed75a480) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f95ed75a540) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f95ed75a660) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f95ed75a780) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f95ed75a8a0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f95ed75a9c0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f95ed75acc0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f95ed75ae40) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f95ed63f0c0) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f95ed63fae0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f95ed63fc60) 0 empty + +Vtable for QTimeLine +QTimeLine::_ZTV9QTimeLine: 15u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QTimeLine) +16 (int (*)(...))QTimeLine::metaObject +24 (int (*)(...))QTimeLine::qt_metacast +32 (int (*)(...))QTimeLine::qt_metacall +40 (int (*)(...))QTimeLine::~QTimeLine +48 (int (*)(...))QTimeLine::~QTimeLine +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QTimeLine::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QTimeLine::valueForTime + +Class QTimeLine + size=16 align=8 + base size=16 base align=8 +QTimeLine (0x0x7f95ed6657b8) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f95ed63fc00) 0 + primary-for QTimeLine (0x0x7f95ed6657b8) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f95ed63fd20) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f95ed63fcc0) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f95ed63ff60) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f95ed337000) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f95ed665a28) 0 + QVector (0x0x7f95ed3371e0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f95ed337240) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f95ed337360) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f95ed337480) 0 + +Vtable for QXmlStreamEntityResolver +QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QXmlStreamEntityResolver) +16 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver +24 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver +32 (int (*)(...))QXmlStreamEntityResolver::resolveEntity +40 (int (*)(...))QXmlStreamEntityResolver::resolveUndeclaredEntity + +Class QXmlStreamEntityResolver + size=8 align=8 + base size=8 base align=8 +QXmlStreamEntityResolver (0x0x7f95ed3375a0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f95ed337600) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f95ed337720) 0 + +Class QGeoAddress + size=8 align=8 + base size=8 base align=8 +QGeoAddress (0x0x7f95ed337840) 0 + +Class QGeoCoordinate + size=8 align=8 + base size=8 base align=8 +QGeoCoordinate (0x0x7f95ed337ae0) 0 + +Class QGeoShape + size=8 align=8 + base size=8 base align=8 +QGeoShape (0x0x7f95ed337d80) 0 + +Class QGeoAreaMonitorInfo + size=8 align=8 + base size=8 base align=8 +QGeoAreaMonitorInfo (0x0x7f95ed447060) 0 + +Class QGeoPositionInfo + size=8 align=8 + base size=8 base align=8 +QGeoPositionInfo (0x0x7f95ed447120) 0 + +Class QGeoPositionInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoPositionInfoSource::QPrivateSignal (0x0x7f95ed4471e0) 0 empty + +Vtable for QGeoPositionInfoSource +QGeoPositionInfoSource::_ZTV22QGeoPositionInfoSource: 23u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QGeoPositionInfoSource) +16 (int (*)(...))QGeoPositionInfoSource::metaObject +24 (int (*)(...))QGeoPositionInfoSource::qt_metacast +32 (int (*)(...))QGeoPositionInfoSource::qt_metacall +40 (int (*)(...))QGeoPositionInfoSource::~QGeoPositionInfoSource +48 (int (*)(...))QGeoPositionInfoSource::~QGeoPositionInfoSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoPositionInfoSource::setUpdateInterval +120 (int (*)(...))QGeoPositionInfoSource::setPreferredPositioningMethods +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual + +Class QGeoPositionInfoSource + size=24 align=8 + base size=24 base align=8 +QGeoPositionInfoSource (0x0x7f95ed665d00) 0 + vptr=((& QGeoPositionInfoSource::_ZTV22QGeoPositionInfoSource) + 16u) + QObject (0x0x7f95ed447180) 0 + primary-for QGeoPositionInfoSource (0x0x7f95ed665d00) + +Class QGeoAreaMonitorSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoAreaMonitorSource::QPrivateSignal (0x0x7f95ed447360) 0 empty + +Vtable for QGeoAreaMonitorSource +QGeoAreaMonitorSource::_ZTV21QGeoAreaMonitorSource: 23u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QGeoAreaMonitorSource) +16 (int (*)(...))QGeoAreaMonitorSource::metaObject +24 (int (*)(...))QGeoAreaMonitorSource::qt_metacast +32 (int (*)(...))QGeoAreaMonitorSource::qt_metacall +40 (int (*)(...))QGeoAreaMonitorSource::~QGeoAreaMonitorSource +48 (int (*)(...))QGeoAreaMonitorSource::~QGeoAreaMonitorSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoAreaMonitorSource::setPositionInfoSource +120 (int (*)(...))QGeoAreaMonitorSource::positionInfoSource +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual + +Class QGeoAreaMonitorSource + size=24 align=8 + base size=24 base align=8 +QGeoAreaMonitorSource (0x0x7f95ed665e38) 0 + vptr=((& QGeoAreaMonitorSource::_ZTV21QGeoAreaMonitorSource) + 16u) + QObject (0x0x7f95ed447300) 0 + primary-for QGeoAreaMonitorSource (0x0x7f95ed665e38) + +Class QGeoCircle + size=8 align=8 + base size=8 base align=8 +QGeoCircle (0x0x7f95ed665ea0) 0 + QGeoShape (0x0x7f95ed4473c0) 0 + +Class QGeoLocation + size=8 align=8 + base size=8 base align=8 +QGeoLocation (0x0x7f95ed447600) 0 + +Class QGeoSatelliteInfo + size=8 align=8 + base size=8 base align=8 +QGeoSatelliteInfo (0x0x7f95ed4478a0) 0 + +Class QGeoSatelliteInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoSatelliteInfoSource::QPrivateSignal (0x0x7f95ed447960) 0 empty + +Vtable for QGeoSatelliteInfoSource +QGeoSatelliteInfoSource::_ZTV23QGeoSatelliteInfoSource: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QGeoSatelliteInfoSource) +16 (int (*)(...))QGeoSatelliteInfoSource::metaObject +24 (int (*)(...))QGeoSatelliteInfoSource::qt_metacast +32 (int (*)(...))QGeoSatelliteInfoSource::qt_metacall +40 (int (*)(...))QGeoSatelliteInfoSource::~QGeoSatelliteInfoSource +48 (int (*)(...))QGeoSatelliteInfoSource::~QGeoSatelliteInfoSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoSatelliteInfoSource::setUpdateInterval +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual + +Class QGeoSatelliteInfoSource + size=24 align=8 + base size=24 base align=8 +QGeoSatelliteInfoSource (0x0x7f95ed060000) 0 + vptr=((& QGeoSatelliteInfoSource::_ZTV23QGeoSatelliteInfoSource) + 16u) + QObject (0x0x7f95ed447900) 0 + primary-for QGeoSatelliteInfoSource (0x0x7f95ed060000) + +Vtable for QGeoPositionInfoSourceFactory +QGeoPositionInfoSourceFactory::_ZTV29QGeoPositionInfoSourceFactory: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI29QGeoPositionInfoSourceFactory) +16 (int (*)(...))QGeoPositionInfoSourceFactory::~QGeoPositionInfoSourceFactory +24 (int (*)(...))QGeoPositionInfoSourceFactory::~QGeoPositionInfoSourceFactory +32 (int (*)(...))__cxa_pure_virtual +40 (int (*)(...))__cxa_pure_virtual +48 (int (*)(...))__cxa_pure_virtual + +Class QGeoPositionInfoSourceFactory + size=8 align=8 + base size=8 base align=8 +QGeoPositionInfoSourceFactory (0x0x7f95ed447a20) 0 nearly-empty + vptr=((& QGeoPositionInfoSourceFactory::_ZTV29QGeoPositionInfoSourceFactory) + 16u) + +Class QGeoRectangle + size=8 align=8 + base size=8 base align=8 +QGeoRectangle (0x0x7f95ed060068) 0 + QGeoShape (0x0x7f95ed447ae0) 0 + +Class QNmeaPositionInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNmeaPositionInfoSource::QPrivateSignal (0x0x7f95ed447e40) 0 empty + +Vtable for QNmeaPositionInfoSource +QNmeaPositionInfoSource::_ZTV23QNmeaPositionInfoSource: 24u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QNmeaPositionInfoSource) +16 (int (*)(...))QNmeaPositionInfoSource::metaObject +24 (int (*)(...))QNmeaPositionInfoSource::qt_metacast +32 (int (*)(...))QNmeaPositionInfoSource::qt_metacall +40 (int (*)(...))QNmeaPositionInfoSource::~QNmeaPositionInfoSource +48 (int (*)(...))QNmeaPositionInfoSource::~QNmeaPositionInfoSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QNmeaPositionInfoSource::setUpdateInterval +120 (int (*)(...))QGeoPositionInfoSource::setPreferredPositioningMethods +128 (int (*)(...))QNmeaPositionInfoSource::lastKnownPosition +136 (int (*)(...))QNmeaPositionInfoSource::supportedPositioningMethods +144 (int (*)(...))QNmeaPositionInfoSource::minimumUpdateInterval +152 (int (*)(...))QNmeaPositionInfoSource::error +160 (int (*)(...))QNmeaPositionInfoSource::startUpdates +168 (int (*)(...))QNmeaPositionInfoSource::stopUpdates +176 (int (*)(...))QNmeaPositionInfoSource::requestUpdate +184 (int (*)(...))QNmeaPositionInfoSource::parsePosInfoFromNmeaData + +Class QNmeaPositionInfoSource + size=32 align=8 + base size=32 base align=8 +QNmeaPositionInfoSource (0x0x7f95ed060138) 0 + vptr=((& QNmeaPositionInfoSource::_ZTV23QNmeaPositionInfoSource) + 16u) + QGeoPositionInfoSource (0x0x7f95ed0601a0) 0 + primary-for QNmeaPositionInfoSource (0x0x7f95ed060138) + QObject (0x0x7f95ed447de0) 0 + primary-for QGeoPositionInfoSource (0x0x7f95ed0601a0) + diff --git a/tests/auto/bic/data/QtPositioning.5.4.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtPositioning.5.4.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..3746cf7 --- /dev/null +++ b/tests/auto/bic/data/QtPositioning.5.4.0.linux-gcc-amd64.txt @@ -0,0 +1,3854 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7fb610c07060) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7fb610c070c0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7fb610c48c60) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7fb610c48cc0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7fb610bdc958) 0 empty + std::input_iterator_tag (0x0x7fb610c48d20) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7fb610bdc9c0) 0 empty + std::forward_iterator_tag (0x0x7fb610bdca28) 0 empty + std::input_iterator_tag (0x0x7fb610c48d80) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7fb610bdca90) 0 empty + std::bidirectional_iterator_tag (0x0x7fb610bdcaf8) 0 empty + std::forward_iterator_tag (0x0x7fb610bdcb60) 0 empty + std::input_iterator_tag (0x0x7fb610c48de0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7fb610c79960) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7fb610c79ba0) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7fb610c79c60) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7fb610c79cc0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7fb610c79d80) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7fb610c79de0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7fb610d642a0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7fb610d64300) 0 + +Vtable for std::exception +std::exception::_ZTVSt9exception: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt9exception) +16 (int (*)(...))std::exception::~exception +24 (int (*)(...))std::exception::~exception +32 (int (*)(...))std::exception::what + +Class std::exception + size=8 align=8 + base size=8 base align=8 +std::exception (0x0x7fb610d64360) 0 nearly-empty + vptr=((& std::exception::_ZTVSt9exception) + 16u) + +Vtable for std::bad_exception +std::bad_exception::_ZTVSt13bad_exception: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt13bad_exception) +16 (int (*)(...))std::bad_exception::~bad_exception +24 (int (*)(...))std::bad_exception::~bad_exception +32 (int (*)(...))std::bad_exception::what + +Class std::bad_exception + size=8 align=8 + base size=8 base align=8 +std::bad_exception (0x0x7fb610bdcea0) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7fb610d643c0) 0 nearly-empty + primary-for std::bad_exception (0x0x7fb610bdcea0) + +Vtable for std::bad_alloc +std::bad_alloc::_ZTVSt9bad_alloc: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt9bad_alloc) +16 (int (*)(...))std::bad_alloc::~bad_alloc +24 (int (*)(...))std::bad_alloc::~bad_alloc +32 (int (*)(...))std::bad_alloc::what + +Class std::bad_alloc + size=8 align=8 + base size=8 base align=8 +std::bad_alloc (0x0x7fb610bdcf08) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7fb610d64420) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fb610bdcf08) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7fb610d64480) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7fb60fb587e0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7fb60fb58840) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7fb60fb58a20) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7fb60f8c8300) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7fb60f8c8360) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7fb60f8c83c0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7fb60f8c8420) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7fb60f8c8540) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7fb60f8cd680) 0 + QAtomicInteger (0x0x7fb60f8cd6e8) 0 + QBasicAtomicInteger (0x0x7fb60f70e060) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7fb60f4e4180) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7fb60f1ae0c0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7fb60f452820) 0 + QGenericArgument (0x0x7fb60f1ae120) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7fb60f1ae2a0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7fb60f1ae3c0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7fb60f1ae600) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7fb60f1ae660) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7fb60f1ae780) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7fb60f1ae7e0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7fb60f1aeae0) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7fb60f1aee40) 0 + +Vtable for __cxxabiv1::__forced_unwind +__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE) +16 (int (*)(...))__cxxabiv1::__forced_unwind::~__forced_unwind +24 (int (*)(...))__cxxabiv1::__forced_unwind::~__forced_unwind +32 (int (*)(...))__cxa_pure_virtual + +Class __cxxabiv1::__forced_unwind + size=8 align=8 + base size=8 base align=8 +__cxxabiv1::__forced_unwind (0x0x7fb60f1aeea0) 0 nearly-empty + vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16u) + +Class sched_param + size=4 align=4 + base size=4 base align=4 +sched_param (0x0x7fb60efe4960) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7fb60efe49c0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7fb60efe4a80) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7fb60efe4ae0) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7fb60efe4b40) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7fb60efe4ba0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7fb60efe4cc0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7fb60efe4d20) 0 + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7fb60f0ed4e0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7fb60f0ed540) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7fb60f0ed6c0) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7fb60f0ed7e0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7fb60f0ed960) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7fb60f0eda20) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7fb60f0ed9c0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7fb60f0edba0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7fb60f0ede40) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7fb60ea19060) 0 + +Vtable for std::locale::facet +std::locale::facet::_ZTVNSt6locale5facetE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6locale5facetE) +16 (int (*)(...))std::locale::facet::~facet +24 (int (*)(...))std::locale::facet::~facet + +Class std::locale::facet + size=16 align=8 + base size=12 base align=8 +std::locale::facet (0x0x7fb60ea190c0) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7fb60ea19120) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7fb60ea19180) 0 + +Vtable for std::ios_base::failure +std::ios_base::failure::_ZTVNSt8ios_base7failureE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt8ios_base7failureE) +16 (int (*)(...))std::ios_base::failure::~failure +24 (int (*)(...))std::ios_base::failure::~failure +32 (int (*)(...))std::ios_base::failure::what + +Class std::ios_base::failure + size=16 align=8 + base size=16 base align=8 +std::ios_base::failure (0x0x7fb60ead6000) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureE) + 16u) + std::exception (0x0x7fb60ea195a0) 0 nearly-empty + primary-for std::ios_base::failure (0x0x7fb60ead6000) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7fb60ea19600) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7fb60ea19660) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7fb60ea196c0) 0 empty + +Vtable for std::ios_base +std::ios_base::_ZTVSt8ios_base: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt8ios_base) +16 (int (*)(...))std::ios_base::~ios_base +24 (int (*)(...))std::ios_base::~ios_base + +Class std::ios_base + size=216 align=8 + base size=216 base align=8 +std::ios_base (0x0x7fb60ea19540) 0 + vptr=((& std::ios_base::_ZTVSt8ios_base) + 16u) + +Class std::ctype_base + size=1 align=1 + base size=0 base align=1 +std::ctype_base (0x0x7fb60ea19840) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7fb60ea19f00) 0 empty + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSo: 2u entries +0 ((& std::basic_ostream::_ZTVSo) + 24u) +8 ((& std::basic_ostream::_ZTVSo) + 64u) + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2u entries +0 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64u) + +VTT for std::basic_istream +std::basic_istream::_ZTTSi: 2u entries +0 ((& std::basic_istream::_ZTVSi) + 24u) +8 ((& std::basic_istream::_ZTVSi) + 64u) + +VTT for std::basic_istream +std::basic_istream::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2u entries +0 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64u) + +Construction vtable for std::basic_istream (0x0x7fb60e693e38 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd0_Si: 10u entries +0 24u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISi) +24 (int (*)(...))std::basic_istream<_CharT, _Traits>::~basic_istream > +32 (int (*)(...))std::basic_istream<_CharT, _Traits>::~basic_istream > +40 18446744073709551592u +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISi) +64 (int (*)(...))std::basic_istream::_ZTv0_n24_NSiD1Ev +72 (int (*)(...))std::basic_istream::_ZTv0_n24_NSiD0Ev + +Construction vtable for std::basic_ostream (0x0x7fb60e693f08 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd16_So: 10u entries +0 8u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISo) +24 (int (*)(...))std::basic_ostream<_CharT, _Traits>::~basic_ostream > +32 (int (*)(...))std::basic_ostream<_CharT, _Traits>::~basic_ostream > +40 18446744073709551608u +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISo) +64 (int (*)(...))std::basic_ostream::_ZTv0_n24_NSoD1Ev +72 (int (*)(...))std::basic_ostream::_ZTv0_n24_NSoD0Ev + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSd: 7u entries +0 ((& std::basic_iostream::_ZTVSd) + 24u) +8 ((& std::basic_iostream::_ZTCSd0_Si) + 24u) +16 ((& std::basic_iostream::_ZTCSd0_Si) + 64u) +24 ((& std::basic_iostream::_ZTCSd16_So) + 24u) +32 ((& std::basic_iostream::_ZTCSd16_So) + 64u) +40 ((& std::basic_iostream::_ZTVSd) + 104u) +48 ((& std::basic_iostream::_ZTVSd) + 64u) + +Construction vtable for std::basic_istream (0x0x7fb60e6933a8 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10u entries +0 24u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +24 (int (*)(...))std::basic_istream<_CharT, _Traits>::~basic_istream > +32 (int (*)(...))std::basic_istream<_CharT, _Traits>::~basic_istream > +40 18446744073709551592u +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +64 (int (*)(...))std::basic_istream::_ZTv0_n24_NSt13basic_istreamIwSt11char_traitsIwEED1Ev +72 (int (*)(...))std::basic_istream::_ZTv0_n24_NSt13basic_istreamIwSt11char_traitsIwEED0Ev + +Construction vtable for std::basic_ostream (0x0x7fb60e6934e0 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10u entries +0 8u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +24 (int (*)(...))std::basic_ostream<_CharT, _Traits>::~basic_ostream > +32 (int (*)(...))std::basic_ostream<_CharT, _Traits>::~basic_ostream > +40 18446744073709551608u +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +64 (int (*)(...))std::basic_ostream::_ZTv0_n24_NSt13basic_ostreamIwSt11char_traitsIwEED1Ev +72 (int (*)(...))std::basic_ostream::_ZTv0_n24_NSt13basic_ostreamIwSt11char_traitsIwEED0Ev + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7u entries +0 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24u) +16 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64u) +24 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24u) +32 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64u) +40 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104u) +48 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64u) + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7fb60e6e1300) 0 + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7fb60e6e1660) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7fb60e6e1600) 0 + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7fb60e6e1b40) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7fb60e5678a0) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7fb60e766750) 0 + std::iterator (0x0x7fb60e567960) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7fb60e7667b8) 0 + std::_Bit_iterator_base (0x0x7fb60e766820) 0 + std::iterator (0x0x7fb60e5679c0) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7fb60e766888) 0 + std::_Bit_iterator_base (0x0x7fb60e7668f0) 0 + std::iterator (0x0x7fb60e567a20) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7fb60e567de0) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7fb60e34d240) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7fb60e34d300) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7fb60e34d3c0) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7fb60e34d7e0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7fb60e34db40) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7fb60e34dc60) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7fb60e146480) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7fb60e146660) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7fb60e146720) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7fb60df0ba80) 0 + +Vtable for QObjectData +QObjectData::_ZTV11QObjectData: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QObjectData) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))__cxa_pure_virtual + +Class QObjectData + size=48 align=8 + base size=48 base align=8 +QObjectData (0x0x7fb60df0bc00) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7fb60df0bde0) 0 empty + +Vtable for QObject +QObject::_ZTV7QObject: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QObject) +16 (int (*)(...))QObject::metaObject +24 (int (*)(...))QObject::qt_metacast +32 (int (*)(...))QObject::qt_metacall +40 (int (*)(...))QObject::~QObject +48 (int (*)(...))QObject::~QObject +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QObject + size=16 align=8 + base size=16 base align=8 +QObject (0x0x7fb60df0bd80) 0 + vptr=((& QObject::_ZTV7QObject) + 16u) + +Vtable for QObjectUserData +QObjectUserData::_ZTV15QObjectUserData: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QObjectUserData) +16 (int (*)(...))QObjectUserData::~QObjectUserData +24 (int (*)(...))QObjectUserData::~QObjectUserData + +Class QObjectUserData + size=8 align=8 + base size=8 base align=8 +QObjectUserData (0x0x7fb60dbea120) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7fb60dbea180) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7fb60dbea240) 0 empty + +Vtable for QAbstractAnimation +QAbstractAnimation::_ZTV18QAbstractAnimation: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractAnimation) +16 (int (*)(...))QAbstractAnimation::metaObject +24 (int (*)(...))QAbstractAnimation::qt_metacast +32 (int (*)(...))QAbstractAnimation::qt_metacall +40 (int (*)(...))QAbstractAnimation::~QAbstractAnimation +48 (int (*)(...))QAbstractAnimation::~QAbstractAnimation +56 (int (*)(...))QAbstractAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QAbstractAnimation + size=16 align=8 + base size=16 base align=8 +QAbstractAnimation (0x0x7fb60df5f5b0) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7fb60dbea1e0) 0 + primary-for QAbstractAnimation (0x0x7fb60df5f5b0) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7fb60dbea300) 0 empty + +Vtable for QAnimationDriver +QAnimationDriver::_ZTV16QAnimationDriver: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QAnimationDriver) +16 (int (*)(...))QAnimationDriver::metaObject +24 (int (*)(...))QAnimationDriver::qt_metacast +32 (int (*)(...))QAnimationDriver::qt_metacall +40 (int (*)(...))QAnimationDriver::~QAnimationDriver +48 (int (*)(...))QAnimationDriver::~QAnimationDriver +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAnimationDriver::advance +120 (int (*)(...))QAnimationDriver::elapsed +128 (int (*)(...))QAnimationDriver::start +136 (int (*)(...))QAnimationDriver::stop + +Class QAnimationDriver + size=16 align=8 + base size=16 base align=8 +QAnimationDriver (0x0x7fb60df5f618) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7fb60dbea2a0) 0 + primary-for QAnimationDriver (0x0x7fb60df5f618) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7fb60dbea3c0) 0 empty + +Vtable for QAnimationGroup +QAnimationGroup::_ZTV15QAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAnimationGroup) +16 (int (*)(...))QAnimationGroup::metaObject +24 (int (*)(...))QAnimationGroup::qt_metacast +32 (int (*)(...))QAnimationGroup::qt_metacall +40 (int (*)(...))QAnimationGroup::~QAnimationGroup +48 (int (*)(...))QAnimationGroup::~QAnimationGroup +56 (int (*)(...))QAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QAnimationGroup + size=16 align=8 + base size=16 base align=8 +QAnimationGroup (0x0x7fb60df5f680) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7fb60df5f6e8) 0 + primary-for QAnimationGroup (0x0x7fb60df5f680) + QObject (0x0x7fb60dbea360) 0 + primary-for QAbstractAnimation (0x0x7fb60df5f6e8) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7fb60dbea480) 0 empty + +Vtable for QParallelAnimationGroup +QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QParallelAnimationGroup) +16 (int (*)(...))QParallelAnimationGroup::metaObject +24 (int (*)(...))QParallelAnimationGroup::qt_metacast +32 (int (*)(...))QParallelAnimationGroup::qt_metacall +40 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup +48 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup +56 (int (*)(...))QParallelAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QParallelAnimationGroup::duration +120 (int (*)(...))QParallelAnimationGroup::updateCurrentTime +128 (int (*)(...))QParallelAnimationGroup::updateState +136 (int (*)(...))QParallelAnimationGroup::updateDirection + +Class QParallelAnimationGroup + size=16 align=8 + base size=16 base align=8 +QParallelAnimationGroup (0x0x7fb60df5f750) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7fb60df5f7b8) 0 + primary-for QParallelAnimationGroup (0x0x7fb60df5f750) + QAbstractAnimation (0x0x7fb60df5f820) 0 + primary-for QAnimationGroup (0x0x7fb60df5f7b8) + QObject (0x0x7fb60dbea420) 0 + primary-for QAbstractAnimation (0x0x7fb60df5f820) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7fb60dbea540) 0 empty + +Vtable for QPauseAnimation +QPauseAnimation::_ZTV15QPauseAnimation: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QPauseAnimation) +16 (int (*)(...))QPauseAnimation::metaObject +24 (int (*)(...))QPauseAnimation::qt_metacast +32 (int (*)(...))QPauseAnimation::qt_metacall +40 (int (*)(...))QPauseAnimation::~QPauseAnimation +48 (int (*)(...))QPauseAnimation::~QPauseAnimation +56 (int (*)(...))QPauseAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QPauseAnimation::duration +120 (int (*)(...))QPauseAnimation::updateCurrentTime +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QPauseAnimation + size=16 align=8 + base size=16 base align=8 +QPauseAnimation (0x0x7fb60df5f888) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7fb60df5f8f0) 0 + primary-for QPauseAnimation (0x0x7fb60df5f888) + QObject (0x0x7fb60dbea4e0) 0 + primary-for QAbstractAnimation (0x0x7fb60df5f8f0) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7fb60dbea720) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7fb60dbea900) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7fb60dbea9c0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7fb60dbead20) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7fb60dbeacc0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7fb60dbead80) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7fb60da72300) 0 empty + +Vtable for QIODevice +QIODevice::_ZTV9QIODevice: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QIODevice) +16 (int (*)(...))QIODevice::metaObject +24 (int (*)(...))QIODevice::qt_metacast +32 (int (*)(...))QIODevice::qt_metacall +40 (int (*)(...))QIODevice::~QIODevice +48 (int (*)(...))QIODevice::~QIODevice +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QIODevice::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QIODevice::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))__cxa_pure_virtual +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))__cxa_pure_virtual + +Class QIODevice + size=16 align=8 + base size=16 base align=8 +QIODevice (0x0x7fb60dacc138) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7fb60da722a0) 0 + primary-for QIODevice (0x0x7fb60dacc138) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7fb60da72420) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7fb60da724e0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7fb60da72660) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7fb60da72600) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7fb60dacc340) 0 + QList (0x0x7fb60dacc3a8) 0 + QListSpecialMethods (0x0x7fb60da72840) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7fb60da72b40) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7fb60da72c00) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7fb60da72ba0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7fb60da72c60) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7fb60da72ae0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7fb60da72f60) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7fb60d8f6060) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7fb60d8f6000) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7fb60d8f6120) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7fb60d8f60c0) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7fb60d8f6cc0) 0 empty + +Vtable for QVariantAnimation +QVariantAnimation::_ZTV17QVariantAnimation: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QVariantAnimation) +16 (int (*)(...))QVariantAnimation::metaObject +24 (int (*)(...))QVariantAnimation::qt_metacast +32 (int (*)(...))QVariantAnimation::qt_metacall +40 (int (*)(...))QVariantAnimation::~QVariantAnimation +48 (int (*)(...))QVariantAnimation::~QVariantAnimation +56 (int (*)(...))QVariantAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QVariantAnimation::duration +120 (int (*)(...))QVariantAnimation::updateCurrentTime +128 (int (*)(...))QVariantAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection +144 (int (*)(...))QVariantAnimation::updateCurrentValue +152 (int (*)(...))QVariantAnimation::interpolated + +Class QVariantAnimation + size=16 align=8 + base size=16 base align=8 +QVariantAnimation (0x0x7fb60dacce38) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7fb60daccea0) 0 + primary-for QVariantAnimation (0x0x7fb60dacce38) + QObject (0x0x7fb60d8f6c60) 0 + primary-for QAbstractAnimation (0x0x7fb60daccea0) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7fb60d8f6d80) 0 empty + +Vtable for QPropertyAnimation +QPropertyAnimation::_ZTV18QPropertyAnimation: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QPropertyAnimation) +16 (int (*)(...))QPropertyAnimation::metaObject +24 (int (*)(...))QPropertyAnimation::qt_metacast +32 (int (*)(...))QPropertyAnimation::qt_metacall +40 (int (*)(...))QPropertyAnimation::~QPropertyAnimation +48 (int (*)(...))QPropertyAnimation::~QPropertyAnimation +56 (int (*)(...))QPropertyAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QVariantAnimation::duration +120 (int (*)(...))QVariantAnimation::updateCurrentTime +128 (int (*)(...))QPropertyAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection +144 (int (*)(...))QPropertyAnimation::updateCurrentValue +152 (int (*)(...))QVariantAnimation::interpolated + +Class QPropertyAnimation + size=16 align=8 + base size=16 base align=8 +QPropertyAnimation (0x0x7fb60daccf70) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7fb60dacc068) 0 + primary-for QPropertyAnimation (0x0x7fb60daccf70) + QAbstractAnimation (0x0x7fb60daccc98) 0 + primary-for QVariantAnimation (0x0x7fb60dacc068) + QObject (0x0x7fb60d8f6d20) 0 + primary-for QAbstractAnimation (0x0x7fb60daccc98) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7fb60d8f6e40) 0 empty + +Vtable for QSequentialAnimationGroup +QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QSequentialAnimationGroup) +16 (int (*)(...))QSequentialAnimationGroup::metaObject +24 (int (*)(...))QSequentialAnimationGroup::qt_metacast +32 (int (*)(...))QSequentialAnimationGroup::qt_metacall +40 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup +48 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup +56 (int (*)(...))QSequentialAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSequentialAnimationGroup::duration +120 (int (*)(...))QSequentialAnimationGroup::updateCurrentTime +128 (int (*)(...))QSequentialAnimationGroup::updateState +136 (int (*)(...))QSequentialAnimationGroup::updateDirection + +Class QSequentialAnimationGroup + size=16 align=8 + base size=16 base align=8 +QSequentialAnimationGroup (0x0x7fb60daccd00) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7fb60daccd68) 0 + primary-for QSequentialAnimationGroup (0x0x7fb60daccd00) + QAbstractAnimation (0x0x7fb60d5a6000) 0 + primary-for QAnimationGroup (0x0x7fb60daccd68) + QObject (0x0x7fb60d8f6de0) 0 + primary-for QAbstractAnimation (0x0x7fb60d5a6000) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7fb60d8f6f00) 0 + +Vtable for QTextCodec +QTextCodec::_ZTV10QTextCodec: 9u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QTextCodec) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))QTextCodec::aliases +32 (int (*)(...))__cxa_pure_virtual +40 (int (*)(...))__cxa_pure_virtual +48 (int (*)(...))__cxa_pure_virtual +56 (int (*)(...))QTextCodec::~QTextCodec +64 (int (*)(...))QTextCodec::~QTextCodec + +Class QTextCodec + size=8 align=8 + base size=8 base align=8 +QTextCodec (0x0x7fb60d8f6ea0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7fb60d5c2060) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7fb60d5c20c0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7fb60d5c2120) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7fb60d5c2300) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7fb60d5c2a80) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7fb60d5c2ba0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7fb60d5c2cc0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7fb60d5c2e40) 0 empty + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7fb60d5c2f00) 0 empty + +Vtable for QBuffer +QBuffer::_ZTV7QBuffer: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QBuffer) +16 (int (*)(...))QBuffer::metaObject +24 (int (*)(...))QBuffer::qt_metacast +32 (int (*)(...))QBuffer::qt_metacall +40 (int (*)(...))QBuffer::~QBuffer +48 (int (*)(...))QBuffer::~QBuffer +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QBuffer::connectNotify +104 (int (*)(...))QBuffer::disconnectNotify +112 (int (*)(...))QIODevice::isSequential +120 (int (*)(...))QBuffer::open +128 (int (*)(...))QBuffer::close +136 (int (*)(...))QBuffer::pos +144 (int (*)(...))QBuffer::size +152 (int (*)(...))QBuffer::seek +160 (int (*)(...))QBuffer::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QBuffer::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBuffer::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBuffer::writeData + +Class QBuffer + size=16 align=8 + base size=16 base align=8 +QBuffer (0x0x7fb60d5a62d8) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7fb60d5a6340) 0 + primary-for QBuffer (0x0x7fb60d5a62d8) + QObject (0x0x7fb60d5c2ea0) 0 + primary-for QIODevice (0x0x7fb60d5a6340) + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7fb60d5c2f60) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7fb60d3c92a0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7fb60d3c9300) 0 + +Vtable for QTextStream +QTextStream::_ZTV11QTextStream: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTextStream) +16 (int (*)(...))QTextStream::~QTextStream +24 (int (*)(...))QTextStream::~QTextStream + +Class QTextStream + size=16 align=8 + base size=16 base align=8 +QTextStream (0x0x7fb60d3c93c0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7fb60d3c9660) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7fb60d3c98a0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7fb60d3c9f00) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7fb60d3c9ea0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7fb60d18a060) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7fb60d18a120) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7fb60d18a1e0) 0 empty + +Vtable for QFileDevice +QFileDevice::_ZTV11QFileDevice: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QFileDevice) +16 (int (*)(...))QFileDevice::metaObject +24 (int (*)(...))QFileDevice::qt_metacast +32 (int (*)(...))QFileDevice::qt_metacall +40 (int (*)(...))QFileDevice::~QFileDevice +48 (int (*)(...))QFileDevice::~QFileDevice +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFileDevice::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QFileDevice::fileName +248 (int (*)(...))QFileDevice::resize +256 (int (*)(...))QFileDevice::permissions +264 (int (*)(...))QFileDevice::setPermissions + +Class QFileDevice + size=16 align=8 + base size=16 base align=8 +QFileDevice (0x0x7fb60d5a67b8) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7fb60d5a6820) 0 + primary-for QFileDevice (0x0x7fb60d5a67b8) + QObject (0x0x7fb60d18a180) 0 + primary-for QIODevice (0x0x7fb60d5a6820) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7fb60d18a360) 0 empty + +Vtable for QFile +QFile::_ZTV5QFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI5QFile) +16 (int (*)(...))QFile::metaObject +24 (int (*)(...))QFile::qt_metacast +32 (int (*)(...))QFile::qt_metacall +40 (int (*)(...))QFile::~QFile +48 (int (*)(...))QFile::~QFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QFile::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFile::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QFile::fileName +248 (int (*)(...))QFile::resize +256 (int (*)(...))QFile::permissions +264 (int (*)(...))QFile::setPermissions + +Class QFile + size=16 align=8 + base size=16 base align=8 +QFile (0x0x7fb60d5a6958) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7fb60d5a69c0) 0 + primary-for QFile (0x0x7fb60d5a6958) + QIODevice (0x0x7fb60d5a6a28) 0 + primary-for QFileDevice (0x0x7fb60d5a69c0) + QObject (0x0x7fb60d18a300) 0 + primary-for QIODevice (0x0x7fb60d5a6a28) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7fb60d18a480) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7fb60d18a720) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7fb60d18aa20) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7fb60d18ac00) 0 empty + +Vtable for QFileSelector +QFileSelector::_ZTV13QFileSelector: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QFileSelector) +16 (int (*)(...))QFileSelector::metaObject +24 (int (*)(...))QFileSelector::qt_metacast +32 (int (*)(...))QFileSelector::qt_metacall +40 (int (*)(...))QFileSelector::~QFileSelector +48 (int (*)(...))QFileSelector::~QFileSelector +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QFileSelector + size=16 align=8 + base size=16 base align=8 +QFileSelector (0x0x7fb60d5a6f08) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7fb60d18aba0) 0 + primary-for QFileSelector (0x0x7fb60d5a6f08) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7fb60d18acc0) 0 empty + +Vtable for QFileSystemWatcher +QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFileSystemWatcher) +16 (int (*)(...))QFileSystemWatcher::metaObject +24 (int (*)(...))QFileSystemWatcher::qt_metacast +32 (int (*)(...))QFileSystemWatcher::qt_metacall +40 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher +48 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QFileSystemWatcher + size=16 align=8 + base size=16 base align=8 +QFileSystemWatcher (0x0x7fb60d5a6f70) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7fb60d18ac60) 0 + primary-for QFileSystemWatcher (0x0x7fb60d5a6f70) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7fb60d18ad20) 0 + +Class QLoggingCategory::AtomicBools + size=3 align=1 + base size=3 base align=1 +QLoggingCategory::AtomicBools (0x0x7fb60d18aea0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7fb60d18ae40) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7fb60d318060) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7fb60d318240) 0 empty + +Vtable for QProcess +QProcess::_ZTV8QProcess: 31u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI8QProcess) +16 (int (*)(...))QProcess::metaObject +24 (int (*)(...))QProcess::qt_metacast +32 (int (*)(...))QProcess::qt_metacall +40 (int (*)(...))QProcess::~QProcess +48 (int (*)(...))QProcess::~QProcess +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QProcess::isSequential +120 (int (*)(...))QProcess::open +128 (int (*)(...))QProcess::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QProcess::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QProcess::bytesAvailable +184 (int (*)(...))QProcess::bytesToWrite +192 (int (*)(...))QProcess::canReadLine +200 (int (*)(...))QProcess::waitForReadyRead +208 (int (*)(...))QProcess::waitForBytesWritten +216 (int (*)(...))QProcess::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QProcess::writeData +240 (int (*)(...))QProcess::setupChildProcess + +Class QProcess + size=16 align=8 + base size=16 base align=8 +QProcess (0x0x7fb60d306138) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7fb60d3061a0) 0 + primary-for QProcess (0x0x7fb60d306138) + QObject (0x0x7fb60d3181e0) 0 + primary-for QIODevice (0x0x7fb60d3061a0) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7fb60d3182a0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7fb60d318420) 0 empty + +Vtable for QSaveFile +QSaveFile::_ZTV9QSaveFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QSaveFile) +16 (int (*)(...))QSaveFile::metaObject +24 (int (*)(...))QSaveFile::qt_metacast +32 (int (*)(...))QSaveFile::qt_metacall +40 (int (*)(...))QSaveFile::~QSaveFile +48 (int (*)(...))QSaveFile::~QSaveFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QSaveFile::open +128 (int (*)(...))QSaveFile::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFileDevice::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QSaveFile::writeData +240 (int (*)(...))QSaveFile::fileName +248 (int (*)(...))QFileDevice::resize +256 (int (*)(...))QFileDevice::permissions +264 (int (*)(...))QFileDevice::setPermissions + +Class QSaveFile + size=16 align=8 + base size=16 base align=8 +QSaveFile (0x0x7fb60d306208) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7fb60d306270) 0 + primary-for QSaveFile (0x0x7fb60d306208) + QIODevice (0x0x7fb60d3062d8) 0 + primary-for QFileDevice (0x0x7fb60d306270) + QObject (0x0x7fb60d3183c0) 0 + primary-for QIODevice (0x0x7fb60d3062d8) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7fb60d3184e0) 0 empty + +Vtable for QSettings +QSettings::_ZTV9QSettings: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QSettings) +16 (int (*)(...))QSettings::metaObject +24 (int (*)(...))QSettings::qt_metacast +32 (int (*)(...))QSettings::qt_metacall +40 (int (*)(...))QSettings::~QSettings +48 (int (*)(...))QSettings::~QSettings +56 (int (*)(...))QSettings::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSettings + size=16 align=8 + base size=16 base align=8 +QSettings (0x0x7fb60d306340) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7fb60d318480) 0 + primary-for QSettings (0x0x7fb60d306340) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7fb60d318540) 0 empty + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7fb60d318660) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7fb60d318900) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7fb60d318a20) 0 empty + +Vtable for QTemporaryFile +QTemporaryFile::_ZTV14QTemporaryFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QTemporaryFile) +16 (int (*)(...))QTemporaryFile::metaObject +24 (int (*)(...))QTemporaryFile::qt_metacast +32 (int (*)(...))QTemporaryFile::qt_metacall +40 (int (*)(...))QTemporaryFile::~QTemporaryFile +48 (int (*)(...))QTemporaryFile::~QTemporaryFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QTemporaryFile::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFile::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QTemporaryFile::fileName +248 (int (*)(...))QFile::resize +256 (int (*)(...))QFile::permissions +264 (int (*)(...))QFile::setPermissions + +Class QTemporaryFile + size=16 align=8 + base size=16 base align=8 +QTemporaryFile (0x0x7fb60d3064e0) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7fb60d306548) 0 + primary-for QTemporaryFile (0x0x7fb60d3064e0) + QFileDevice (0x0x7fb60d3065b0) 0 + primary-for QFile (0x0x7fb60d306548) + QIODevice (0x0x7fb60d306618) 0 + primary-for QFileDevice (0x0x7fb60d3065b0) + QObject (0x0x7fb60d3189c0) 0 + primary-for QIODevice (0x0x7fb60d306618) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7fb60d318b40) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7fb60d0bd060) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7fb60d0bd1e0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7fb60d0bd300) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7fb60d0bd480) 0 empty + +Vtable for QAbstractItemModel +QAbstractItemModel::_ZTV18QAbstractItemModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractItemModel) +16 (int (*)(...))QAbstractItemModel::metaObject +24 (int (*)(...))QAbstractItemModel::qt_metacast +32 (int (*)(...))QAbstractItemModel::qt_metacall +40 (int (*)(...))QAbstractItemModel::~QAbstractItemModel +48 (int (*)(...))QAbstractItemModel::~QAbstractItemModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractItemModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractItemModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractItemModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractItemModel + size=16 align=8 + base size=16 base align=8 +QAbstractItemModel (0x0x7fb60d306af8) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7fb60d0bd420) 0 + primary-for QAbstractItemModel (0x0x7fb60d306af8) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7fb60d0bd7e0) 0 empty + +Vtable for QAbstractTableModel +QAbstractTableModel::_ZTV19QAbstractTableModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTableModel) +16 (int (*)(...))QAbstractTableModel::metaObject +24 (int (*)(...))QAbstractTableModel::qt_metacast +32 (int (*)(...))QAbstractTableModel::qt_metacall +40 (int (*)(...))QAbstractTableModel::~QAbstractTableModel +48 (int (*)(...))QAbstractTableModel::~QAbstractTableModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractTableModel::index +120 (int (*)(...))QAbstractTableModel::parent +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractTableModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractTableModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractTableModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractTableModel + size=16 align=8 + base size=16 base align=8 +QAbstractTableModel (0x0x7fb60d306c98) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7fb60d306d00) 0 + primary-for QAbstractTableModel (0x0x7fb60d306c98) + QObject (0x0x7fb60d0bd780) 0 + primary-for QAbstractItemModel (0x0x7fb60d306d00) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7fb60d0bd8a0) 0 empty + +Vtable for QAbstractListModel +QAbstractListModel::_ZTV18QAbstractListModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractListModel) +16 (int (*)(...))QAbstractListModel::metaObject +24 (int (*)(...))QAbstractListModel::qt_metacast +32 (int (*)(...))QAbstractListModel::qt_metacall +40 (int (*)(...))QAbstractListModel::~QAbstractListModel +48 (int (*)(...))QAbstractListModel::~QAbstractListModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractListModel::index +120 (int (*)(...))QAbstractListModel::parent +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QAbstractListModel::columnCount +152 (int (*)(...))QAbstractListModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractListModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractListModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractListModel + size=16 align=8 + base size=16 base align=8 +QAbstractListModel (0x0x7fb60d306d68) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7fb60d306dd0) 0 + primary-for QAbstractListModel (0x0x7fb60d306d68) + QObject (0x0x7fb60d0bd840) 0 + primary-for QAbstractItemModel (0x0x7fb60d306dd0) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7fb60d0bd960) 0 empty + +Vtable for QAbstractProxyModel +QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractProxyModel) +16 (int (*)(...))QAbstractProxyModel::metaObject +24 (int (*)(...))QAbstractProxyModel::qt_metacast +32 (int (*)(...))QAbstractProxyModel::qt_metacall +40 (int (*)(...))QAbstractProxyModel::~QAbstractProxyModel +48 (int (*)(...))QAbstractProxyModel::~QAbstractProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractProxyModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QAbstractProxyModel::headerData +184 (int (*)(...))QAbstractProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QAbstractProxyModel::mimeTypes +216 (int (*)(...))QAbstractProxyModel::mimeData +224 (int (*)(...))QAbstractProxyModel::canDropMimeData +232 (int (*)(...))QAbstractProxyModel::dropMimeData +240 (int (*)(...))QAbstractProxyModel::supportedDropActions +248 (int (*)(...))QAbstractProxyModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QAbstractProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QAbstractProxyModel::setSourceModel +392 (int (*)(...))__cxa_pure_virtual +400 (int (*)(...))__cxa_pure_virtual +408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource +416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource + +Class QAbstractProxyModel + size=16 align=8 + base size=16 base align=8 +QAbstractProxyModel (0x0x7fb60d306e38) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7fb60d306ea0) 0 + primary-for QAbstractProxyModel (0x0x7fb60d306e38) + QObject (0x0x7fb60d0bd900) 0 + primary-for QAbstractItemModel (0x0x7fb60d306ea0) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7fb60d0bda20) 0 empty + +Vtable for QIdentityProxyModel +QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QIdentityProxyModel) +16 (int (*)(...))QIdentityProxyModel::metaObject +24 (int (*)(...))QIdentityProxyModel::qt_metacast +32 (int (*)(...))QIdentityProxyModel::qt_metacall +40 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel +48 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QIdentityProxyModel::index +120 (int (*)(...))QIdentityProxyModel::parent +128 (int (*)(...))QIdentityProxyModel::sibling +136 (int (*)(...))QIdentityProxyModel::rowCount +144 (int (*)(...))QIdentityProxyModel::columnCount +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QIdentityProxyModel::headerData +184 (int (*)(...))QAbstractProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QAbstractProxyModel::mimeTypes +216 (int (*)(...))QAbstractProxyModel::mimeData +224 (int (*)(...))QAbstractProxyModel::canDropMimeData +232 (int (*)(...))QIdentityProxyModel::dropMimeData +240 (int (*)(...))QAbstractProxyModel::supportedDropActions +248 (int (*)(...))QAbstractProxyModel::supportedDragActions +256 (int (*)(...))QIdentityProxyModel::insertRows +264 (int (*)(...))QIdentityProxyModel::insertColumns +272 (int (*)(...))QIdentityProxyModel::removeRows +280 (int (*)(...))QIdentityProxyModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QAbstractProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QIdentityProxyModel::match +352 (int (*)(...))QAbstractProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QIdentityProxyModel::setSourceModel +392 (int (*)(...))QIdentityProxyModel::mapToSource +400 (int (*)(...))QIdentityProxyModel::mapFromSource +408 (int (*)(...))QIdentityProxyModel::mapSelectionToSource +416 (int (*)(...))QIdentityProxyModel::mapSelectionFromSource + +Class QIdentityProxyModel + size=16 align=8 + base size=16 base align=8 +QIdentityProxyModel (0x0x7fb60d306f08) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7fb60d306f70) 0 + primary-for QIdentityProxyModel (0x0x7fb60d306f08) + QAbstractItemModel (0x0x7fb60cdee000) 0 + primary-for QAbstractProxyModel (0x0x7fb60d306f70) + QObject (0x0x7fb60d0bd9c0) 0 + primary-for QAbstractItemModel (0x0x7fb60cdee000) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7fb60d0bda80) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7fb60d0bdc00) 0 empty + +Vtable for QItemSelectionModel +QItemSelectionModel::_ZTV19QItemSelectionModel: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QItemSelectionModel) +16 (int (*)(...))QItemSelectionModel::metaObject +24 (int (*)(...))QItemSelectionModel::qt_metacast +32 (int (*)(...))QItemSelectionModel::qt_metacall +40 (int (*)(...))QItemSelectionModel::~QItemSelectionModel +48 (int (*)(...))QItemSelectionModel::~QItemSelectionModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QItemSelectionModel::setCurrentIndex +120 (int (*)(...))QItemSelectionModel::select +128 (int (*)(...))QItemSelectionModel::select +136 (int (*)(...))QItemSelectionModel::clear +144 (int (*)(...))QItemSelectionModel::reset +152 (int (*)(...))QItemSelectionModel::clearCurrentIndex + +Class QItemSelectionModel + size=16 align=8 + base size=16 base align=8 +QItemSelectionModel (0x0x7fb60cdee0d0) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7fb60d0bdba0) 0 + primary-for QItemSelectionModel (0x0x7fb60cdee0d0) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7fb60cdee270) 0 + QList (0x0x7fb60cdee2d8) 0 + QListSpecialMethods (0x0x7fb60d0bde40) 0 empty + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7fb60d0bdf00) 0 empty + +Vtable for QSortFilterProxyModel +QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QSortFilterProxyModel) +16 (int (*)(...))QSortFilterProxyModel::metaObject +24 (int (*)(...))QSortFilterProxyModel::qt_metacast +32 (int (*)(...))QSortFilterProxyModel::qt_metacall +40 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel +48 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSortFilterProxyModel::index +120 (int (*)(...))QSortFilterProxyModel::parent +128 (int (*)(...))QSortFilterProxyModel::sibling +136 (int (*)(...))QSortFilterProxyModel::rowCount +144 (int (*)(...))QSortFilterProxyModel::columnCount +152 (int (*)(...))QSortFilterProxyModel::hasChildren +160 (int (*)(...))QSortFilterProxyModel::data +168 (int (*)(...))QSortFilterProxyModel::setData +176 (int (*)(...))QSortFilterProxyModel::headerData +184 (int (*)(...))QSortFilterProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QSortFilterProxyModel::mimeTypes +216 (int (*)(...))QSortFilterProxyModel::mimeData +224 (int (*)(...))QAbstractProxyModel::canDropMimeData +232 (int (*)(...))QSortFilterProxyModel::dropMimeData +240 (int (*)(...))QSortFilterProxyModel::supportedDropActions +248 (int (*)(...))QAbstractProxyModel::supportedDragActions +256 (int (*)(...))QSortFilterProxyModel::insertRows +264 (int (*)(...))QSortFilterProxyModel::insertColumns +272 (int (*)(...))QSortFilterProxyModel::removeRows +280 (int (*)(...))QSortFilterProxyModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QSortFilterProxyModel::fetchMore +312 (int (*)(...))QSortFilterProxyModel::canFetchMore +320 (int (*)(...))QSortFilterProxyModel::flags +328 (int (*)(...))QSortFilterProxyModel::sort +336 (int (*)(...))QSortFilterProxyModel::buddy +344 (int (*)(...))QSortFilterProxyModel::match +352 (int (*)(...))QSortFilterProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QSortFilterProxyModel::setSourceModel +392 (int (*)(...))QSortFilterProxyModel::mapToSource +400 (int (*)(...))QSortFilterProxyModel::mapFromSource +408 (int (*)(...))QSortFilterProxyModel::mapSelectionToSource +416 (int (*)(...))QSortFilterProxyModel::mapSelectionFromSource +424 (int (*)(...))QSortFilterProxyModel::filterAcceptsRow +432 (int (*)(...))QSortFilterProxyModel::filterAcceptsColumn +440 (int (*)(...))QSortFilterProxyModel::lessThan + +Class QSortFilterProxyModel + size=16 align=8 + base size=16 base align=8 +QSortFilterProxyModel (0x0x7fb60cdee340) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7fb60cdee3a8) 0 + primary-for QSortFilterProxyModel (0x0x7fb60cdee340) + QAbstractItemModel (0x0x7fb60cdee410) 0 + primary-for QAbstractProxyModel (0x0x7fb60cdee3a8) + QObject (0x0x7fb60d0bdea0) 0 + primary-for QAbstractItemModel (0x0x7fb60cdee410) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7fb60ceb8000) 0 empty + +Vtable for QStringListModel +QStringListModel::_ZTV16QStringListModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QStringListModel) +16 (int (*)(...))QStringListModel::metaObject +24 (int (*)(...))QStringListModel::qt_metacast +32 (int (*)(...))QStringListModel::qt_metacall +40 (int (*)(...))QStringListModel::~QStringListModel +48 (int (*)(...))QStringListModel::~QStringListModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractListModel::index +120 (int (*)(...))QAbstractListModel::parent +128 (int (*)(...))QStringListModel::sibling +136 (int (*)(...))QStringListModel::rowCount +144 (int (*)(...))QAbstractListModel::columnCount +152 (int (*)(...))QAbstractListModel::hasChildren +160 (int (*)(...))QStringListModel::data +168 (int (*)(...))QStringListModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractListModel::dropMimeData +240 (int (*)(...))QStringListModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QStringListModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QStringListModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QStringListModel::flags +328 (int (*)(...))QStringListModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QStringListModel + size=24 align=8 + base size=24 base align=8 +QStringListModel (0x0x7fb60cdee478) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7fb60cdee4e0) 0 + primary-for QStringListModel (0x0x7fb60cdee478) + QAbstractItemModel (0x0x7fb60cdee548) 0 + primary-for QAbstractListModel (0x0x7fb60cdee4e0) + QObject (0x0x7fb60d0bdf60) 0 + primary-for QAbstractItemModel (0x0x7fb60cdee548) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7fb60ceb8060) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7fb60ceb8120) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7fb60ceb81e0) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7fb60ceb8240) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7fb60ceb8300) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7fb60ceb8360) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7fb60ceb82a0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7fb60ceb83c0) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7fb60ceb8420) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7fb60ceb84e0) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7fb60ceb8540) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7fb60ceb8480) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7fb60ceb8660) 0 empty + +Vtable for QEventLoop +QEventLoop::_ZTV10QEventLoop: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QEventLoop) +16 (int (*)(...))QEventLoop::metaObject +24 (int (*)(...))QEventLoop::qt_metacast +32 (int (*)(...))QEventLoop::qt_metacall +40 (int (*)(...))QEventLoop::~QEventLoop +48 (int (*)(...))QEventLoop::~QEventLoop +56 (int (*)(...))QEventLoop::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QEventLoop + size=16 align=8 + base size=16 base align=8 +QEventLoop (0x0x7fb60cdee5b0) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7fb60ceb8600) 0 + primary-for QEventLoop (0x0x7fb60cdee5b0) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7fb60ceb8780) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7fb60ceb8840) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7fb60ceb88a0) 0 + +Vtable for QAbstractEventDispatcher +QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher) +16 (int (*)(...))QAbstractEventDispatcher::metaObject +24 (int (*)(...))QAbstractEventDispatcher::qt_metacast +32 (int (*)(...))QAbstractEventDispatcher::qt_metacall +40 (int (*)(...))QAbstractEventDispatcher::~QAbstractEventDispatcher +48 (int (*)(...))QAbstractEventDispatcher::~QAbstractEventDispatcher +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual +184 (int (*)(...))__cxa_pure_virtual +192 (int (*)(...))__cxa_pure_virtual +200 (int (*)(...))__cxa_pure_virtual +208 (int (*)(...))QAbstractEventDispatcher::startingUp +216 (int (*)(...))QAbstractEventDispatcher::closingDown + +Class QAbstractEventDispatcher + size=16 align=8 + base size=16 base align=8 +QAbstractEventDispatcher (0x0x7fb60cdee6e8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7fb60ceb87e0) 0 + primary-for QAbstractEventDispatcher (0x0x7fb60cdee6e8) + +Vtable for QAbstractNativeEventFilter +QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter) +16 (int (*)(...))QAbstractNativeEventFilter::~QAbstractNativeEventFilter +24 (int (*)(...))QAbstractNativeEventFilter::~QAbstractNativeEventFilter +32 (int (*)(...))__cxa_pure_virtual + +Class QAbstractNativeEventFilter + size=16 align=8 + base size=16 base align=8 +QAbstractNativeEventFilter (0x0x7fb60ceb8900) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7fb60ceb8960) 0 + +Vtable for QEvent +QEvent::_ZTV6QEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QEvent) +16 (int (*)(...))QEvent::~QEvent +24 (int (*)(...))QEvent::~QEvent + +Class QEvent + size=24 align=8 + base size=20 base align=8 +QEvent (0x0x7fb60ceb8a80) 0 + vptr=((& QEvent::_ZTV6QEvent) + 16u) + +Vtable for QTimerEvent +QTimerEvent::_ZTV11QTimerEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTimerEvent) +16 (int (*)(...))QTimerEvent::~QTimerEvent +24 (int (*)(...))QTimerEvent::~QTimerEvent + +Class QTimerEvent + size=24 align=8 + base size=24 base align=8 +QTimerEvent (0x0x7fb60cdee7b8) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7fb60ceb8ae0) 0 + primary-for QTimerEvent (0x0x7fb60cdee7b8) + +Vtable for QChildEvent +QChildEvent::_ZTV11QChildEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QChildEvent) +16 (int (*)(...))QChildEvent::~QChildEvent +24 (int (*)(...))QChildEvent::~QChildEvent + +Class QChildEvent + size=32 align=8 + base size=32 base align=8 +QChildEvent (0x0x7fb60cdee820) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7fb60ceb8b40) 0 + primary-for QChildEvent (0x0x7fb60cdee820) + +Vtable for QDynamicPropertyChangeEvent +QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI27QDynamicPropertyChangeEvent) +16 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent +24 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent + +Class QDynamicPropertyChangeEvent + size=32 align=8 + base size=32 base align=8 +QDynamicPropertyChangeEvent (0x0x7fb60cdee888) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7fb60ceb8ba0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7fb60cdee888) + +Vtable for QDeferredDeleteEvent +QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QDeferredDeleteEvent) +16 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent +24 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent + +Class QDeferredDeleteEvent + size=24 align=8 + base size=24 base align=8 +QDeferredDeleteEvent (0x0x7fb60cdee8f0) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7fb60ceb8c00) 0 + primary-for QDeferredDeleteEvent (0x0x7fb60cdee8f0) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7fb60ceb8cc0) 0 empty + +Vtable for QCoreApplication +QCoreApplication::_ZTV16QCoreApplication: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QCoreApplication) +16 (int (*)(...))QCoreApplication::metaObject +24 (int (*)(...))QCoreApplication::qt_metacast +32 (int (*)(...))QCoreApplication::qt_metacall +40 (int (*)(...))QCoreApplication::~QCoreApplication +48 (int (*)(...))QCoreApplication::~QCoreApplication +56 (int (*)(...))QCoreApplication::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QCoreApplication::notify +120 (int (*)(...))QCoreApplication::compressEvent + +Class QCoreApplication + size=16 align=8 + base size=16 base align=8 +QCoreApplication (0x0x7fb60cdee958) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7fb60ceb8c60) 0 + primary-for QCoreApplication (0x0x7fb60cdee958) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7fb60ceb8d20) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7fb60ceb8d80) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7fb60ceb8ea0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7fb60ccff000) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7fb60ccff060) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7fb60ccff1e0) 0 empty + +Vtable for QMimeData +QMimeData::_ZTV9QMimeData: 17u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QMimeData) +16 (int (*)(...))QMimeData::metaObject +24 (int (*)(...))QMimeData::qt_metacast +32 (int (*)(...))QMimeData::qt_metacall +40 (int (*)(...))QMimeData::~QMimeData +48 (int (*)(...))QMimeData::~QMimeData +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QMimeData::hasFormat +120 (int (*)(...))QMimeData::formats +128 (int (*)(...))QMimeData::retrieveData + +Class QMimeData + size=16 align=8 + base size=16 base align=8 +QMimeData (0x0x7fb60cdeebc8) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7fb60ccff180) 0 + primary-for QMimeData (0x0x7fb60cdeebc8) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7fb60ccff2a0) 0 empty + +Vtable for QObjectCleanupHandler +QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QObjectCleanupHandler) +16 (int (*)(...))QObjectCleanupHandler::metaObject +24 (int (*)(...))QObjectCleanupHandler::qt_metacast +32 (int (*)(...))QObjectCleanupHandler::qt_metacall +40 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler +48 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QObjectCleanupHandler + size=24 align=8 + base size=24 base align=8 +QObjectCleanupHandler (0x0x7fb60cdeec30) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7fb60ccff240) 0 + primary-for QObjectCleanupHandler (0x0x7fb60cdeec30) + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7fb60ccff3c0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7fb60ccff540) 0 + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7fb60ccffc00) 0 empty + +Vtable for QSharedMemory +QSharedMemory::_ZTV13QSharedMemory: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QSharedMemory) +16 (int (*)(...))QSharedMemory::metaObject +24 (int (*)(...))QSharedMemory::qt_metacast +32 (int (*)(...))QSharedMemory::qt_metacall +40 (int (*)(...))QSharedMemory::~QSharedMemory +48 (int (*)(...))QSharedMemory::~QSharedMemory +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSharedMemory + size=16 align=8 + base size=16 base align=8 +QSharedMemory (0x0x7fb60cdeee38) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7fb60ccffba0) 0 + primary-for QSharedMemory (0x0x7fb60cdeee38) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7fb60ccffcc0) 0 empty + +Vtable for QSignalMapper +QSignalMapper::_ZTV13QSignalMapper: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QSignalMapper) +16 (int (*)(...))QSignalMapper::metaObject +24 (int (*)(...))QSignalMapper::qt_metacast +32 (int (*)(...))QSignalMapper::qt_metacall +40 (int (*)(...))QSignalMapper::~QSignalMapper +48 (int (*)(...))QSignalMapper::~QSignalMapper +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSignalMapper + size=16 align=8 + base size=16 base align=8 +QSignalMapper (0x0x7fb60cdeeea0) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7fb60ccffc60) 0 + primary-for QSignalMapper (0x0x7fb60cdeeea0) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7fb60ccffd80) 0 empty + +Vtable for QSocketNotifier +QSocketNotifier::_ZTV15QSocketNotifier: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QSocketNotifier) +16 (int (*)(...))QSocketNotifier::metaObject +24 (int (*)(...))QSocketNotifier::qt_metacast +32 (int (*)(...))QSocketNotifier::qt_metacall +40 (int (*)(...))QSocketNotifier::~QSocketNotifier +48 (int (*)(...))QSocketNotifier::~QSocketNotifier +56 (int (*)(...))QSocketNotifier::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSocketNotifier + size=16 align=8 + base size=16 base align=8 +QSocketNotifier (0x0x7fb60cdeef08) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7fb60ccffd20) 0 + primary-for QSocketNotifier (0x0x7fb60cdeef08) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7fb60ccffde0) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7fb60ccfff00) 0 empty + +Vtable for QTimer +QTimer::_ZTV6QTimer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QTimer) +16 (int (*)(...))QTimer::metaObject +24 (int (*)(...))QTimer::qt_metacast +32 (int (*)(...))QTimer::qt_metacall +40 (int (*)(...))QTimer::~QTimer +48 (int (*)(...))QTimer::~QTimer +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QTimer::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QTimer + size=32 align=8 + base size=29 base align=8 +QTimer (0x0x7fb60cdeef70) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7fb60ccffea0) 0 + primary-for QTimer (0x0x7fb60cdeef70) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7fb60ca600c0) 0 empty + +Vtable for QTranslator +QTranslator::_ZTV11QTranslator: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTranslator) +16 (int (*)(...))QTranslator::metaObject +24 (int (*)(...))QTranslator::qt_metacast +32 (int (*)(...))QTranslator::qt_metacall +40 (int (*)(...))QTranslator::~QTranslator +48 (int (*)(...))QTranslator::~QTranslator +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QTranslator::translate +120 (int (*)(...))QTranslator::isEmpty + +Class QTranslator + size=16 align=8 + base size=16 base align=8 +QTranslator (0x0x7fb60ca62068) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7fb60ca60060) 0 + primary-for QTranslator (0x0x7fb60ca62068) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7fb60ca60120) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7fb60ca602a0) 0 + +Vtable for QFactoryInterface +QFactoryInterface::_ZTV17QFactoryInterface: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QFactoryInterface) +16 (int (*)(...))QFactoryInterface::~QFactoryInterface +24 (int (*)(...))QFactoryInterface::~QFactoryInterface +32 (int (*)(...))__cxa_pure_virtual + +Class QFactoryInterface + size=8 align=8 + base size=8 base align=8 +QFactoryInterface (0x0x7fb60ca60300) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7fb60ca60420) 0 empty + +Vtable for QLibrary +QLibrary::_ZTV8QLibrary: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI8QLibrary) +16 (int (*)(...))QLibrary::metaObject +24 (int (*)(...))QLibrary::qt_metacast +32 (int (*)(...))QLibrary::qt_metacall +40 (int (*)(...))QLibrary::~QLibrary +48 (int (*)(...))QLibrary::~QLibrary +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QLibrary + size=32 align=8 + base size=25 base align=8 +QLibrary (0x0x7fb60ca62138) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7fb60ca603c0) 0 + primary-for QLibrary (0x0x7fb60ca62138) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7fb60ca60540) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7fb60ca606c0) 0 empty + +Vtable for QPluginLoader +QPluginLoader::_ZTV13QPluginLoader: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QPluginLoader) +16 (int (*)(...))QPluginLoader::metaObject +24 (int (*)(...))QPluginLoader::qt_metacast +32 (int (*)(...))QPluginLoader::qt_metacall +40 (int (*)(...))QPluginLoader::~QPluginLoader +48 (int (*)(...))QPluginLoader::~QPluginLoader +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QPluginLoader + size=32 align=8 + base size=25 base align=8 +QPluginLoader (0x0x7fb60ca622d8) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7fb60ca60660) 0 + primary-for QPluginLoader (0x0x7fb60ca622d8) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7fb60ca60720) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7fb60ca608a0) 0 empty + +Vtable for QAbstractState +QAbstractState::_ZTV14QAbstractState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QAbstractState) +16 (int (*)(...))QAbstractState::metaObject +24 (int (*)(...))QAbstractState::qt_metacast +32 (int (*)(...))QAbstractState::qt_metacall +40 (int (*)(...))QAbstractState::~QAbstractState +48 (int (*)(...))QAbstractState::~QAbstractState +56 (int (*)(...))QAbstractState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QAbstractState + size=16 align=8 + base size=16 base align=8 +QAbstractState (0x0x7fb60ca623a8) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7fb60ca60840) 0 + primary-for QAbstractState (0x0x7fb60ca623a8) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7fb60ca60960) 0 empty + +Vtable for QAbstractTransition +QAbstractTransition::_ZTV19QAbstractTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTransition) +16 (int (*)(...))QAbstractTransition::metaObject +24 (int (*)(...))QAbstractTransition::qt_metacast +32 (int (*)(...))QAbstractTransition::qt_metacall +40 (int (*)(...))QAbstractTransition::~QAbstractTransition +48 (int (*)(...))QAbstractTransition::~QAbstractTransition +56 (int (*)(...))QAbstractTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QAbstractTransition + size=16 align=8 + base size=16 base align=8 +QAbstractTransition (0x0x7fb60ca62410) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7fb60ca60900) 0 + primary-for QAbstractTransition (0x0x7fb60ca62410) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7fb60ca60a20) 0 empty + +Vtable for QEventTransition +QEventTransition::_ZTV16QEventTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QEventTransition) +16 (int (*)(...))QEventTransition::metaObject +24 (int (*)(...))QEventTransition::qt_metacast +32 (int (*)(...))QEventTransition::qt_metacall +40 (int (*)(...))QEventTransition::~QEventTransition +48 (int (*)(...))QEventTransition::~QEventTransition +56 (int (*)(...))QEventTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QEventTransition::eventTest +120 (int (*)(...))QEventTransition::onTransition + +Class QEventTransition + size=16 align=8 + base size=16 base align=8 +QEventTransition (0x0x7fb60ca62478) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7fb60ca624e0) 0 + primary-for QEventTransition (0x0x7fb60ca62478) + QObject (0x0x7fb60ca609c0) 0 + primary-for QAbstractTransition (0x0x7fb60ca624e0) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7fb60ca60ae0) 0 empty + +Vtable for QFinalState +QFinalState::_ZTV11QFinalState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QFinalState) +16 (int (*)(...))QFinalState::metaObject +24 (int (*)(...))QFinalState::qt_metacast +32 (int (*)(...))QFinalState::qt_metacall +40 (int (*)(...))QFinalState::~QFinalState +48 (int (*)(...))QFinalState::~QFinalState +56 (int (*)(...))QFinalState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFinalState::onEntry +120 (int (*)(...))QFinalState::onExit + +Class QFinalState + size=16 align=8 + base size=16 base align=8 +QFinalState (0x0x7fb60ca62548) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7fb60ca625b0) 0 + primary-for QFinalState (0x0x7fb60ca62548) + QObject (0x0x7fb60ca60a80) 0 + primary-for QAbstractState (0x0x7fb60ca625b0) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7fb60ca60ba0) 0 empty + +Vtable for QHistoryState +QHistoryState::_ZTV13QHistoryState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QHistoryState) +16 (int (*)(...))QHistoryState::metaObject +24 (int (*)(...))QHistoryState::qt_metacast +32 (int (*)(...))QHistoryState::qt_metacall +40 (int (*)(...))QHistoryState::~QHistoryState +48 (int (*)(...))QHistoryState::~QHistoryState +56 (int (*)(...))QHistoryState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QHistoryState::onEntry +120 (int (*)(...))QHistoryState::onExit + +Class QHistoryState + size=16 align=8 + base size=16 base align=8 +QHistoryState (0x0x7fb60ca62618) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7fb60ca62680) 0 + primary-for QHistoryState (0x0x7fb60ca62618) + QObject (0x0x7fb60ca60b40) 0 + primary-for QAbstractState (0x0x7fb60ca62680) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7fb60ca60c60) 0 empty + +Vtable for QSignalTransition +QSignalTransition::_ZTV17QSignalTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QSignalTransition) +16 (int (*)(...))QSignalTransition::metaObject +24 (int (*)(...))QSignalTransition::qt_metacast +32 (int (*)(...))QSignalTransition::qt_metacall +40 (int (*)(...))QSignalTransition::~QSignalTransition +48 (int (*)(...))QSignalTransition::~QSignalTransition +56 (int (*)(...))QSignalTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSignalTransition::eventTest +120 (int (*)(...))QSignalTransition::onTransition + +Class QSignalTransition + size=16 align=8 + base size=16 base align=8 +QSignalTransition (0x0x7fb60ca626e8) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7fb60ca62750) 0 + primary-for QSignalTransition (0x0x7fb60ca626e8) + QObject (0x0x7fb60ca60c00) 0 + primary-for QAbstractTransition (0x0x7fb60ca62750) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7fb60ca60d20) 0 empty + +Vtable for QState +QState::_ZTV6QState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QState) +16 (int (*)(...))QState::metaObject +24 (int (*)(...))QState::qt_metacast +32 (int (*)(...))QState::qt_metacall +40 (int (*)(...))QState::~QState +48 (int (*)(...))QState::~QState +56 (int (*)(...))QState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QState::onEntry +120 (int (*)(...))QState::onExit + +Class QState + size=16 align=8 + base size=16 base align=8 +QState (0x0x7fb60ca627b8) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7fb60ca62820) 0 + primary-for QState (0x0x7fb60ca627b8) + QObject (0x0x7fb60ca60cc0) 0 + primary-for QAbstractState (0x0x7fb60ca62820) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7fb60ca60e40) 0 empty + +Vtable for QStateMachine::SignalEvent +QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN13QStateMachine11SignalEventE) +16 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent +24 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent + +Class QStateMachine::SignalEvent + size=48 align=8 + base size=48 base align=8 +QStateMachine::SignalEvent (0x0x7fb60ca629c0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7fb60ca60ea0) 0 + primary-for QStateMachine::SignalEvent (0x0x7fb60ca629c0) + +Vtable for QStateMachine::WrappedEvent +QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN13QStateMachine12WrappedEventE) +16 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent +24 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent + +Class QStateMachine::WrappedEvent + size=40 align=8 + base size=40 base align=8 +QStateMachine::WrappedEvent (0x0x7fb60ca62a28) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7fb60ca60f00) 0 + primary-for QStateMachine::WrappedEvent (0x0x7fb60ca62a28) + +Vtable for QStateMachine +QStateMachine::_ZTV13QStateMachine: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QStateMachine) +16 (int (*)(...))QStateMachine::metaObject +24 (int (*)(...))QStateMachine::qt_metacast +32 (int (*)(...))QStateMachine::qt_metacall +40 (int (*)(...))QStateMachine::~QStateMachine +48 (int (*)(...))QStateMachine::~QStateMachine +56 (int (*)(...))QStateMachine::event +64 (int (*)(...))QStateMachine::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QStateMachine::onEntry +120 (int (*)(...))QStateMachine::onExit +128 (int (*)(...))QStateMachine::beginSelectTransitions +136 (int (*)(...))QStateMachine::endSelectTransitions +144 (int (*)(...))QStateMachine::beginMicrostep +152 (int (*)(...))QStateMachine::endMicrostep + +Class QStateMachine + size=16 align=8 + base size=16 base align=8 +QStateMachine (0x0x7fb60ca62888) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7fb60ca628f0) 0 + primary-for QStateMachine (0x0x7fb60ca62888) + QAbstractState (0x0x7fb60ca62958) 0 + primary-for QState (0x0x7fb60ca628f0) + QObject (0x0x7fb60ca60de0) 0 + primary-for QAbstractState (0x0x7fb60ca62958) + +Vtable for QException +QException::_ZTV10QException: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QException) +16 (int (*)(...))QException::~QException +24 (int (*)(...))QException::~QException +32 (int (*)(...))std::exception::what +40 (int (*)(...))QException::raise +48 (int (*)(...))QException::clone + +Class QException + size=8 align=8 + base size=8 base align=8 +QException (0x0x7fb60ca62a90) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7fb60ca60f60) 0 nearly-empty + primary-for QException (0x0x7fb60ca62a90) + +Vtable for QUnhandledException +QUnhandledException::_ZTV19QUnhandledException: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QUnhandledException) +16 (int (*)(...))QUnhandledException::~QUnhandledException +24 (int (*)(...))QUnhandledException::~QUnhandledException +32 (int (*)(...))std::exception::what +40 (int (*)(...))QUnhandledException::raise +48 (int (*)(...))QUnhandledException::clone + +Class QUnhandledException + size=8 align=8 + base size=8 base align=8 +QUnhandledException (0x0x7fb60ca62af8) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7fb60ca62b60) 0 nearly-empty + primary-for QUnhandledException (0x0x7fb60ca62af8) + std::exception (0x0x7fb60c7a9000) 0 nearly-empty + primary-for QException (0x0x7fb60ca62b60) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7fb60c7a9060) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7fb60c7a9120) 0 + +Vtable for QRunnable +QRunnable::_ZTV9QRunnable: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QRunnable) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))QRunnable::~QRunnable +32 (int (*)(...))QRunnable::~QRunnable + +Class QRunnable + size=16 align=8 + base size=12 base align=8 +QRunnable (0x0x7fb60c7a9180) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7fb60c7a91e0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7fb60ca62d00) 0 + QBasicMutex (0x0x7fb60c7a9300) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7fb60c7a9360) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7fb60c7a93c0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7fb60c7a9420) 0 + +Vtable for QtPrivate::ResultStoreBase +QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9QtPrivate15ResultStoreBaseE) +16 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase +24 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase + +Class QtPrivate::ResultStoreBase + size=48 align=8 + base size=44 base align=8 +QtPrivate::ResultStoreBase (0x0x7fb60c7a95a0) 0 + vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16u) + +Vtable for QFutureInterfaceBase +QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QFutureInterfaceBase) +16 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase +24 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase + +Class QFutureInterfaceBase + size=16 align=8 + base size=16 base align=8 +QFutureInterfaceBase (0x0x7fb60c7a9660) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7fb60c7a99c0) 0 empty + +Vtable for QFutureWatcherBase +QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFutureWatcherBase) +16 (int (*)(...))QFutureWatcherBase::metaObject +24 (int (*)(...))QFutureWatcherBase::qt_metacast +32 (int (*)(...))QFutureWatcherBase::qt_metacall +40 (int (*)(...))QFutureWatcherBase::~QFutureWatcherBase +48 (int (*)(...))QFutureWatcherBase::~QFutureWatcherBase +56 (int (*)(...))QFutureWatcherBase::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QFutureWatcherBase::connectNotify +104 (int (*)(...))QFutureWatcherBase::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QFutureWatcherBase + size=16 align=8 + base size=16 base align=8 +QFutureWatcherBase (0x0x7fb60c834618) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7fb60c7a9960) 0 + primary-for QFutureWatcherBase (0x0x7fb60c834618) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7fb60c7a9ae0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7fb60c7a9b40) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7fb60c7a9ba0) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7fb60c7a9c00) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7fb60c7a9cc0) 0 empty + +Vtable for QThread +QThread::_ZTV7QThread: 15u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QThread) +16 (int (*)(...))QThread::metaObject +24 (int (*)(...))QThread::qt_metacast +32 (int (*)(...))QThread::qt_metacall +40 (int (*)(...))QThread::~QThread +48 (int (*)(...))QThread::~QThread +56 (int (*)(...))QThread::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QThread::run + +Class QThread + size=16 align=8 + base size=16 base align=8 +QThread (0x0x7fb60c8349c0) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7fb60c7a9c60) 0 + primary-for QThread (0x0x7fb60c8349c0) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7fb60c7a9d80) 0 empty + +Vtable for QThreadPool +QThreadPool::_ZTV11QThreadPool: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QThreadPool) +16 (int (*)(...))QThreadPool::metaObject +24 (int (*)(...))QThreadPool::qt_metacast +32 (int (*)(...))QThreadPool::qt_metacall +40 (int (*)(...))QThreadPool::~QThreadPool +48 (int (*)(...))QThreadPool::~QThreadPool +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QThreadPool + size=16 align=8 + base size=16 base align=8 +QThreadPool (0x0x7fb60c834a28) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7fb60c7a9d20) 0 + primary-for QThreadPool (0x0x7fb60c834a28) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7fb60c7a9de0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7fb60c7a9ea0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7fb60c581480) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7fb60c5814e0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7fb60c581660) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7fb60c581600) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7fb60c5817e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7fb60c5818a0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7fb60c581a80) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7fb60c581c00) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7fb60c581c60) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7fb60c581cc0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7fb60c581d20) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7fb60c581e40) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7fb60c581f60) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7fb60c6f70c0) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7fb60c6f71e0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7fb60c6f7540) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7fb60c6f7660) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7fb60c6f7780) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7fb60c6f7840) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7fb60c6f7960) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7fb60c6f7a80) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7fb60c6f7ba0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7fb60c6f7cc0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7fb60c20c000) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7fb60c20c180) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7fb60c20c3c0) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7fb60c20cde0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7fb60c20cf60) 0 empty + +Vtable for QTimeLine +QTimeLine::_ZTV9QTimeLine: 15u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QTimeLine) +16 (int (*)(...))QTimeLine::metaObject +24 (int (*)(...))QTimeLine::qt_metacast +32 (int (*)(...))QTimeLine::qt_metacall +40 (int (*)(...))QTimeLine::~QTimeLine +48 (int (*)(...))QTimeLine::~QTimeLine +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QTimeLine::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QTimeLine::valueForTime + +Class QTimeLine + size=16 align=8 + base size=16 base align=8 +QTimeLine (0x0x7fb60c2a0340) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7fb60c20cf00) 0 + primary-for QTimeLine (0x0x7fb60c2a0340) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7fb60c2fc060) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7fb60c2fc000) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7fb60c2fc2a0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7fb60c2fc300) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7fb60c2a05b0) 0 + QVector (0x0x7fb60c2fc4e0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7fb60c2fc540) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7fb60c2fc660) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7fb60c2fc780) 0 + +Vtable for QXmlStreamEntityResolver +QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QXmlStreamEntityResolver) +16 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver +24 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver +32 (int (*)(...))QXmlStreamEntityResolver::resolveEntity +40 (int (*)(...))QXmlStreamEntityResolver::resolveUndeclaredEntity + +Class QXmlStreamEntityResolver + size=8 align=8 + base size=8 base align=8 +QXmlStreamEntityResolver (0x0x7fb60c2fc8a0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7fb60c2fc900) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7fb60c2fca20) 0 + +Class QGeoAddress + size=8 align=8 + base size=8 base align=8 +QGeoAddress (0x0x7fb60c2fcb40) 0 + +Class QGeoCoordinate + size=8 align=8 + base size=8 base align=8 +QGeoCoordinate (0x0x7fb60c2fcde0) 0 + +Class QGeoShape + size=8 align=8 + base size=8 base align=8 +QGeoShape (0x0x7fb60bfed0c0) 0 + +Class QGeoAreaMonitorInfo + size=8 align=8 + base size=8 base align=8 +QGeoAreaMonitorInfo (0x0x7fb60bfed360) 0 + +Class QGeoPositionInfo + size=8 align=8 + base size=8 base align=8 +QGeoPositionInfo (0x0x7fb60bfed420) 0 + +Class QGeoPositionInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoPositionInfoSource::QPrivateSignal (0x0x7fb60bfed4e0) 0 empty + +Vtable for QGeoPositionInfoSource +QGeoPositionInfoSource::_ZTV22QGeoPositionInfoSource: 23u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QGeoPositionInfoSource) +16 (int (*)(...))QGeoPositionInfoSource::metaObject +24 (int (*)(...))QGeoPositionInfoSource::qt_metacast +32 (int (*)(...))QGeoPositionInfoSource::qt_metacall +40 (int (*)(...))QGeoPositionInfoSource::~QGeoPositionInfoSource +48 (int (*)(...))QGeoPositionInfoSource::~QGeoPositionInfoSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoPositionInfoSource::setUpdateInterval +120 (int (*)(...))QGeoPositionInfoSource::setPreferredPositioningMethods +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual + +Class QGeoPositionInfoSource + size=24 align=8 + base size=24 base align=8 +QGeoPositionInfoSource (0x0x7fb60c2a0888) 0 + vptr=((& QGeoPositionInfoSource::_ZTV22QGeoPositionInfoSource) + 16u) + QObject (0x0x7fb60bfed480) 0 + primary-for QGeoPositionInfoSource (0x0x7fb60c2a0888) + +Class QGeoAreaMonitorSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoAreaMonitorSource::QPrivateSignal (0x0x7fb60bfed660) 0 empty + +Vtable for QGeoAreaMonitorSource +QGeoAreaMonitorSource::_ZTV21QGeoAreaMonitorSource: 23u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QGeoAreaMonitorSource) +16 (int (*)(...))QGeoAreaMonitorSource::metaObject +24 (int (*)(...))QGeoAreaMonitorSource::qt_metacast +32 (int (*)(...))QGeoAreaMonitorSource::qt_metacall +40 (int (*)(...))QGeoAreaMonitorSource::~QGeoAreaMonitorSource +48 (int (*)(...))QGeoAreaMonitorSource::~QGeoAreaMonitorSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoAreaMonitorSource::setPositionInfoSource +120 (int (*)(...))QGeoAreaMonitorSource::positionInfoSource +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual + +Class QGeoAreaMonitorSource + size=24 align=8 + base size=24 base align=8 +QGeoAreaMonitorSource (0x0x7fb60c2a09c0) 0 + vptr=((& QGeoAreaMonitorSource::_ZTV21QGeoAreaMonitorSource) + 16u) + QObject (0x0x7fb60bfed600) 0 + primary-for QGeoAreaMonitorSource (0x0x7fb60c2a09c0) + +Class QGeoCircle + size=8 align=8 + base size=8 base align=8 +QGeoCircle (0x0x7fb60c2a0a28) 0 + QGeoShape (0x0x7fb60bfed6c0) 0 + +Class QGeoLocation + size=8 align=8 + base size=8 base align=8 +QGeoLocation (0x0x7fb60bfed900) 0 + +Class QGeoSatelliteInfo + size=8 align=8 + base size=8 base align=8 +QGeoSatelliteInfo (0x0x7fb60bfedba0) 0 + +Class QGeoSatelliteInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoSatelliteInfoSource::QPrivateSignal (0x0x7fb60bfedc60) 0 empty + +Vtable for QGeoSatelliteInfoSource +QGeoSatelliteInfoSource::_ZTV23QGeoSatelliteInfoSource: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QGeoSatelliteInfoSource) +16 (int (*)(...))QGeoSatelliteInfoSource::metaObject +24 (int (*)(...))QGeoSatelliteInfoSource::qt_metacast +32 (int (*)(...))QGeoSatelliteInfoSource::qt_metacall +40 (int (*)(...))QGeoSatelliteInfoSource::~QGeoSatelliteInfoSource +48 (int (*)(...))QGeoSatelliteInfoSource::~QGeoSatelliteInfoSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoSatelliteInfoSource::setUpdateInterval +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual + +Class QGeoSatelliteInfoSource + size=24 align=8 + base size=24 base align=8 +QGeoSatelliteInfoSource (0x0x7fb60c2a0b60) 0 + vptr=((& QGeoSatelliteInfoSource::_ZTV23QGeoSatelliteInfoSource) + 16u) + QObject (0x0x7fb60bfedc00) 0 + primary-for QGeoSatelliteInfoSource (0x0x7fb60c2a0b60) + +Vtable for QGeoPositionInfoSourceFactory +QGeoPositionInfoSourceFactory::_ZTV29QGeoPositionInfoSourceFactory: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI29QGeoPositionInfoSourceFactory) +16 (int (*)(...))QGeoPositionInfoSourceFactory::~QGeoPositionInfoSourceFactory +24 (int (*)(...))QGeoPositionInfoSourceFactory::~QGeoPositionInfoSourceFactory +32 (int (*)(...))__cxa_pure_virtual +40 (int (*)(...))__cxa_pure_virtual +48 (int (*)(...))__cxa_pure_virtual + +Class QGeoPositionInfoSourceFactory + size=8 align=8 + base size=8 base align=8 +QGeoPositionInfoSourceFactory (0x0x7fb60bfedd20) 0 nearly-empty + vptr=((& QGeoPositionInfoSourceFactory::_ZTV29QGeoPositionInfoSourceFactory) + 16u) + +Class QGeoRectangle + size=8 align=8 + base size=8 base align=8 +QGeoRectangle (0x0x7fb60c2a0bc8) 0 + QGeoShape (0x0x7fb60bfedde0) 0 + +Class QNmeaPositionInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNmeaPositionInfoSource::QPrivateSignal (0x0x7fb60c0d21e0) 0 empty + +Vtable for QNmeaPositionInfoSource +QNmeaPositionInfoSource::_ZTV23QNmeaPositionInfoSource: 24u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QNmeaPositionInfoSource) +16 (int (*)(...))QNmeaPositionInfoSource::metaObject +24 (int (*)(...))QNmeaPositionInfoSource::qt_metacast +32 (int (*)(...))QNmeaPositionInfoSource::qt_metacall +40 (int (*)(...))QNmeaPositionInfoSource::~QNmeaPositionInfoSource +48 (int (*)(...))QNmeaPositionInfoSource::~QNmeaPositionInfoSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QNmeaPositionInfoSource::setUpdateInterval +120 (int (*)(...))QGeoPositionInfoSource::setPreferredPositioningMethods +128 (int (*)(...))QNmeaPositionInfoSource::lastKnownPosition +136 (int (*)(...))QNmeaPositionInfoSource::supportedPositioningMethods +144 (int (*)(...))QNmeaPositionInfoSource::minimumUpdateInterval +152 (int (*)(...))QNmeaPositionInfoSource::error +160 (int (*)(...))QNmeaPositionInfoSource::startUpdates +168 (int (*)(...))QNmeaPositionInfoSource::stopUpdates +176 (int (*)(...))QNmeaPositionInfoSource::requestUpdate +184 (int (*)(...))QNmeaPositionInfoSource::parsePosInfoFromNmeaData + +Class QNmeaPositionInfoSource + size=32 align=8 + base size=32 base align=8 +QNmeaPositionInfoSource (0x0x7fb60c2a0d00) 0 + vptr=((& QNmeaPositionInfoSource::_ZTV23QNmeaPositionInfoSource) + 16u) + QGeoPositionInfoSource (0x0x7fb60c2a0d68) 0 + primary-for QNmeaPositionInfoSource (0x0x7fb60c2a0d00) + QObject (0x0x7fb60c0d2180) 0 + primary-for QGeoPositionInfoSource (0x0x7fb60c2a0d68) + diff --git a/tests/auto/bic/data/QtPositioning.5.6.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtPositioning.5.6.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..42ed838 --- /dev/null +++ b/tests/auto/bic/data/QtPositioning.5.6.0.linux-gcc-amd64.txt @@ -0,0 +1,4118 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f7583ec7ae0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f7583ec7b40) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f7583f85780) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f7583f857e0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f7583f02958) 0 empty + std::input_iterator_tag (0x0x7f7583f85840) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f7583f029c0) 0 empty + std::forward_iterator_tag (0x0x7f7583f02a28) 0 empty + std::input_iterator_tag (0x0x7f7583f858a0) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f7583f02a90) 0 empty + std::bidirectional_iterator_tag (0x0x7f7583f02af8) 0 empty + std::forward_iterator_tag (0x0x7f7583f02b60) 0 empty + std::input_iterator_tag (0x0x7f7583f85900) 0 empty + +Class __gnu_cxx::__ops::_Iter_less_iter + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Iter_less_iter (0x0x7f7583f85de0) 0 empty + +Class __gnu_cxx::__ops::_Iter_less_val + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Iter_less_val (0x0x7f7583f85e40) 0 empty + +Class __gnu_cxx::__ops::_Val_less_iter + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Val_less_iter (0x0x7f7583f85ea0) 0 empty + +Class __gnu_cxx::__ops::_Iter_equal_to_iter + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Iter_equal_to_iter (0x0x7f7583f85f00) 0 empty + +Class __gnu_cxx::__ops::_Iter_equal_to_val + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Iter_equal_to_val (0x0x7f7583f85f60) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f75840199c0) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f7584019c00) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f7584019cc0) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f7584019d20) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f7584019de0) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f7584019e40) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f7582cc5300) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f7582cc5360) 0 + +Vtable for std::exception +std::exception::_ZTVSt9exception: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt9exception) +16 (int (*)(...))std::exception::~exception +24 (int (*)(...))std::exception::~exception +32 (int (*)(...))std::exception::what + +Class std::exception + size=8 align=8 + base size=8 base align=8 +std::exception (0x0x7f7582cc53c0) 0 nearly-empty + vptr=((& std::exception::_ZTVSt9exception) + 16u) + +Vtable for std::bad_exception +std::bad_exception::_ZTVSt13bad_exception: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt13bad_exception) +16 (int (*)(...))std::bad_exception::~bad_exception +24 (int (*)(...))std::bad_exception::~bad_exception +32 (int (*)(...))std::bad_exception::what + +Class std::bad_exception + size=8 align=8 + base size=8 base align=8 +std::bad_exception (0x0x7f7583f02e38) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f7582cc5420) 0 nearly-empty + primary-for std::bad_exception (0x0x7f7583f02e38) + +Vtable for std::bad_alloc +std::bad_alloc::_ZTVSt9bad_alloc: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt9bad_alloc) +16 (int (*)(...))std::bad_alloc::~bad_alloc +24 (int (*)(...))std::bad_alloc::~bad_alloc +32 (int (*)(...))std::bad_alloc::what + +Class std::bad_alloc + size=8 align=8 + base size=8 base align=8 +std::bad_alloc (0x0x7f7583f02ea0) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f7582cc5480) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f7583f02ea0) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f7582cc54e0) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f7582a5ec00) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f7582a5ec60) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7f7582a5ee40) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f7582b81ea0) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f7582b81f00) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f7582b81f60) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f7582be9000) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f7582be9180) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f7582bb2618) 0 + QAtomicInteger (0x0x7f7582bb2680) 0 + QBasicAtomicInteger (0x0x7f7582be9cc0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f75826b1de0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f75824ee2a0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f7582724888) 0 + QGenericArgument (0x0x7f75824ee300) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f75824ee480) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f75824ee540) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f75824ee600) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f75824ee660) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f75824ee7e0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f75824ee8a0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f75824eecc0) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f758227a060) 0 + +Vtable for __cxxabiv1::__forced_unwind +__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class __cxxabiv1::__forced_unwind + size=8 align=8 + base size=8 base align=8 +__cxxabiv1::__forced_unwind (0x0x7f758227a0c0) 0 nearly-empty + vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16u) + +Class sched_param + size=4 align=4 + base size=4 base align=4 +sched_param (0x0x7f758227af60) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f7582342000) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f75823420c0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f7582342120) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f7582342180) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f75823421e0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f7582342300) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f7582342360) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f7582342c00) 0 + +Vtable for std::locale::facet +std::locale::facet::_ZTVNSt6locale5facetE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6locale5facetE) +16 (int (*)(...))std::locale::facet::~facet +24 (int (*)(...))std::locale::facet::~facet + +Class std::locale::facet + size=16 align=8 + base size=12 base align=8 +std::locale::facet (0x0x7f7582342c60) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f7582342cc0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f7582342d20) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7f7582200120) 0 + +Vtable for std::logic_error +std::logic_error::_ZTVSt11logic_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt11logic_error) +16 (int (*)(...))std::logic_error::~logic_error +24 (int (*)(...))std::logic_error::~logic_error +32 (int (*)(...))std::logic_error::what + +Class std::logic_error + size=16 align=8 + base size=16 base align=8 +std::logic_error (0x0x7f7582337c30) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7f75822001e0) 0 nearly-empty + primary-for std::logic_error (0x0x7f7582337c30) + +Vtable for std::domain_error +std::domain_error::_ZTVSt12domain_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12domain_error) +16 (int (*)(...))std::domain_error::~domain_error +24 (int (*)(...))std::domain_error::~domain_error +32 (int (*)(...))std::logic_error::what + +Class std::domain_error + size=16 align=8 + base size=16 base align=8 +std::domain_error (0x0x7f7582337c98) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7f7582337d00) 0 + primary-for std::domain_error (0x0x7f7582337c98) + std::exception (0x0x7f7582200240) 0 nearly-empty + primary-for std::logic_error (0x0x7f7582337d00) + +Vtable for std::invalid_argument +std::invalid_argument::_ZTVSt16invalid_argument: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt16invalid_argument) +16 (int (*)(...))std::invalid_argument::~invalid_argument +24 (int (*)(...))std::invalid_argument::~invalid_argument +32 (int (*)(...))std::logic_error::what + +Class std::invalid_argument + size=16 align=8 + base size=16 base align=8 +std::invalid_argument (0x0x7f7582337d68) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7f7582337dd0) 0 + primary-for std::invalid_argument (0x0x7f7582337d68) + std::exception (0x0x7f75822002a0) 0 nearly-empty + primary-for std::logic_error (0x0x7f7582337dd0) + +Vtable for std::length_error +std::length_error::_ZTVSt12length_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12length_error) +16 (int (*)(...))std::length_error::~length_error +24 (int (*)(...))std::length_error::~length_error +32 (int (*)(...))std::logic_error::what + +Class std::length_error + size=16 align=8 + base size=16 base align=8 +std::length_error (0x0x7f7582337e38) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7f7582337ea0) 0 + primary-for std::length_error (0x0x7f7582337e38) + std::exception (0x0x7f7582200300) 0 nearly-empty + primary-for std::logic_error (0x0x7f7582337ea0) + +Vtable for std::out_of_range +std::out_of_range::_ZTVSt12out_of_range: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12out_of_range) +16 (int (*)(...))std::out_of_range::~out_of_range +24 (int (*)(...))std::out_of_range::~out_of_range +32 (int (*)(...))std::logic_error::what + +Class std::out_of_range + size=16 align=8 + base size=16 base align=8 +std::out_of_range (0x0x7f7582337f08) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7f7582337f70) 0 + primary-for std::out_of_range (0x0x7f7582337f08) + std::exception (0x0x7f7582200360) 0 nearly-empty + primary-for std::logic_error (0x0x7f7582337f70) + +Vtable for std::runtime_error +std::runtime_error::_ZTVSt13runtime_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt13runtime_error) +16 (int (*)(...))std::runtime_error::~runtime_error +24 (int (*)(...))std::runtime_error::~runtime_error +32 (int (*)(...))std::runtime_error::what + +Class std::runtime_error + size=16 align=8 + base size=16 base align=8 +std::runtime_error (0x0x7f7582337138) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7f75822003c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f7582337138) + +Vtable for std::range_error +std::range_error::_ZTVSt11range_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt11range_error) +16 (int (*)(...))std::range_error::~range_error +24 (int (*)(...))std::range_error::~range_error +32 (int (*)(...))std::runtime_error::what + +Class std::range_error + size=16 align=8 + base size=16 base align=8 +std::range_error (0x0x7f7582337208) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7f7582337270) 0 + primary-for std::range_error (0x0x7f7582337208) + std::exception (0x0x7f7582200420) 0 nearly-empty + primary-for std::runtime_error (0x0x7f7582337270) + +Vtable for std::overflow_error +std::overflow_error::_ZTVSt14overflow_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt14overflow_error) +16 (int (*)(...))std::overflow_error::~overflow_error +24 (int (*)(...))std::overflow_error::~overflow_error +32 (int (*)(...))std::runtime_error::what + +Class std::overflow_error + size=16 align=8 + base size=16 base align=8 +std::overflow_error (0x0x7f75823372d8) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7f75823373a8) 0 + primary-for std::overflow_error (0x0x7f75823372d8) + std::exception (0x0x7f7582200480) 0 nearly-empty + primary-for std::runtime_error (0x0x7f75823373a8) + +Vtable for std::underflow_error +std::underflow_error::_ZTVSt15underflow_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt15underflow_error) +16 (int (*)(...))std::underflow_error::~underflow_error +24 (int (*)(...))std::underflow_error::~underflow_error +32 (int (*)(...))std::runtime_error::what + +Class std::underflow_error + size=16 align=8 + base size=16 base align=8 +std::underflow_error (0x0x7f75823374e0) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7f75823375b0) 0 + primary-for std::underflow_error (0x0x7f75823374e0) + std::exception (0x0x7f75822004e0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f75823375b0) + +Class std::ios_base::system_error::error_code + size=16 align=8 + base size=16 base align=8 +std::ios_base::system_error::error_code (0x0x7f7582200600) 0 + +Vtable for std::ios_base::system_error +std::ios_base::system_error::_ZTVNSt8ios_base12system_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt8ios_base12system_errorE) +16 (int (*)(...))std::ios_base::system_error::~system_error +24 (int (*)(...))std::ios_base::system_error::~system_error +32 (int (*)(...))std::runtime_error::what + +Class std::ios_base::system_error + size=32 align=8 + base size=32 base align=8 +std::ios_base::system_error (0x0x7f7582337958) 0 + vptr=((& std::ios_base::system_error::_ZTVNSt8ios_base12system_errorE) + 16u) + std::runtime_error (0x0x7f7582337a28) 0 + primary-for std::ios_base::system_error (0x0x7f7582337958) + std::exception (0x0x7f75822005a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f7582337a28) + +Vtable for std::ios_base::failure +std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt8ios_base7failureB5cxx11E) +16 (int (*)(...))std::ios_base::failure::~failure +24 (int (*)(...))std::ios_base::failure::~failure +32 (int (*)(...))std::ios_base::failure::what + +Class std::ios_base::failure + size=32 align=8 + base size=32 base align=8 +std::ios_base::failure (0x0x7f7582249000) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::ios_base::system_error (0x0x7f7582249068) 0 + primary-for std::ios_base::failure (0x0x7f7582249000) + std::runtime_error (0x0x7f75822490d0) 0 + primary-for std::ios_base::system_error (0x0x7f7582249068) + std::exception (0x0x7f7582200660) 0 nearly-empty + primary-for std::runtime_error (0x0x7f75822490d0) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f75822006c0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f7582200720) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f7582200780) 0 empty + +Vtable for std::ios_base +std::ios_base::_ZTVSt8ios_base: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt8ios_base) +16 (int (*)(...))std::ios_base::~ios_base +24 (int (*)(...))std::ios_base::~ios_base + +Class std::ios_base + size=216 align=8 + base size=216 base align=8 +std::ios_base (0x0x7f7582200540) 0 + vptr=((& std::ios_base::_ZTVSt8ios_base) + 16u) + +Class std::ctype_base + size=1 align=1 + base size=0 base align=1 +std::ctype_base (0x0x7f7582200ea0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f7581f505a0) 0 empty + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSo: 2u entries +0 ((& std::basic_ostream::_ZTVSo) + 24u) +8 ((& std::basic_ostream::_ZTVSo) + 64u) + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2u entries +0 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64u) + +VTT for std::basic_istream +std::basic_istream::_ZTTSi: 2u entries +0 ((& std::basic_istream::_ZTVSi) + 24u) +8 ((& std::basic_istream::_ZTVSi) + 64u) + +VTT for std::basic_istream +std::basic_istream::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2u entries +0 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64u) + +Construction vtable for std::basic_istream (0x0x7f7581a5d750 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd0_Si: 10u entries +0 24u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISi) +24 0u +32 0u +40 18446744073709551592u +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISi) +64 0u +72 0u + +Construction vtable for std::basic_ostream (0x0x7f7581a5d820 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd16_So: 10u entries +0 8u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISo) +24 0u +32 0u +40 18446744073709551608u +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISo) +64 0u +72 0u + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSd: 7u entries +0 ((& std::basic_iostream::_ZTVSd) + 24u) +8 ((& std::basic_iostream::_ZTCSd0_Si) + 24u) +16 ((& std::basic_iostream::_ZTCSd0_Si) + 64u) +24 ((& std::basic_iostream::_ZTCSd16_So) + 24u) +32 ((& std::basic_iostream::_ZTCSd16_So) + 64u) +40 ((& std::basic_iostream::_ZTVSd) + 104u) +48 ((& std::basic_iostream::_ZTVSd) + 64u) + +Construction vtable for std::basic_istream (0x0x7f7581a5dbc8 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10u entries +0 24u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +24 0u +32 0u +40 18446744073709551592u +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +64 0u +72 0u + +Construction vtable for std::basic_ostream (0x0x7f7581a5dc98 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10u entries +0 8u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +24 0u +32 0u +40 18446744073709551608u +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +64 0u +72 0u + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7u entries +0 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24u) +16 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64u) +24 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24u) +32 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64u) +40 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104u) +48 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64u) + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7f7581cd5cc0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f7581cd5d20) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f7581b5f360) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f7581b5f540) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f7581b5f780) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f7581b5f840) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f7581b5f7e0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f7581b5fea0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f75819b72a0) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7f75819b7660) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7f75819b76c0) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f75819b7720) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7f75819b7ae0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7f75819b7b40) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7f7581b4ec98) 0 empty + QListData::NotIndirectLayout (0x0x7f75819b7ba0) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7f75817db310) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f75819b7c00) 0 empty + QListData::NotIndirectLayout (0x0x7f75819b7c60) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7f7581b4ed00) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f75819b7cc0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f75819b7d20) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f75819b7a80) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f758184a900) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f758184aae0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f758184aa80) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f758152d068) 0 + QList (0x0x7f758152d0d0) 0 + QListSpecialMethods (0x0x7f758184acc0) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f758184af00) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f758158f600) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f758152dd00) 0 + std::iterator (0x0x7f758158f6c0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f758152dd68) 0 + std::_Bit_iterator_base (0x0x7f758152ddd0) 0 + std::iterator (0x0x7f758158f720) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f758152de38) 0 + std::_Bit_iterator_base (0x0x7f758152dea0) 0 + std::iterator (0x0x7f758158f780) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f758158fb40) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f758109f060) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f758109f120) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f758109f240) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f758109f3c0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f758109f660) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f758109f780) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f75811d2180) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f75811d2540) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f75811d2780) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f7580faa7e0) 0 + +Vtable for QObjectData +QObjectData::_ZTV11QObjectData: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QObjectData) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))__cxa_pure_virtual + +Class QObjectData + size=48 align=8 + base size=48 base align=8 +QObjectData (0x0x7f7580faa960) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f7580faab40) 0 empty + +Vtable for QObject +QObject::_ZTV7QObject: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QObject) +16 (int (*)(...))QObject::metaObject +24 (int (*)(...))QObject::qt_metacast +32 (int (*)(...))QObject::qt_metacall +40 (int (*)(...))QObject::~QObject +48 (int (*)(...))QObject::~QObject +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QObject + size=16 align=8 + base size=16 base align=8 +QObject (0x0x7f7580faaae0) 0 + vptr=((& QObject::_ZTV7QObject) + 16u) + +Vtable for QObjectUserData +QObjectUserData::_ZTV15QObjectUserData: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QObjectUserData) +16 (int (*)(...))QObjectUserData::~QObjectUserData +24 (int (*)(...))QObjectUserData::~QObjectUserData + +Class QObjectUserData + size=8 align=8 + base size=8 base align=8 +QObjectUserData (0x0x7f7580faaea0) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f7580faaf00) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f7580caa000) 0 empty + +Vtable for QAbstractAnimation +QAbstractAnimation::_ZTV18QAbstractAnimation: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractAnimation) +16 (int (*)(...))QAbstractAnimation::metaObject +24 (int (*)(...))QAbstractAnimation::qt_metacast +32 (int (*)(...))QAbstractAnimation::qt_metacall +40 0u +48 0u +56 (int (*)(...))QAbstractAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QAbstractAnimation + size=16 align=8 + base size=16 base align=8 +QAbstractAnimation (0x0x7f7580ca5000) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f7580faaf60) 0 + primary-for QAbstractAnimation (0x0x7f7580ca5000) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f7580caa0c0) 0 empty + +Vtable for QAnimationDriver +QAnimationDriver::_ZTV16QAnimationDriver: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QAnimationDriver) +16 (int (*)(...))QAnimationDriver::metaObject +24 (int (*)(...))QAnimationDriver::qt_metacast +32 (int (*)(...))QAnimationDriver::qt_metacall +40 (int (*)(...))QAnimationDriver::~QAnimationDriver +48 (int (*)(...))QAnimationDriver::~QAnimationDriver +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAnimationDriver::advance +120 (int (*)(...))QAnimationDriver::elapsed +128 (int (*)(...))QAnimationDriver::start +136 (int (*)(...))QAnimationDriver::stop + +Class QAnimationDriver + size=16 align=8 + base size=16 base align=8 +QAnimationDriver (0x0x7f7580ca5068) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f7580caa060) 0 + primary-for QAnimationDriver (0x0x7f7580ca5068) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f7580caa180) 0 empty + +Vtable for QAnimationGroup +QAnimationGroup::_ZTV15QAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAnimationGroup) +16 (int (*)(...))QAnimationGroup::metaObject +24 (int (*)(...))QAnimationGroup::qt_metacast +32 (int (*)(...))QAnimationGroup::qt_metacall +40 0u +48 0u +56 (int (*)(...))QAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QAnimationGroup + size=16 align=8 + base size=16 base align=8 +QAnimationGroup (0x0x7f7580ca50d0) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f7580ca5138) 0 + primary-for QAnimationGroup (0x0x7f7580ca50d0) + QObject (0x0x7f7580caa120) 0 + primary-for QAbstractAnimation (0x0x7f7580ca5138) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f7580caa240) 0 empty + +Vtable for QParallelAnimationGroup +QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QParallelAnimationGroup) +16 (int (*)(...))QParallelAnimationGroup::metaObject +24 (int (*)(...))QParallelAnimationGroup::qt_metacast +32 (int (*)(...))QParallelAnimationGroup::qt_metacall +40 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup +48 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup +56 (int (*)(...))QParallelAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QParallelAnimationGroup::duration +120 (int (*)(...))QParallelAnimationGroup::updateCurrentTime +128 (int (*)(...))QParallelAnimationGroup::updateState +136 (int (*)(...))QParallelAnimationGroup::updateDirection + +Class QParallelAnimationGroup + size=16 align=8 + base size=16 base align=8 +QParallelAnimationGroup (0x0x7f7580ca51a0) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f7580ca5208) 0 + primary-for QParallelAnimationGroup (0x0x7f7580ca51a0) + QAbstractAnimation (0x0x7f7580ca5270) 0 + primary-for QAnimationGroup (0x0x7f7580ca5208) + QObject (0x0x7f7580caa1e0) 0 + primary-for QAbstractAnimation (0x0x7f7580ca5270) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f7580caa300) 0 empty + +Vtable for QPauseAnimation +QPauseAnimation::_ZTV15QPauseAnimation: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QPauseAnimation) +16 (int (*)(...))QPauseAnimation::metaObject +24 (int (*)(...))QPauseAnimation::qt_metacast +32 (int (*)(...))QPauseAnimation::qt_metacall +40 (int (*)(...))QPauseAnimation::~QPauseAnimation +48 (int (*)(...))QPauseAnimation::~QPauseAnimation +56 (int (*)(...))QPauseAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QPauseAnimation::duration +120 (int (*)(...))QPauseAnimation::updateCurrentTime +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QPauseAnimation + size=16 align=8 + base size=16 base align=8 +QPauseAnimation (0x0x7f7580ca52d8) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f7580ca5340) 0 + primary-for QPauseAnimation (0x0x7f7580ca52d8) + QObject (0x0x7f7580caa2a0) 0 + primary-for QAbstractAnimation (0x0x7f7580ca5340) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f7580d78660) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f7580d787e0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f7580d788a0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f7580d78c60) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7f7580d78c00) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f7580d78cc0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f7580afc720) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f7580afc7e0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f7580afc780) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f7580afc840) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f7580afc6c0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f7580afcb40) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f7580afcc00) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f7580afcba0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f7580afccc0) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f7580afcc60) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f75808c9900) 0 empty + +Vtable for QVariantAnimation +QVariantAnimation::_ZTV17QVariantAnimation: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QVariantAnimation) +16 (int (*)(...))QVariantAnimation::metaObject +24 (int (*)(...))QVariantAnimation::qt_metacast +32 (int (*)(...))QVariantAnimation::qt_metacall +40 (int (*)(...))QVariantAnimation::~QVariantAnimation +48 (int (*)(...))QVariantAnimation::~QVariantAnimation +56 (int (*)(...))QVariantAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QVariantAnimation::duration +120 (int (*)(...))QVariantAnimation::updateCurrentTime +128 (int (*)(...))QVariantAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection +144 (int (*)(...))QVariantAnimation::updateCurrentValue +152 (int (*)(...))QVariantAnimation::interpolated + +Class QVariantAnimation + size=16 align=8 + base size=16 base align=8 +QVariantAnimation (0x0x7f75808f43a8) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f75808f4410) 0 + primary-for QVariantAnimation (0x0x7f75808f43a8) + QObject (0x0x7f75808c98a0) 0 + primary-for QAbstractAnimation (0x0x7f75808f4410) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f75808c99c0) 0 empty + +Vtable for QPropertyAnimation +QPropertyAnimation::_ZTV18QPropertyAnimation: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QPropertyAnimation) +16 (int (*)(...))QPropertyAnimation::metaObject +24 (int (*)(...))QPropertyAnimation::qt_metacast +32 (int (*)(...))QPropertyAnimation::qt_metacall +40 (int (*)(...))QPropertyAnimation::~QPropertyAnimation +48 (int (*)(...))QPropertyAnimation::~QPropertyAnimation +56 (int (*)(...))QPropertyAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QVariantAnimation::duration +120 (int (*)(...))QVariantAnimation::updateCurrentTime +128 (int (*)(...))QPropertyAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection +144 (int (*)(...))QPropertyAnimation::updateCurrentValue +152 (int (*)(...))QVariantAnimation::interpolated + +Class QPropertyAnimation + size=16 align=8 + base size=16 base align=8 +QPropertyAnimation (0x0x7f75808f44e0) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f75808f4548) 0 + primary-for QPropertyAnimation (0x0x7f75808f44e0) + QAbstractAnimation (0x0x7f75808f45b0) 0 + primary-for QVariantAnimation (0x0x7f75808f4548) + QObject (0x0x7f75808c9960) 0 + primary-for QAbstractAnimation (0x0x7f75808f45b0) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f75808c9a80) 0 empty + +Vtable for QSequentialAnimationGroup +QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QSequentialAnimationGroup) +16 (int (*)(...))QSequentialAnimationGroup::metaObject +24 (int (*)(...))QSequentialAnimationGroup::qt_metacast +32 (int (*)(...))QSequentialAnimationGroup::qt_metacall +40 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup +48 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup +56 (int (*)(...))QSequentialAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSequentialAnimationGroup::duration +120 (int (*)(...))QSequentialAnimationGroup::updateCurrentTime +128 (int (*)(...))QSequentialAnimationGroup::updateState +136 (int (*)(...))QSequentialAnimationGroup::updateDirection + +Class QSequentialAnimationGroup + size=16 align=8 + base size=16 base align=8 +QSequentialAnimationGroup (0x0x7f75808f4618) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f75808f4680) 0 + primary-for QSequentialAnimationGroup (0x0x7f75808f4618) + QAbstractAnimation (0x0x7f75808f46e8) 0 + primary-for QAnimationGroup (0x0x7f75808f4680) + QObject (0x0x7f75808c9a20) 0 + primary-for QAbstractAnimation (0x0x7f75808f46e8) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f75808c9b40) 0 + +Vtable for QTextCodec +QTextCodec::_ZTV10QTextCodec: 9u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QTextCodec) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))QTextCodec::aliases +32 (int (*)(...))__cxa_pure_virtual +40 (int (*)(...))__cxa_pure_virtual +48 (int (*)(...))__cxa_pure_virtual +56 0u +64 0u + +Class QTextCodec + size=8 align=8 + base size=8 base align=8 +QTextCodec (0x0x7f75808c9ae0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f75808c9c60) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f75808c9cc0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f75808c9d20) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f75808c9f00) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f7580a066c0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f7580a06840) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f7580a069c0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f7580a06ba0) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f7580a06c60) 0 empty + +Vtable for QIODevice +QIODevice::_ZTV9QIODevice: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QIODevice) +16 (int (*)(...))QIODevice::metaObject +24 (int (*)(...))QIODevice::qt_metacast +32 (int (*)(...))QIODevice::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QIODevice::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QIODevice::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))__cxa_pure_virtual +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))__cxa_pure_virtual + +Class QIODevice + size=16 align=8 + base size=16 base align=8 +QIODevice (0x0x7f75808f49c0) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f7580a06c00) 0 + primary-for QIODevice (0x0x7f75808f49c0) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f7580a06de0) 0 empty + +Vtable for QBuffer +QBuffer::_ZTV7QBuffer: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QBuffer) +16 (int (*)(...))QBuffer::metaObject +24 (int (*)(...))QBuffer::qt_metacast +32 (int (*)(...))QBuffer::qt_metacall +40 (int (*)(...))QBuffer::~QBuffer +48 (int (*)(...))QBuffer::~QBuffer +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QBuffer::connectNotify +104 (int (*)(...))QBuffer::disconnectNotify +112 (int (*)(...))QIODevice::isSequential +120 (int (*)(...))QBuffer::open +128 (int (*)(...))QBuffer::close +136 (int (*)(...))QBuffer::pos +144 (int (*)(...))QBuffer::size +152 (int (*)(...))QBuffer::seek +160 (int (*)(...))QBuffer::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QBuffer::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBuffer::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBuffer::writeData + +Class QBuffer + size=16 align=8 + base size=16 base align=8 +QBuffer (0x0x7f75808f4af8) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f75808f4b60) 0 + primary-for QBuffer (0x0x7f75808f4af8) + QObject (0x0x7f7580a06d80) 0 + primary-for QIODevice (0x0x7f75808f4b60) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f7580a06e40) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f7580a06f00) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f75807fb2a0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f75807fb300) 0 + +Vtable for QTextStream +QTextStream::_ZTV11QTextStream: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTextStream) +16 (int (*)(...))QTextStream::~QTextStream +24 (int (*)(...))QTextStream::~QTextStream + +Class QTextStream + size=16 align=8 + base size=16 base align=8 +QTextStream (0x0x7f75807fb3c0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f75807fb5a0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f75807fb7e0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f75807fbae0) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f75807fba80) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f75807fbc60) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f75807fbd20) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f75807fbf00) 0 empty + +Vtable for QFileDevice +QFileDevice::_ZTV11QFileDevice: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QFileDevice) +16 (int (*)(...))QFileDevice::metaObject +24 (int (*)(...))QFileDevice::qt_metacast +32 (int (*)(...))QFileDevice::qt_metacall +40 (int (*)(...))QFileDevice::~QFileDevice +48 (int (*)(...))QFileDevice::~QFileDevice +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFileDevice::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QFileDevice::fileName +248 (int (*)(...))QFileDevice::resize +256 (int (*)(...))QFileDevice::permissions +264 (int (*)(...))QFileDevice::setPermissions + +Class QFileDevice + size=16 align=8 + base size=16 base align=8 +QFileDevice (0x0x7f758055d340) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f758055d3a8) 0 + primary-for QFileDevice (0x0x7f758055d340) + QObject (0x0x7f75807fbea0) 0 + primary-for QIODevice (0x0x7f758055d3a8) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f75806330c0) 0 empty + +Vtable for QFile +QFile::_ZTV5QFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI5QFile) +16 (int (*)(...))QFile::metaObject +24 (int (*)(...))QFile::qt_metacast +32 (int (*)(...))QFile::qt_metacall +40 (int (*)(...))QFile::~QFile +48 (int (*)(...))QFile::~QFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QFile::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFile::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QFile::fileName +248 (int (*)(...))QFile::resize +256 (int (*)(...))QFile::permissions +264 (int (*)(...))QFile::setPermissions + +Class QFile + size=16 align=8 + base size=16 base align=8 +QFile (0x0x7f758055d4e0) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f758055d548) 0 + primary-for QFile (0x0x7f758055d4e0) + QIODevice (0x0x7f758055d5b0) 0 + primary-for QFileDevice (0x0x7f758055d548) + QObject (0x0x7f7580633060) 0 + primary-for QIODevice (0x0x7f758055d5b0) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f75806331e0) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f75806334e0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f7580633840) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f7580633a20) 0 empty + +Vtable for QFileSelector +QFileSelector::_ZTV13QFileSelector: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QFileSelector) +16 (int (*)(...))QFileSelector::metaObject +24 (int (*)(...))QFileSelector::qt_metacast +32 (int (*)(...))QFileSelector::qt_metacall +40 (int (*)(...))QFileSelector::~QFileSelector +48 (int (*)(...))QFileSelector::~QFileSelector +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QFileSelector + size=16 align=8 + base size=16 base align=8 +QFileSelector (0x0x7f758055da90) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f75806339c0) 0 + primary-for QFileSelector (0x0x7f758055da90) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f7580633ae0) 0 empty + +Vtable for QFileSystemWatcher +QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFileSystemWatcher) +16 (int (*)(...))QFileSystemWatcher::metaObject +24 (int (*)(...))QFileSystemWatcher::qt_metacast +32 (int (*)(...))QFileSystemWatcher::qt_metacall +40 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher +48 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QFileSystemWatcher + size=16 align=8 + base size=16 base align=8 +QFileSystemWatcher (0x0x7f758055daf8) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f7580633a80) 0 + primary-for QFileSystemWatcher (0x0x7f758055daf8) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f7580633b40) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7f7580633cc0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f7580633c60) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f7580633e40) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f75803880c0) 0 empty + +Vtable for QProcess +QProcess::_ZTV8QProcess: 31u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI8QProcess) +16 (int (*)(...))QProcess::metaObject +24 (int (*)(...))QProcess::qt_metacast +32 (int (*)(...))QProcess::qt_metacall +40 (int (*)(...))QProcess::~QProcess +48 (int (*)(...))QProcess::~QProcess +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QProcess::isSequential +120 (int (*)(...))QProcess::open +128 (int (*)(...))QProcess::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QProcess::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QProcess::bytesAvailable +184 (int (*)(...))QProcess::bytesToWrite +192 (int (*)(...))QProcess::canReadLine +200 (int (*)(...))QProcess::waitForReadyRead +208 (int (*)(...))QProcess::waitForBytesWritten +216 (int (*)(...))QProcess::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QProcess::writeData +240 (int (*)(...))QProcess::setupChildProcess + +Class QProcess + size=16 align=8 + base size=16 base align=8 +QProcess (0x0x7f758055dd00) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f758055dd68) 0 + primary-for QProcess (0x0x7f758055dd00) + QObject (0x0x7f7580388060) 0 + primary-for QIODevice (0x0x7f758055dd68) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f7580388120) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f75803882a0) 0 empty + +Vtable for QSaveFile +QSaveFile::_ZTV9QSaveFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QSaveFile) +16 (int (*)(...))QSaveFile::metaObject +24 (int (*)(...))QSaveFile::qt_metacast +32 (int (*)(...))QSaveFile::qt_metacall +40 (int (*)(...))QSaveFile::~QSaveFile +48 (int (*)(...))QSaveFile::~QSaveFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QSaveFile::open +128 (int (*)(...))QSaveFile::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFileDevice::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QSaveFile::writeData +240 (int (*)(...))QSaveFile::fileName +248 (int (*)(...))QFileDevice::resize +256 (int (*)(...))QFileDevice::permissions +264 (int (*)(...))QFileDevice::setPermissions + +Class QSaveFile + size=16 align=8 + base size=16 base align=8 +QSaveFile (0x0x7f758055ddd0) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f758055de38) 0 + primary-for QSaveFile (0x0x7f758055ddd0) + QIODevice (0x0x7f758055dea0) 0 + primary-for QFileDevice (0x0x7f758055de38) + QObject (0x0x7f7580388240) 0 + primary-for QIODevice (0x0x7f758055dea0) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f7580388360) 0 empty + +Vtable for QSettings +QSettings::_ZTV9QSettings: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QSettings) +16 (int (*)(...))QSettings::metaObject +24 (int (*)(...))QSettings::qt_metacast +32 (int (*)(...))QSettings::qt_metacall +40 (int (*)(...))QSettings::~QSettings +48 (int (*)(...))QSettings::~QSettings +56 (int (*)(...))QSettings::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSettings + size=16 align=8 + base size=16 base align=8 +QSettings (0x0x7f758055df08) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f7580388300) 0 + primary-for QSettings (0x0x7f758055df08) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f75803883c0) 0 empty + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f75803884e0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f75803887e0) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f7580388900) 0 empty + +Vtable for QTemporaryFile +QTemporaryFile::_ZTV14QTemporaryFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QTemporaryFile) +16 (int (*)(...))QTemporaryFile::metaObject +24 (int (*)(...))QTemporaryFile::qt_metacast +32 (int (*)(...))QTemporaryFile::qt_metacall +40 (int (*)(...))QTemporaryFile::~QTemporaryFile +48 (int (*)(...))QTemporaryFile::~QTemporaryFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QTemporaryFile::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFile::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QTemporaryFile::fileName +248 (int (*)(...))QFile::resize +256 (int (*)(...))QFile::permissions +264 (int (*)(...))QFile::setPermissions + +Class QTemporaryFile + size=16 align=8 + base size=16 base align=8 +QTemporaryFile (0x0x7f758043b068) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f758043b0d0) 0 + primary-for QTemporaryFile (0x0x7f758043b068) + QFileDevice (0x0x7f758043b138) 0 + primary-for QFile (0x0x7f758043b0d0) + QIODevice (0x0x7f758043b1a0) 0 + primary-for QFileDevice (0x0x7f758043b138) + QObject (0x0x7f75803888a0) 0 + primary-for QIODevice (0x0x7f758043b1a0) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f7580388a20) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f7580388e40) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f7580144060) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f75801441e0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f75801443c0) 0 empty + +Vtable for QAbstractItemModel +QAbstractItemModel::_ZTV18QAbstractItemModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractItemModel) +16 (int (*)(...))QAbstractItemModel::metaObject +24 (int (*)(...))QAbstractItemModel::qt_metacast +32 (int (*)(...))QAbstractItemModel::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractItemModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractItemModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractItemModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractItemModel + size=16 align=8 + base size=16 base align=8 +QAbstractItemModel (0x0x7f758043b680) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f7580144360) 0 + primary-for QAbstractItemModel (0x0x7f758043b680) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f7580144720) 0 empty + +Vtable for QAbstractTableModel +QAbstractTableModel::_ZTV19QAbstractTableModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTableModel) +16 (int (*)(...))QAbstractTableModel::metaObject +24 (int (*)(...))QAbstractTableModel::qt_metacast +32 (int (*)(...))QAbstractTableModel::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractTableModel::index +120 (int (*)(...))QAbstractTableModel::parent +128 (int (*)(...))QAbstractTableModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractTableModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractTableModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractTableModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractTableModel + size=16 align=8 + base size=16 base align=8 +QAbstractTableModel (0x0x7f758043b888) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f758043b8f0) 0 + primary-for QAbstractTableModel (0x0x7f758043b888) + QObject (0x0x7f75801446c0) 0 + primary-for QAbstractItemModel (0x0x7f758043b8f0) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f75801447e0) 0 empty + +Vtable for QAbstractListModel +QAbstractListModel::_ZTV18QAbstractListModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractListModel) +16 (int (*)(...))QAbstractListModel::metaObject +24 (int (*)(...))QAbstractListModel::qt_metacast +32 (int (*)(...))QAbstractListModel::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractListModel::index +120 (int (*)(...))QAbstractListModel::parent +128 (int (*)(...))QAbstractListModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QAbstractListModel::columnCount +152 (int (*)(...))QAbstractListModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractListModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractListModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractListModel + size=16 align=8 + base size=16 base align=8 +QAbstractListModel (0x0x7f758043b958) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f758043b9c0) 0 + primary-for QAbstractListModel (0x0x7f758043b958) + QObject (0x0x7f7580144780) 0 + primary-for QAbstractItemModel (0x0x7f758043b9c0) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f7580144ae0) 0 empty + +Vtable for QAbstractProxyModel +QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractProxyModel) +16 (int (*)(...))QAbstractProxyModel::metaObject +24 (int (*)(...))QAbstractProxyModel::qt_metacast +32 (int (*)(...))QAbstractProxyModel::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractProxyModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QAbstractProxyModel::headerData +184 (int (*)(...))QAbstractProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QAbstractProxyModel::mimeTypes +216 (int (*)(...))QAbstractProxyModel::mimeData +224 (int (*)(...))QAbstractProxyModel::canDropMimeData +232 (int (*)(...))QAbstractProxyModel::dropMimeData +240 (int (*)(...))QAbstractProxyModel::supportedDropActions +248 (int (*)(...))QAbstractProxyModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QAbstractProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QAbstractProxyModel::setSourceModel +392 (int (*)(...))__cxa_pure_virtual +400 (int (*)(...))__cxa_pure_virtual +408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource +416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource + +Class QAbstractProxyModel + size=16 align=8 + base size=16 base align=8 +QAbstractProxyModel (0x0x7f758043baf8) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f758043bb60) 0 + primary-for QAbstractProxyModel (0x0x7f758043baf8) + QObject (0x0x7f7580144a80) 0 + primary-for QAbstractItemModel (0x0x7f758043bb60) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f7580144ba0) 0 empty + +Vtable for QIdentityProxyModel +QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QIdentityProxyModel) +16 (int (*)(...))QIdentityProxyModel::metaObject +24 (int (*)(...))QIdentityProxyModel::qt_metacast +32 (int (*)(...))QIdentityProxyModel::qt_metacall +40 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel +48 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QIdentityProxyModel::index +120 (int (*)(...))QIdentityProxyModel::parent +128 (int (*)(...))QIdentityProxyModel::sibling +136 (int (*)(...))QIdentityProxyModel::rowCount +144 (int (*)(...))QIdentityProxyModel::columnCount +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QIdentityProxyModel::headerData +184 (int (*)(...))QAbstractProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QAbstractProxyModel::mimeTypes +216 (int (*)(...))QAbstractProxyModel::mimeData +224 (int (*)(...))QAbstractProxyModel::canDropMimeData +232 (int (*)(...))QIdentityProxyModel::dropMimeData +240 (int (*)(...))QAbstractProxyModel::supportedDropActions +248 (int (*)(...))QAbstractProxyModel::supportedDragActions +256 (int (*)(...))QIdentityProxyModel::insertRows +264 (int (*)(...))QIdentityProxyModel::insertColumns +272 (int (*)(...))QIdentityProxyModel::removeRows +280 (int (*)(...))QIdentityProxyModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QAbstractProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QIdentityProxyModel::match +352 (int (*)(...))QAbstractProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QIdentityProxyModel::setSourceModel +392 (int (*)(...))QIdentityProxyModel::mapToSource +400 (int (*)(...))QIdentityProxyModel::mapFromSource +408 (int (*)(...))QIdentityProxyModel::mapSelectionToSource +416 (int (*)(...))QIdentityProxyModel::mapSelectionFromSource + +Class QIdentityProxyModel + size=16 align=8 + base size=16 base align=8 +QIdentityProxyModel (0x0x7f758043bbc8) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f758043bc30) 0 + primary-for QIdentityProxyModel (0x0x7f758043bbc8) + QAbstractItemModel (0x0x7f758043bc98) 0 + primary-for QAbstractProxyModel (0x0x7f758043bc30) + QObject (0x0x7f7580144b40) 0 + primary-for QAbstractItemModel (0x0x7f758043bc98) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f7580144c00) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f7580144de0) 0 empty + +Vtable for QItemSelectionModel +QItemSelectionModel::_ZTV19QItemSelectionModel: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QItemSelectionModel) +16 (int (*)(...))QItemSelectionModel::metaObject +24 (int (*)(...))QItemSelectionModel::qt_metacast +32 (int (*)(...))QItemSelectionModel::qt_metacall +40 (int (*)(...))QItemSelectionModel::~QItemSelectionModel +48 (int (*)(...))QItemSelectionModel::~QItemSelectionModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QItemSelectionModel::setCurrentIndex +120 (int (*)(...))QItemSelectionModel::select +128 (int (*)(...))QItemSelectionModel::select +136 (int (*)(...))QItemSelectionModel::clear +144 (int (*)(...))QItemSelectionModel::reset +152 (int (*)(...))QItemSelectionModel::clearCurrentIndex + +Class QItemSelectionModel + size=16 align=8 + base size=16 base align=8 +QItemSelectionModel (0x0x7f758043bdd0) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f7580144d80) 0 + primary-for QItemSelectionModel (0x0x7f758043bdd0) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f757ff17000) 0 + QList (0x0x7f757ff17068) 0 + QListSpecialMethods (0x0x7f757fef2060) 0 empty + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f757fef2480) 0 empty + +Vtable for QSortFilterProxyModel +QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QSortFilterProxyModel) +16 (int (*)(...))QSortFilterProxyModel::metaObject +24 (int (*)(...))QSortFilterProxyModel::qt_metacast +32 (int (*)(...))QSortFilterProxyModel::qt_metacall +40 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel +48 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSortFilterProxyModel::index +120 (int (*)(...))QSortFilterProxyModel::parent +128 (int (*)(...))QSortFilterProxyModel::sibling +136 (int (*)(...))QSortFilterProxyModel::rowCount +144 (int (*)(...))QSortFilterProxyModel::columnCount +152 (int (*)(...))QSortFilterProxyModel::hasChildren +160 (int (*)(...))QSortFilterProxyModel::data +168 (int (*)(...))QSortFilterProxyModel::setData +176 (int (*)(...))QSortFilterProxyModel::headerData +184 (int (*)(...))QSortFilterProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QSortFilterProxyModel::mimeTypes +216 (int (*)(...))QSortFilterProxyModel::mimeData +224 (int (*)(...))QAbstractProxyModel::canDropMimeData +232 (int (*)(...))QSortFilterProxyModel::dropMimeData +240 (int (*)(...))QSortFilterProxyModel::supportedDropActions +248 (int (*)(...))QAbstractProxyModel::supportedDragActions +256 (int (*)(...))QSortFilterProxyModel::insertRows +264 (int (*)(...))QSortFilterProxyModel::insertColumns +272 (int (*)(...))QSortFilterProxyModel::removeRows +280 (int (*)(...))QSortFilterProxyModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QSortFilterProxyModel::fetchMore +312 (int (*)(...))QSortFilterProxyModel::canFetchMore +320 (int (*)(...))QSortFilterProxyModel::flags +328 (int (*)(...))QSortFilterProxyModel::sort +336 (int (*)(...))QSortFilterProxyModel::buddy +344 (int (*)(...))QSortFilterProxyModel::match +352 (int (*)(...))QSortFilterProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QSortFilterProxyModel::setSourceModel +392 (int (*)(...))QSortFilterProxyModel::mapToSource +400 (int (*)(...))QSortFilterProxyModel::mapFromSource +408 (int (*)(...))QSortFilterProxyModel::mapSelectionToSource +416 (int (*)(...))QSortFilterProxyModel::mapSelectionFromSource +424 (int (*)(...))QSortFilterProxyModel::filterAcceptsRow +432 (int (*)(...))QSortFilterProxyModel::filterAcceptsColumn +440 (int (*)(...))QSortFilterProxyModel::lessThan + +Class QSortFilterProxyModel + size=16 align=8 + base size=16 base align=8 +QSortFilterProxyModel (0x0x7f757ff17138) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f757ff171a0) 0 + primary-for QSortFilterProxyModel (0x0x7f757ff17138) + QAbstractItemModel (0x0x7f757ff17208) 0 + primary-for QAbstractProxyModel (0x0x7f757ff171a0) + QObject (0x0x7f757fef2420) 0 + primary-for QAbstractItemModel (0x0x7f757ff17208) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f757fef2540) 0 empty + +Vtable for QStringListModel +QStringListModel::_ZTV16QStringListModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QStringListModel) +16 (int (*)(...))QStringListModel::metaObject +24 (int (*)(...))QStringListModel::qt_metacast +32 (int (*)(...))QStringListModel::qt_metacall +40 (int (*)(...))QStringListModel::~QStringListModel +48 (int (*)(...))QStringListModel::~QStringListModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractListModel::index +120 (int (*)(...))QAbstractListModel::parent +128 (int (*)(...))QStringListModel::sibling +136 (int (*)(...))QStringListModel::rowCount +144 (int (*)(...))QAbstractListModel::columnCount +152 (int (*)(...))QAbstractListModel::hasChildren +160 (int (*)(...))QStringListModel::data +168 (int (*)(...))QStringListModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractListModel::dropMimeData +240 (int (*)(...))QStringListModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QStringListModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QStringListModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QStringListModel::flags +328 (int (*)(...))QStringListModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QStringListModel + size=24 align=8 + base size=24 base align=8 +QStringListModel (0x0x7f757ff17270) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f757ff172d8) 0 + primary-for QStringListModel (0x0x7f757ff17270) + QAbstractItemModel (0x0x7f757ff17340) 0 + primary-for QAbstractListModel (0x0x7f757ff172d8) + QObject (0x0x7f757fef24e0) 0 + primary-for QAbstractItemModel (0x0x7f757ff17340) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f757fef25a0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f757fef2660) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f757fef2720) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f757fef2780) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f757fef2840) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f757fef28a0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f757fef27e0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f757fef2900) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f757fef2960) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f757fef2a20) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f757fef2a80) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f757fef29c0) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f757fef2ba0) 0 empty + +Vtable for QEventLoop +QEventLoop::_ZTV10QEventLoop: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QEventLoop) +16 (int (*)(...))QEventLoop::metaObject +24 (int (*)(...))QEventLoop::qt_metacast +32 (int (*)(...))QEventLoop::qt_metacall +40 (int (*)(...))QEventLoop::~QEventLoop +48 (int (*)(...))QEventLoop::~QEventLoop +56 (int (*)(...))QEventLoop::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QEventLoop + size=16 align=8 + base size=16 base align=8 +QEventLoop (0x0x7f757ff173a8) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f757fef2b40) 0 + primary-for QEventLoop (0x0x7f757ff173a8) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f757fef2cc0) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f757fef2d80) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f757fef2de0) 0 + +Vtable for QAbstractEventDispatcher +QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher) +16 (int (*)(...))QAbstractEventDispatcher::metaObject +24 (int (*)(...))QAbstractEventDispatcher::qt_metacast +32 (int (*)(...))QAbstractEventDispatcher::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual +184 (int (*)(...))__cxa_pure_virtual +192 (int (*)(...))__cxa_pure_virtual +200 (int (*)(...))__cxa_pure_virtual +208 (int (*)(...))QAbstractEventDispatcher::startingUp +216 (int (*)(...))QAbstractEventDispatcher::closingDown + +Class QAbstractEventDispatcher + size=16 align=8 + base size=16 base align=8 +QAbstractEventDispatcher (0x0x7f757ff174e0) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f757fef2d20) 0 + primary-for QAbstractEventDispatcher (0x0x7f757ff174e0) + +Vtable for QAbstractNativeEventFilter +QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class QAbstractNativeEventFilter + size=16 align=8 + base size=16 base align=8 +QAbstractNativeEventFilter (0x0x7f757fef2e40) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f757fef2ea0) 0 + +Vtable for QEvent +QEvent::_ZTV6QEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QEvent) +16 (int (*)(...))QEvent::~QEvent +24 (int (*)(...))QEvent::~QEvent + +Class QEvent + size=24 align=8 + base size=20 base align=8 +QEvent (0x0x7f757fcc7060) 0 + vptr=((& QEvent::_ZTV6QEvent) + 16u) + +Vtable for QTimerEvent +QTimerEvent::_ZTV11QTimerEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTimerEvent) +16 (int (*)(...))QTimerEvent::~QTimerEvent +24 (int (*)(...))QTimerEvent::~QTimerEvent + +Class QTimerEvent + size=24 align=8 + base size=24 base align=8 +QTimerEvent (0x0x7f757ff175b0) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f757fcc70c0) 0 + primary-for QTimerEvent (0x0x7f757ff175b0) + +Vtable for QChildEvent +QChildEvent::_ZTV11QChildEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QChildEvent) +16 (int (*)(...))QChildEvent::~QChildEvent +24 (int (*)(...))QChildEvent::~QChildEvent + +Class QChildEvent + size=32 align=8 + base size=32 base align=8 +QChildEvent (0x0x7f757ff17618) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f757fcc7120) 0 + primary-for QChildEvent (0x0x7f757ff17618) + +Vtable for QDynamicPropertyChangeEvent +QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI27QDynamicPropertyChangeEvent) +16 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent +24 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent + +Class QDynamicPropertyChangeEvent + size=32 align=8 + base size=32 base align=8 +QDynamicPropertyChangeEvent (0x0x7f757ff17680) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f757fcc7180) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f757ff17680) + +Vtable for QDeferredDeleteEvent +QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QDeferredDeleteEvent) +16 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent +24 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent + +Class QDeferredDeleteEvent + size=24 align=8 + base size=24 base align=8 +QDeferredDeleteEvent (0x0x7f757ff176e8) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f757fcc71e0) 0 + primary-for QDeferredDeleteEvent (0x0x7f757ff176e8) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f757fcc72a0) 0 empty + +Vtable for QCoreApplication +QCoreApplication::_ZTV16QCoreApplication: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QCoreApplication) +16 (int (*)(...))QCoreApplication::metaObject +24 (int (*)(...))QCoreApplication::qt_metacast +32 (int (*)(...))QCoreApplication::qt_metacall +40 (int (*)(...))QCoreApplication::~QCoreApplication +48 (int (*)(...))QCoreApplication::~QCoreApplication +56 (int (*)(...))QCoreApplication::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QCoreApplication::notify +120 (int (*)(...))QCoreApplication::compressEvent + +Class QCoreApplication + size=16 align=8 + base size=16 base align=8 +QCoreApplication (0x0x7f757ff17750) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f757fcc7240) 0 + primary-for QCoreApplication (0x0x7f757ff17750) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f757fcc7300) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f757fcc7480) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f757fcc7600) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f757fcc7780) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f757fcc77e0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f757fcc79c0) 0 empty + +Vtable for QMimeData +QMimeData::_ZTV9QMimeData: 17u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QMimeData) +16 (int (*)(...))QMimeData::metaObject +24 (int (*)(...))QMimeData::qt_metacast +32 (int (*)(...))QMimeData::qt_metacall +40 (int (*)(...))QMimeData::~QMimeData +48 (int (*)(...))QMimeData::~QMimeData +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QMimeData::hasFormat +120 (int (*)(...))QMimeData::formats +128 (int (*)(...))QMimeData::retrieveData + +Class QMimeData + size=16 align=8 + base size=16 base align=8 +QMimeData (0x0x7f757ff178f0) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f757fcc7960) 0 + primary-for QMimeData (0x0x7f757ff178f0) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f757fcc7a80) 0 empty + +Vtable for QObjectCleanupHandler +QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QObjectCleanupHandler) +16 (int (*)(...))QObjectCleanupHandler::metaObject +24 (int (*)(...))QObjectCleanupHandler::qt_metacast +32 (int (*)(...))QObjectCleanupHandler::qt_metacall +40 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler +48 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QObjectCleanupHandler + size=24 align=8 + base size=24 base align=8 +QObjectCleanupHandler (0x0x7f757ff17958) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f757fcc7a20) 0 + primary-for QObjectCleanupHandler (0x0x7f757ff17958) + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f757fcc7ae0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f757fcc7c60) 0 + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f757fad12a0) 0 empty + +Vtable for QSharedMemory +QSharedMemory::_ZTV13QSharedMemory: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QSharedMemory) +16 (int (*)(...))QSharedMemory::metaObject +24 (int (*)(...))QSharedMemory::qt_metacast +32 (int (*)(...))QSharedMemory::qt_metacall +40 (int (*)(...))QSharedMemory::~QSharedMemory +48 (int (*)(...))QSharedMemory::~QSharedMemory +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSharedMemory + size=16 align=8 + base size=16 base align=8 +QSharedMemory (0x0x7f757ff17d68) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f757fad1240) 0 + primary-for QSharedMemory (0x0x7f757ff17d68) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f757fad1360) 0 empty + +Vtable for QSignalMapper +QSignalMapper::_ZTV13QSignalMapper: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QSignalMapper) +16 (int (*)(...))QSignalMapper::metaObject +24 (int (*)(...))QSignalMapper::qt_metacast +32 (int (*)(...))QSignalMapper::qt_metacall +40 (int (*)(...))QSignalMapper::~QSignalMapper +48 (int (*)(...))QSignalMapper::~QSignalMapper +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSignalMapper + size=16 align=8 + base size=16 base align=8 +QSignalMapper (0x0x7f757ff17dd0) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f757fad1300) 0 + primary-for QSignalMapper (0x0x7f757ff17dd0) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f757fad1420) 0 empty + +Vtable for QSocketNotifier +QSocketNotifier::_ZTV15QSocketNotifier: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QSocketNotifier) +16 (int (*)(...))QSocketNotifier::metaObject +24 (int (*)(...))QSocketNotifier::qt_metacast +32 (int (*)(...))QSocketNotifier::qt_metacall +40 (int (*)(...))QSocketNotifier::~QSocketNotifier +48 (int (*)(...))QSocketNotifier::~QSocketNotifier +56 (int (*)(...))QSocketNotifier::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSocketNotifier + size=16 align=8 + base size=16 base align=8 +QSocketNotifier (0x0x7f757ff17e38) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f757fad13c0) 0 + primary-for QSocketNotifier (0x0x7f757ff17e38) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f757fad1480) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f757fad15a0) 0 empty + +Vtable for QTimer +QTimer::_ZTV6QTimer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QTimer) +16 (int (*)(...))QTimer::metaObject +24 (int (*)(...))QTimer::qt_metacast +32 (int (*)(...))QTimer::qt_metacall +40 (int (*)(...))QTimer::~QTimer +48 (int (*)(...))QTimer::~QTimer +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QTimer::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QTimer + size=32 align=8 + base size=29 base align=8 +QTimer (0x0x7f757ff17ea0) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f757fad1540) 0 + primary-for QTimer (0x0x7f757ff17ea0) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f757fad1720) 0 empty + +Vtable for QTranslator +QTranslator::_ZTV11QTranslator: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTranslator) +16 (int (*)(...))QTranslator::metaObject +24 (int (*)(...))QTranslator::qt_metacast +32 (int (*)(...))QTranslator::qt_metacall +40 (int (*)(...))QTranslator::~QTranslator +48 (int (*)(...))QTranslator::~QTranslator +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QTranslator::translate +120 (int (*)(...))QTranslator::isEmpty + +Class QTranslator + size=16 align=8 + base size=16 base align=8 +QTranslator (0x0x7f757ff17f70) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f757fad16c0) 0 + primary-for QTranslator (0x0x7f757ff17f70) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f757fad1780) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f757fad1960) 0 + +Vtable for QFactoryInterface +QFactoryInterface::_ZTV17QFactoryInterface: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QFactoryInterface) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class QFactoryInterface + size=8 align=8 + base size=8 base align=8 +QFactoryInterface (0x0x7f757fad19c0) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f757fad1ae0) 0 empty + +Vtable for QLibrary +QLibrary::_ZTV8QLibrary: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI8QLibrary) +16 (int (*)(...))QLibrary::metaObject +24 (int (*)(...))QLibrary::qt_metacast +32 (int (*)(...))QLibrary::qt_metacall +40 (int (*)(...))QLibrary::~QLibrary +48 (int (*)(...))QLibrary::~QLibrary +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QLibrary + size=32 align=8 + base size=25 base align=8 +QLibrary (0x0x7f757ff17c98) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f757fad1a80) 0 + primary-for QLibrary (0x0x7f757ff17c98) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f757fad1c00) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f757fad1de0) 0 empty + +Vtable for QPluginLoader +QPluginLoader::_ZTV13QPluginLoader: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QPluginLoader) +16 (int (*)(...))QPluginLoader::metaObject +24 (int (*)(...))QPluginLoader::qt_metacast +32 (int (*)(...))QPluginLoader::qt_metacall +40 (int (*)(...))QPluginLoader::~QPluginLoader +48 (int (*)(...))QPluginLoader::~QPluginLoader +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QPluginLoader + size=32 align=8 + base size=25 base align=8 +QPluginLoader (0x0x7f757fbab0d0) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f757fad1d80) 0 + primary-for QPluginLoader (0x0x7f757fbab0d0) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f757fad1e40) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f757fbf7060) 0 empty + +Vtable for QAbstractState +QAbstractState::_ZTV14QAbstractState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QAbstractState) +16 (int (*)(...))QAbstractState::metaObject +24 (int (*)(...))QAbstractState::qt_metacast +32 (int (*)(...))QAbstractState::qt_metacall +40 0u +48 0u +56 (int (*)(...))QAbstractState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QAbstractState + size=16 align=8 + base size=16 base align=8 +QAbstractState (0x0x7f757fbab1a0) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f757fbf7000) 0 + primary-for QAbstractState (0x0x7f757fbab1a0) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f757fbf7120) 0 empty + +Vtable for QAbstractTransition +QAbstractTransition::_ZTV19QAbstractTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTransition) +16 (int (*)(...))QAbstractTransition::metaObject +24 (int (*)(...))QAbstractTransition::qt_metacast +32 (int (*)(...))QAbstractTransition::qt_metacall +40 0u +48 0u +56 (int (*)(...))QAbstractTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QAbstractTransition + size=16 align=8 + base size=16 base align=8 +QAbstractTransition (0x0x7f757fbab208) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f757fbf70c0) 0 + primary-for QAbstractTransition (0x0x7f757fbab208) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f757fbf71e0) 0 empty + +Vtable for QEventTransition +QEventTransition::_ZTV16QEventTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QEventTransition) +16 (int (*)(...))QEventTransition::metaObject +24 (int (*)(...))QEventTransition::qt_metacast +32 (int (*)(...))QEventTransition::qt_metacall +40 (int (*)(...))QEventTransition::~QEventTransition +48 (int (*)(...))QEventTransition::~QEventTransition +56 (int (*)(...))QEventTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QEventTransition::eventTest +120 (int (*)(...))QEventTransition::onTransition + +Class QEventTransition + size=16 align=8 + base size=16 base align=8 +QEventTransition (0x0x7f757fbab270) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f757fbab2d8) 0 + primary-for QEventTransition (0x0x7f757fbab270) + QObject (0x0x7f757fbf7180) 0 + primary-for QAbstractTransition (0x0x7f757fbab2d8) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f757fbf72a0) 0 empty + +Vtable for QFinalState +QFinalState::_ZTV11QFinalState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QFinalState) +16 (int (*)(...))QFinalState::metaObject +24 (int (*)(...))QFinalState::qt_metacast +32 (int (*)(...))QFinalState::qt_metacall +40 (int (*)(...))QFinalState::~QFinalState +48 (int (*)(...))QFinalState::~QFinalState +56 (int (*)(...))QFinalState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFinalState::onEntry +120 (int (*)(...))QFinalState::onExit + +Class QFinalState + size=16 align=8 + base size=16 base align=8 +QFinalState (0x0x7f757fbab340) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f757fbab3a8) 0 + primary-for QFinalState (0x0x7f757fbab340) + QObject (0x0x7f757fbf7240) 0 + primary-for QAbstractState (0x0x7f757fbab3a8) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f757fbf7360) 0 empty + +Vtable for QHistoryState +QHistoryState::_ZTV13QHistoryState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QHistoryState) +16 (int (*)(...))QHistoryState::metaObject +24 (int (*)(...))QHistoryState::qt_metacast +32 (int (*)(...))QHistoryState::qt_metacall +40 (int (*)(...))QHistoryState::~QHistoryState +48 (int (*)(...))QHistoryState::~QHistoryState +56 (int (*)(...))QHistoryState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QHistoryState::onEntry +120 (int (*)(...))QHistoryState::onExit + +Class QHistoryState + size=16 align=8 + base size=16 base align=8 +QHistoryState (0x0x7f757fbab410) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f757fbab478) 0 + primary-for QHistoryState (0x0x7f757fbab410) + QObject (0x0x7f757fbf7300) 0 + primary-for QAbstractState (0x0x7f757fbab478) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f757fbf7420) 0 empty + +Vtable for QSignalTransition +QSignalTransition::_ZTV17QSignalTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QSignalTransition) +16 (int (*)(...))QSignalTransition::metaObject +24 (int (*)(...))QSignalTransition::qt_metacast +32 (int (*)(...))QSignalTransition::qt_metacall +40 (int (*)(...))QSignalTransition::~QSignalTransition +48 (int (*)(...))QSignalTransition::~QSignalTransition +56 (int (*)(...))QSignalTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSignalTransition::eventTest +120 (int (*)(...))QSignalTransition::onTransition + +Class QSignalTransition + size=16 align=8 + base size=16 base align=8 +QSignalTransition (0x0x7f757fbab4e0) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f757fbab548) 0 + primary-for QSignalTransition (0x0x7f757fbab4e0) + QObject (0x0x7f757fbf73c0) 0 + primary-for QAbstractTransition (0x0x7f757fbab548) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f757fbf74e0) 0 empty + +Vtable for QState +QState::_ZTV6QState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QState) +16 (int (*)(...))QState::metaObject +24 (int (*)(...))QState::qt_metacast +32 (int (*)(...))QState::qt_metacall +40 (int (*)(...))QState::~QState +48 (int (*)(...))QState::~QState +56 (int (*)(...))QState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QState::onEntry +120 (int (*)(...))QState::onExit + +Class QState + size=16 align=8 + base size=16 base align=8 +QState (0x0x7f757fbab5b0) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f757fbab618) 0 + primary-for QState (0x0x7f757fbab5b0) + QObject (0x0x7f757fbf7480) 0 + primary-for QAbstractState (0x0x7f757fbab618) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f757fbf7600) 0 empty + +Vtable for QStateMachine::SignalEvent +QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN13QStateMachine11SignalEventE) +16 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent +24 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent + +Class QStateMachine::SignalEvent + size=48 align=8 + base size=48 base align=8 +QStateMachine::SignalEvent (0x0x7f757fbab7b8) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f757fbf7660) 0 + primary-for QStateMachine::SignalEvent (0x0x7f757fbab7b8) + +Vtable for QStateMachine::WrappedEvent +QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN13QStateMachine12WrappedEventE) +16 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent +24 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent + +Class QStateMachine::WrappedEvent + size=40 align=8 + base size=40 base align=8 +QStateMachine::WrappedEvent (0x0x7f757fbab820) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f757fbf76c0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f757fbab820) + +Vtable for QStateMachine +QStateMachine::_ZTV13QStateMachine: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QStateMachine) +16 (int (*)(...))QStateMachine::metaObject +24 (int (*)(...))QStateMachine::qt_metacast +32 (int (*)(...))QStateMachine::qt_metacall +40 (int (*)(...))QStateMachine::~QStateMachine +48 (int (*)(...))QStateMachine::~QStateMachine +56 (int (*)(...))QStateMachine::event +64 (int (*)(...))QStateMachine::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QStateMachine::onEntry +120 (int (*)(...))QStateMachine::onExit +128 (int (*)(...))QStateMachine::beginSelectTransitions +136 (int (*)(...))QStateMachine::endSelectTransitions +144 (int (*)(...))QStateMachine::beginMicrostep +152 (int (*)(...))QStateMachine::endMicrostep + +Class QStateMachine + size=16 align=8 + base size=16 base align=8 +QStateMachine (0x0x7f757fbab680) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f757fbab6e8) 0 + primary-for QStateMachine (0x0x7f757fbab680) + QAbstractState (0x0x7f757fbab750) 0 + primary-for QState (0x0x7f757fbab6e8) + QObject (0x0x7f757fbf75a0) 0 + primary-for QAbstractState (0x0x7f757fbab750) + +Vtable for QException +QException::_ZTV10QException: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QException) +16 (int (*)(...))QException::~QException +24 (int (*)(...))QException::~QException +32 (int (*)(...))std::exception::what +40 (int (*)(...))QException::raise +48 (int (*)(...))QException::clone + +Class QException + size=8 align=8 + base size=8 base align=8 +QException (0x0x7f757fbab888) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f757fbf7720) 0 nearly-empty + primary-for QException (0x0x7f757fbab888) + +Vtable for QUnhandledException +QUnhandledException::_ZTV19QUnhandledException: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QUnhandledException) +16 (int (*)(...))QUnhandledException::~QUnhandledException +24 (int (*)(...))QUnhandledException::~QUnhandledException +32 (int (*)(...))std::exception::what +40 (int (*)(...))QUnhandledException::raise +48 (int (*)(...))QUnhandledException::clone + +Class QUnhandledException + size=8 align=8 + base size=8 base align=8 +QUnhandledException (0x0x7f757fbab8f0) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f757fbab958) 0 nearly-empty + primary-for QUnhandledException (0x0x7f757fbab8f0) + std::exception (0x0x7f757fbf7780) 0 nearly-empty + primary-for QException (0x0x7f757fbab958) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f757fbf77e0) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f757fbf78a0) 0 + +Vtable for QRunnable +QRunnable::_ZTV9QRunnable: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QRunnable) +16 (int (*)(...))__cxa_pure_virtual +24 0u +32 0u + +Class QRunnable + size=16 align=8 + base size=12 base align=8 +QRunnable (0x0x7f757fbf7900) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f757fbf7960) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f757fbabaf8) 0 + QBasicMutex (0x0x7f757fbf7ae0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f757fbf7b40) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f757fbf7c00) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f757fbf7c60) 0 + +Vtable for QtPrivate::ResultStoreBase +QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9QtPrivate15ResultStoreBaseE) +16 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase +24 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase + +Class QtPrivate::ResultStoreBase + size=48 align=8 + base size=44 base align=8 +QtPrivate::ResultStoreBase (0x0x7f757fbf7de0) 0 + vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16u) + +Vtable for QFutureInterfaceBase +QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QFutureInterfaceBase) +16 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase +24 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase + +Class QFutureInterfaceBase + size=16 align=8 + base size=16 base align=8 +QFutureInterfaceBase (0x0x7f757fbf7ea0) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f757f976240) 0 empty + +Vtable for QFutureWatcherBase +QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFutureWatcherBase) +16 (int (*)(...))QFutureWatcherBase::metaObject +24 (int (*)(...))QFutureWatcherBase::qt_metacast +32 (int (*)(...))QFutureWatcherBase::qt_metacall +40 0u +48 0u +56 (int (*)(...))QFutureWatcherBase::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QFutureWatcherBase::connectNotify +104 (int (*)(...))QFutureWatcherBase::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QFutureWatcherBase + size=16 align=8 + base size=16 base align=8 +QFutureWatcherBase (0x0x7f757f9373a8) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f757f9761e0) 0 + primary-for QFutureWatcherBase (0x0x7f757f9373a8) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f757f976360) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f757f9763c0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f757f976420) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f757f976480) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f757f976540) 0 empty + +Vtable for QThread +QThread::_ZTV7QThread: 15u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QThread) +16 (int (*)(...))QThread::metaObject +24 (int (*)(...))QThread::qt_metacast +32 (int (*)(...))QThread::qt_metacall +40 (int (*)(...))QThread::~QThread +48 (int (*)(...))QThread::~QThread +56 (int (*)(...))QThread::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QThread::run + +Class QThread + size=16 align=8 + base size=16 base align=8 +QThread (0x0x7f757f937820) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f757f9764e0) 0 + primary-for QThread (0x0x7f757f937820) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f757f976600) 0 empty + +Vtable for QThreadPool +QThreadPool::_ZTV11QThreadPool: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QThreadPool) +16 (int (*)(...))QThreadPool::metaObject +24 (int (*)(...))QThreadPool::qt_metacast +32 (int (*)(...))QThreadPool::qt_metacall +40 (int (*)(...))QThreadPool::~QThreadPool +48 (int (*)(...))QThreadPool::~QThreadPool +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QThreadPool + size=16 align=8 + base size=16 base align=8 +QThreadPool (0x0x7f757f937888) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f757f9765a0) 0 + primary-for QThreadPool (0x0x7f757f937888) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f757f976660) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f757f976720) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f757f976c00) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f757f976de0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f757f6fb060) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f757f6fb000) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f757f6fb1e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f757f6fb2a0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f757f6fb540) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f757f6fb720) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f757f6fb780) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f757f6fb7e0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f757f6fb840) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f757f6fb9c0) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f757f6fbb40) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f757f6fbcc0) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7f757f6fbe40) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f757f44d600) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f757f44d780) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f757f44d900) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f757f44d9c0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f757f44dc00) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f757f44de40) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f757f631000) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f757f631180) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f757f6314e0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f757f6316c0) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f757f631a80) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f757f2f04e0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f757f2f0660) 0 empty + +Vtable for QTimeLine +QTimeLine::_ZTV9QTimeLine: 15u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QTimeLine) +16 (int (*)(...))QTimeLine::metaObject +24 (int (*)(...))QTimeLine::qt_metacast +32 (int (*)(...))QTimeLine::qt_metacall +40 (int (*)(...))QTimeLine::~QTimeLine +48 (int (*)(...))QTimeLine::~QTimeLine +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QTimeLine::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QTimeLine::valueForTime + +Class QTimeLine + size=16 align=8 + base size=16 base align=8 +QTimeLine (0x0x7f757f258bc8) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f757f2f0600) 0 + primary-for QTimeLine (0x0x7f757f258bc8) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f757f2f0720) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f757f2f06c0) 0 + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7f757f2f0a80) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7f757f2f0a20) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f757f2f0d80) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f757f2f0f00) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f757f02d068) 0 + QVector (0x0x7f757f012180) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f757f0121e0) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f757f012360) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f757f0124e0) 0 + +Vtable for QXmlStreamEntityResolver +QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QXmlStreamEntityResolver) +16 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver +24 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver +32 (int (*)(...))QXmlStreamEntityResolver::resolveEntity +40 (int (*)(...))QXmlStreamEntityResolver::resolveUndeclaredEntity + +Class QXmlStreamEntityResolver + size=8 align=8 + base size=8 base align=8 +QXmlStreamEntityResolver (0x0x7f757f012660) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f757f0126c0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f757f0127e0) 0 + +Class QGeoAddress + size=8 align=8 + base size=8 base align=8 +QGeoAddress (0x0x7f757f012900) 0 + +Class QGeoCoordinate + size=8 align=8 + base size=8 base align=8 +QGeoCoordinate (0x0x7f757f012c00) 0 + +Class QGeoShape + size=8 align=8 + base size=8 base align=8 +QGeoShape (0x0x7f757f012f00) 0 + +Class QGeoAreaMonitorInfo + size=8 align=8 + base size=8 base align=8 +QGeoAreaMonitorInfo (0x0x7f757f118240) 0 + +Class QGeoPositionInfo + size=8 align=8 + base size=8 base align=8 +QGeoPositionInfo (0x0x7f757f118300) 0 + +Class QGeoPositionInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoPositionInfoSource::QPrivateSignal (0x0x7f757f1183c0) 0 empty + +Vtable for QGeoPositionInfoSource +QGeoPositionInfoSource::_ZTV22QGeoPositionInfoSource: 23u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QGeoPositionInfoSource) +16 (int (*)(...))QGeoPositionInfoSource::metaObject +24 (int (*)(...))QGeoPositionInfoSource::qt_metacast +32 (int (*)(...))QGeoPositionInfoSource::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoPositionInfoSource::setUpdateInterval +120 (int (*)(...))QGeoPositionInfoSource::setPreferredPositioningMethods +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual + +Class QGeoPositionInfoSource + size=24 align=8 + base size=24 base align=8 +QGeoPositionInfoSource (0x0x7f757f02d340) 0 + vptr=((& QGeoPositionInfoSource::_ZTV22QGeoPositionInfoSource) + 16u) + QObject (0x0x7f757f118360) 0 + primary-for QGeoPositionInfoSource (0x0x7f757f02d340) + +Class QGeoAreaMonitorSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoAreaMonitorSource::QPrivateSignal (0x0x7f757f118540) 0 empty + +Vtable for QGeoAreaMonitorSource +QGeoAreaMonitorSource::_ZTV21QGeoAreaMonitorSource: 23u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QGeoAreaMonitorSource) +16 (int (*)(...))QGeoAreaMonitorSource::metaObject +24 (int (*)(...))QGeoAreaMonitorSource::qt_metacast +32 (int (*)(...))QGeoAreaMonitorSource::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoAreaMonitorSource::setPositionInfoSource +120 (int (*)(...))QGeoAreaMonitorSource::positionInfoSource +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual + +Class QGeoAreaMonitorSource + size=24 align=8 + base size=24 base align=8 +QGeoAreaMonitorSource (0x0x7f757f02d478) 0 + vptr=((& QGeoAreaMonitorSource::_ZTV21QGeoAreaMonitorSource) + 16u) + QObject (0x0x7f757f1184e0) 0 + primary-for QGeoAreaMonitorSource (0x0x7f757f02d478) + +Class QGeoCircle + size=8 align=8 + base size=8 base align=8 +QGeoCircle (0x0x7f757f02d4e0) 0 + QGeoShape (0x0x7f757f1185a0) 0 + +Class QGeoLocation + size=8 align=8 + base size=8 base align=8 +QGeoLocation (0x0x7f757f118840) 0 + +Class QGeoSatelliteInfo + size=8 align=8 + base size=8 base align=8 +QGeoSatelliteInfo (0x0x7f757f118b40) 0 + +Class QGeoSatelliteInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoSatelliteInfoSource::QPrivateSignal (0x0x7f757f118c00) 0 empty + +Vtable for QGeoSatelliteInfoSource +QGeoSatelliteInfoSource::_ZTV23QGeoSatelliteInfoSource: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QGeoSatelliteInfoSource) +16 (int (*)(...))QGeoSatelliteInfoSource::metaObject +24 (int (*)(...))QGeoSatelliteInfoSource::qt_metacast +32 (int (*)(...))QGeoSatelliteInfoSource::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoSatelliteInfoSource::setUpdateInterval +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual + +Class QGeoSatelliteInfoSource + size=24 align=8 + base size=24 base align=8 +QGeoSatelliteInfoSource (0x0x7f757f02d618) 0 + vptr=((& QGeoSatelliteInfoSource::_ZTV23QGeoSatelliteInfoSource) + 16u) + QObject (0x0x7f757f118ba0) 0 + primary-for QGeoSatelliteInfoSource (0x0x7f757f02d618) + +Vtable for QGeoPositionInfoSourceFactory +QGeoPositionInfoSourceFactory::_ZTV29QGeoPositionInfoSourceFactory: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI29QGeoPositionInfoSourceFactory) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual +40 (int (*)(...))__cxa_pure_virtual +48 (int (*)(...))__cxa_pure_virtual + +Class QGeoPositionInfoSourceFactory + size=8 align=8 + base size=8 base align=8 +QGeoPositionInfoSourceFactory (0x0x7f757f118cc0) 0 nearly-empty + vptr=((& QGeoPositionInfoSourceFactory::_ZTV29QGeoPositionInfoSourceFactory) + 16u) + +Class QGeoRectangle + size=8 align=8 + base size=8 base align=8 +QGeoRectangle (0x0x7f757f02d680) 0 + QGeoShape (0x0x7f757f118d80) 0 + +Class QNmeaPositionInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNmeaPositionInfoSource::QPrivateSignal (0x0x7f757eded1e0) 0 empty + +Vtable for QNmeaPositionInfoSource +QNmeaPositionInfoSource::_ZTV23QNmeaPositionInfoSource: 24u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QNmeaPositionInfoSource) +16 (int (*)(...))QNmeaPositionInfoSource::metaObject +24 (int (*)(...))QNmeaPositionInfoSource::qt_metacast +32 (int (*)(...))QNmeaPositionInfoSource::qt_metacall +40 (int (*)(...))QNmeaPositionInfoSource::~QNmeaPositionInfoSource +48 (int (*)(...))QNmeaPositionInfoSource::~QNmeaPositionInfoSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QNmeaPositionInfoSource::setUpdateInterval +120 (int (*)(...))QGeoPositionInfoSource::setPreferredPositioningMethods +128 (int (*)(...))QNmeaPositionInfoSource::lastKnownPosition +136 (int (*)(...))QNmeaPositionInfoSource::supportedPositioningMethods +144 (int (*)(...))QNmeaPositionInfoSource::minimumUpdateInterval +152 (int (*)(...))QNmeaPositionInfoSource::error +160 (int (*)(...))QNmeaPositionInfoSource::startUpdates +168 (int (*)(...))QNmeaPositionInfoSource::stopUpdates +176 (int (*)(...))QNmeaPositionInfoSource::requestUpdate +184 (int (*)(...))QNmeaPositionInfoSource::parsePosInfoFromNmeaData + +Class QNmeaPositionInfoSource + size=32 align=8 + base size=32 base align=8 +QNmeaPositionInfoSource (0x0x7f757f02d820) 0 + vptr=((& QNmeaPositionInfoSource::_ZTV23QNmeaPositionInfoSource) + 16u) + QGeoPositionInfoSource (0x0x7f757f02d888) 0 + primary-for QNmeaPositionInfoSource (0x0x7f757f02d820) + QObject (0x0x7f757eded180) 0 + primary-for QGeoPositionInfoSource (0x0x7f757f02d888) + diff --git a/tests/auto/bic/data/QtPositioning.5.7.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtPositioning.5.7.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..cf3f81f --- /dev/null +++ b/tests/auto/bic/data/QtPositioning.5.7.0.linux-gcc-amd64.txt @@ -0,0 +1,4400 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7ff717ebbd80) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7ff717f63540) 0 empty + +Class std::__do_is_nt_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_nt_destructible_impl (0x0x7ff717f63780) 0 empty + +Class std::__do_is_default_constructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_default_constructible_impl (0x0x7ff717f639c0) 0 empty + +Class std::__do_is_static_castable_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_static_castable_impl (0x0x7ff717f63c00) 0 empty + +Class std::__do_is_direct_constructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_direct_constructible_impl (0x0x7ff717f63d80) 0 empty + +Class std::__do_is_nary_constructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_nary_constructible_impl (0x0x7ff717f97180) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7ff715c1b900) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7ff715c1b9c0) 0 empty + +Class std::__result_of_memfun_ref_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_memfun_ref_impl (0x0x7ff715c1bd20) 0 empty + +Class std::__result_of_memfun_deref_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_memfun_deref_impl (0x0x7ff715c1bde0) 0 empty + +Class std::__result_of_memobj_ref_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_memobj_ref_impl (0x0x7ff715c1bea0) 0 empty + +Class std::__result_of_memobj_deref_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_memobj_deref_impl (0x0x7ff715c1bf60) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7ff715c52240) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7ff715c523c0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7ff715c52840) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7ff715c528a0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7ff715cfb540) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7ff715cfb5a0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7ff715c1f750) 0 empty + std::input_iterator_tag (0x0x7ff715cfb600) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7ff715c1f7b8) 0 empty + std::forward_iterator_tag (0x0x7ff715c1f820) 0 empty + std::input_iterator_tag (0x0x7ff715cfb660) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7ff715c1f888) 0 empty + std::bidirectional_iterator_tag (0x0x7ff715c1f8f0) 0 empty + std::forward_iterator_tag (0x0x7ff715c1f958) 0 empty + std::input_iterator_tag (0x0x7ff715cfb6c0) 0 empty + +Class __gnu_cxx::__ops::_Iter_less_iter + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Iter_less_iter (0x0x7ff715d3d360) 0 empty + +Class __gnu_cxx::__ops::_Iter_less_val + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Iter_less_val (0x0x7ff715d3d3c0) 0 empty + +Class __gnu_cxx::__ops::_Val_less_iter + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Val_less_iter (0x0x7ff715d3d420) 0 empty + +Class __gnu_cxx::__ops::_Iter_equal_to_iter + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Iter_equal_to_iter (0x0x7ff715d3d480) 0 empty + +Class __gnu_cxx::__ops::_Iter_equal_to_val + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__ops::_Iter_equal_to_val (0x0x7ff715d3d4e0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7ff715a65000) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7ff715a65240) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7ff715a65300) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7ff715a65360) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7ff715a65420) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7ff715a65480) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7ff715a65900) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7ff715a65960) 0 + +Vtable for std::exception +std::exception::_ZTVSt9exception: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt9exception) +16 (int (*)(...))std::exception::~exception +24 (int (*)(...))std::exception::~exception +32 (int (*)(...))std::exception::what + +Class std::exception + size=8 align=8 + base size=8 base align=8 +std::exception (0x0x7ff715a659c0) 0 nearly-empty + vptr=((& std::exception::_ZTVSt9exception) + 16u) + +Vtable for std::bad_exception +std::bad_exception::_ZTVSt13bad_exception: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt13bad_exception) +16 (int (*)(...))std::bad_exception::~bad_exception +24 (int (*)(...))std::bad_exception::~bad_exception +32 (int (*)(...))std::bad_exception::what + +Class std::bad_exception + size=8 align=8 + base size=8 base align=8 +std::bad_exception (0x0x7ff715c1fea0) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7ff715a65a20) 0 nearly-empty + primary-for std::bad_exception (0x0x7ff715c1fea0) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7ff715a65a80) 0 + +Vtable for std::nested_exception +std::nested_exception::_ZTVSt16nested_exception: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt16nested_exception) +16 (int (*)(...))std::nested_exception::~nested_exception +24 (int (*)(...))std::nested_exception::~nested_exception + +Class std::nested_exception + size=16 align=8 + base size=16 base align=8 +std::nested_exception (0x0x7ff715a65ae0) 0 + vptr=((& std::nested_exception::_ZTVSt16nested_exception) + 16u) + +Vtable for std::bad_alloc +std::bad_alloc::_ZTVSt9bad_alloc: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt9bad_alloc) +16 (int (*)(...))std::bad_alloc::~bad_alloc +24 (int (*)(...))std::bad_alloc::~bad_alloc +32 (int (*)(...))std::bad_alloc::what + +Class std::bad_alloc + size=8 align=8 + base size=8 base align=8 +std::bad_alloc (0x0x7ff715b6f0d0) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7ff715a65f00) 0 nearly-empty + primary-for std::bad_alloc (0x0x7ff715b6f0d0) + +Vtable for std::bad_array_new_length +std::bad_array_new_length::_ZTVSt20bad_array_new_length: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt20bad_array_new_length) +16 (int (*)(...))std::bad_array_new_length::~bad_array_new_length +24 (int (*)(...))std::bad_array_new_length::~bad_array_new_length +32 (int (*)(...))std::bad_array_new_length::what + +Class std::bad_array_new_length + size=8 align=8 + base size=8 base align=8 +std::bad_array_new_length (0x0x7ff715b6f138) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7ff715b6f1a0) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7ff715b6f138) + std::exception (0x0x7ff715a65f60) 0 nearly-empty + primary-for std::bad_alloc (0x0x7ff715b6f1a0) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7ff715b81000) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7ff715b81c00) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7ff715982900) 0 + +Vtable for __cxxabiv1::__forced_unwind +__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class __cxxabiv1::__forced_unwind + size=8 align=8 + base size=8 base align=8 +__cxxabiv1::__forced_unwind (0x0x7ff715982960) 0 nearly-empty + vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16u) + +Class sched_param + size=4 align=4 + base size=4 base align=4 +sched_param (0x0x7ff715678840) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7ff7156788a0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7ff715678960) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7ff7156789c0) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7ff715678a20) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7ff715678a80) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7ff715678ba0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7ff715678c00) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7ff71542f060) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7ff71542f0c0) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7ff7151ca8a0) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7ff7151ca900) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7ff7151fc8a0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7ff714ff96c0) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7ff7151d5f08) 0 + std::iterator (0x0x7ff714ff9780) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7ff7151d5f70) 0 + std::_Bit_iterator_base (0x0x7ff7151d56e8) 0 + std::iterator (0x0x7ff714ff97e0) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7ff7151d5750) 0 + std::_Bit_iterator_base (0x0x7ff7151d5a28) 0 + std::iterator (0x0x7ff714ff9840) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7ff714e26660) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7ff714f21420) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7ff714f213c0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7ff714cc13c0) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7ff713a87e40) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7ff713a87ea0) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7ff71383c2a0) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7ff7138f3780) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7ff7138f37e0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7ff7138f3840) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7ff7138f38a0) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7ff7138f3a20) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7ff7138f3e40) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7ff713948138) 0 + std::__atomic_flag_base (0x0x7ff7138f3ea0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7ff713948888) 0 + QAtomicInteger (0x0x7ff7139488f0) 0 + QBasicAtomicInteger (0x0x7ff71349c420) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7ff7132d4cc0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7ff713115ba0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7ff713291b60) 0 + QGenericArgument (0x0x7ff713115c00) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7ff713115d80) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7ff713115e40) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7ff712df1ea0) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7ff712df1f00) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7ff712e970c0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7ff712e97180) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7ff712e975a0) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7ff712e97600) 0 + +Vtable for std::locale::facet +std::locale::facet::_ZTVNSt6locale5facetE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6locale5facetE) +16 (int (*)(...))std::locale::facet::~facet +24 (int (*)(...))std::locale::facet::~facet + +Class std::locale::facet + size=16 align=8 + base size=12 base align=8 +std::locale::facet (0x0x7ff712e97660) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7ff712e976c0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7ff712e97720) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7ff712e97ae0) 0 + +Vtable for std::logic_error +std::logic_error::_ZTVSt11logic_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt11logic_error) +16 (int (*)(...))std::logic_error::~logic_error +24 (int (*)(...))std::logic_error::~logic_error +32 (int (*)(...))std::logic_error::what + +Class std::logic_error + size=16 align=8 + base size=16 base align=8 +std::logic_error (0x0x7ff712e10d00) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7ff712e97ba0) 0 nearly-empty + primary-for std::logic_error (0x0x7ff712e10d00) + +Vtable for std::domain_error +std::domain_error::_ZTVSt12domain_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12domain_error) +16 (int (*)(...))std::domain_error::~domain_error +24 (int (*)(...))std::domain_error::~domain_error +32 (int (*)(...))std::logic_error::what + +Class std::domain_error + size=16 align=8 + base size=16 base align=8 +std::domain_error (0x0x7ff712e10dd0) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7ff712fa9000) 0 + primary-for std::domain_error (0x0x7ff712e10dd0) + std::exception (0x0x7ff712e97c00) 0 nearly-empty + primary-for std::logic_error (0x0x7ff712fa9000) + +Vtable for std::invalid_argument +std::invalid_argument::_ZTVSt16invalid_argument: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt16invalid_argument) +16 (int (*)(...))std::invalid_argument::~invalid_argument +24 (int (*)(...))std::invalid_argument::~invalid_argument +32 (int (*)(...))std::logic_error::what + +Class std::invalid_argument + size=16 align=8 + base size=16 base align=8 +std::invalid_argument (0x0x7ff712fa9068) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7ff712fa90d0) 0 + primary-for std::invalid_argument (0x0x7ff712fa9068) + std::exception (0x0x7ff712e97c60) 0 nearly-empty + primary-for std::logic_error (0x0x7ff712fa90d0) + +Vtable for std::length_error +std::length_error::_ZTVSt12length_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12length_error) +16 (int (*)(...))std::length_error::~length_error +24 (int (*)(...))std::length_error::~length_error +32 (int (*)(...))std::logic_error::what + +Class std::length_error + size=16 align=8 + base size=16 base align=8 +std::length_error (0x0x7ff712fa9138) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7ff712fa91a0) 0 + primary-for std::length_error (0x0x7ff712fa9138) + std::exception (0x0x7ff712e97cc0) 0 nearly-empty + primary-for std::logic_error (0x0x7ff712fa91a0) + +Vtable for std::out_of_range +std::out_of_range::_ZTVSt12out_of_range: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12out_of_range) +16 (int (*)(...))std::out_of_range::~out_of_range +24 (int (*)(...))std::out_of_range::~out_of_range +32 (int (*)(...))std::logic_error::what + +Class std::out_of_range + size=16 align=8 + base size=16 base align=8 +std::out_of_range (0x0x7ff712fa9208) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7ff712fa9270) 0 + primary-for std::out_of_range (0x0x7ff712fa9208) + std::exception (0x0x7ff712e97d20) 0 nearly-empty + primary-for std::logic_error (0x0x7ff712fa9270) + +Vtable for std::runtime_error +std::runtime_error::_ZTVSt13runtime_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt13runtime_error) +16 (int (*)(...))std::runtime_error::~runtime_error +24 (int (*)(...))std::runtime_error::~runtime_error +32 (int (*)(...))std::runtime_error::what + +Class std::runtime_error + size=16 align=8 + base size=16 base align=8 +std::runtime_error (0x0x7ff712fa92d8) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7ff712e97d80) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff712fa92d8) + +Vtable for std::range_error +std::range_error::_ZTVSt11range_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt11range_error) +16 (int (*)(...))std::range_error::~range_error +24 (int (*)(...))std::range_error::~range_error +32 (int (*)(...))std::runtime_error::what + +Class std::range_error + size=16 align=8 + base size=16 base align=8 +std::range_error (0x0x7ff712fa9340) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7ff712fa93a8) 0 + primary-for std::range_error (0x0x7ff712fa9340) + std::exception (0x0x7ff712e97de0) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff712fa93a8) + +Vtable for std::overflow_error +std::overflow_error::_ZTVSt14overflow_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt14overflow_error) +16 (int (*)(...))std::overflow_error::~overflow_error +24 (int (*)(...))std::overflow_error::~overflow_error +32 (int (*)(...))std::runtime_error::what + +Class std::overflow_error + size=16 align=8 + base size=16 base align=8 +std::overflow_error (0x0x7ff712fa9410) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7ff712fa9478) 0 + primary-for std::overflow_error (0x0x7ff712fa9410) + std::exception (0x0x7ff712e97e40) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff712fa9478) + +Vtable for std::underflow_error +std::underflow_error::_ZTVSt15underflow_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt15underflow_error) +16 (int (*)(...))std::underflow_error::~underflow_error +24 (int (*)(...))std::underflow_error::~underflow_error +32 (int (*)(...))std::runtime_error::what + +Class std::underflow_error + size=16 align=8 + base size=16 base align=8 +std::underflow_error (0x0x7ff712fa94e0) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7ff712fa9548) 0 + primary-for std::underflow_error (0x0x7ff712fa94e0) + std::exception (0x0x7ff712e97ea0) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff712fa9548) + +Vtable for std::_V2::error_category +std::_V2::error_category::_ZTVNSt3_V214error_categoryE: 10u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt3_V214error_categoryE) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual +40 (int (*)(...))std::_V2::error_category::_M_message +48 (int (*)(...))__cxa_pure_virtual +56 (int (*)(...))std::_V2::error_category::default_error_condition +64 (int (*)(...))std::_V2::error_category::equivalent +72 (int (*)(...))std::_V2::error_category::equivalent + +Class std::_V2::error_category + size=8 align=8 + base size=8 base align=8 +std::_V2::error_category (0x0x7ff712bcb060) 0 nearly-empty + vptr=((& std::_V2::error_category::_ZTVNSt3_V214error_categoryE) + 16u) + +Class std::error_code + size=16 align=8 + base size=16 base align=8 +std::error_code (0x0x7ff712bcb2a0) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7ff712bcb420) 0 + +Vtable for std::system_error +std::system_error::_ZTVSt12system_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12system_error) +16 (int (*)(...))std::system_error::~system_error +24 (int (*)(...))std::system_error::~system_error +32 (int (*)(...))std::runtime_error::what + +Class std::system_error + size=32 align=8 + base size=32 base align=8 +std::system_error (0x0x7ff712fa9a28) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7ff712fa9a90) 0 + primary-for std::system_error (0x0x7ff712fa9a28) + std::exception (0x0x7ff712bcb660) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff712fa9a90) + +Vtable for std::ios_base::failure +std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt8ios_base7failureB5cxx11E) +16 (int (*)(...))std::ios_base::failure::~failure +24 (int (*)(...))std::ios_base::failure::~failure +32 (int (*)(...))std::ios_base::failure::what + +Class std::ios_base::failure + size=32 align=8 + base size=32 base align=8 +std::ios_base::failure (0x0x7ff712c27680) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7ff712c276e8) 0 + primary-for std::ios_base::failure (0x0x7ff712c27680) + std::runtime_error (0x0x7ff712c27750) 0 + primary-for std::system_error (0x0x7ff712c276e8) + std::exception (0x0x7ff712bcb960) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff712c27750) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7ff712bcb9c0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7ff712bcba20) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7ff712bcba80) 0 empty + +Vtable for std::ios_base +std::ios_base::_ZTVSt8ios_base: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt8ios_base) +16 (int (*)(...))std::ios_base::~ios_base +24 (int (*)(...))std::ios_base::~ios_base + +Class std::ios_base + size=216 align=8 + base size=216 base align=8 +std::ios_base (0x0x7ff712bcb900) 0 + vptr=((& std::ios_base::_ZTVSt8ios_base) + 16u) + +Class std::ctype_base + size=1 align=1 + base size=0 base align=1 +std::ctype_base (0x0x7ff712cff240) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7ff712cff900) 0 empty + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSo: 2u entries +0 ((& std::basic_ostream::_ZTVSo) + 24u) +8 ((& std::basic_ostream::_ZTVSo) + 64u) + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2u entries +0 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64u) + +VTT for std::basic_istream +std::basic_istream::_ZTTSi: 2u entries +0 ((& std::basic_istream::_ZTVSi) + 24u) +8 ((& std::basic_istream::_ZTVSi) + 64u) + +VTT for std::basic_istream +std::basic_istream::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2u entries +0 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64u) + +Construction vtable for std::basic_istream (0x0x7ff71291b000 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd0_Si: 10u entries +0 24u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISi) +24 0u +32 0u +40 18446744073709551592u +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISi) +64 0u +72 0u + +Construction vtable for std::basic_ostream (0x0x7ff71291b0d0 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd16_So: 10u entries +0 8u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISo) +24 0u +32 0u +40 18446744073709551608u +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISo) +64 0u +72 0u + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSd: 7u entries +0 ((& std::basic_iostream::_ZTVSd) + 24u) +8 ((& std::basic_iostream::_ZTCSd0_Si) + 24u) +16 ((& std::basic_iostream::_ZTCSd0_Si) + 64u) +24 ((& std::basic_iostream::_ZTCSd16_So) + 24u) +32 ((& std::basic_iostream::_ZTCSd16_So) + 64u) +40 ((& std::basic_iostream::_ZTVSd) + 104u) +48 ((& std::basic_iostream::_ZTVSd) + 64u) + +Construction vtable for std::basic_istream (0x0x7ff71291b478 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10u entries +0 24u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +24 0u +32 0u +40 18446744073709551592u +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +64 0u +72 0u + +Construction vtable for std::basic_ostream (0x0x7ff71291b548 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10u entries +0 8u +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +24 0u +32 0u +40 18446744073709551608u +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +64 0u +72 0u + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7u entries +0 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24u) +8 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24u) +16 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64u) +24 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24u) +32 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64u) +40 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104u) +48 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64u) + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7ff7129391e0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7ff712939240) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7ff712637660) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7ff712637840) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7ff712637a80) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7ff712637b40) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7ff712637ae0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7ff712463ae0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7ff7121f6660) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7ff7121f6a80) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7ff7121f6ae0) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7ff7121f6b40) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7ff7121f6f00) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7ff7121f6f60) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7ff7121fc618) 0 empty + QListData::NotIndirectLayout (0x0x7ff711ff3000) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7ff711fec850) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7ff711ff3060) 0 empty + QListData::NotIndirectLayout (0x0x7ff711ff30c0) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7ff7121fc680) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7ff711ff3120) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7ff711ff3180) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7ff7121f6ea0) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7ff711ff3d20) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7ff712181e40) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7ff712181de0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7ff712186f08) 0 + QList (0x0x7ff712186f70) 0 + QListSpecialMethods (0x0x7ff7121bc060) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7ff7121bc360) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7ff7121bc780) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7ff7121bcde0) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7ff7121bcf60) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7ff711c36060) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7ff711dfdf70) 0 + std::__uses_alloc_base (0x0x7ff711c36000) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7ff711d2c0c0) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7ff711d2c300) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7ff711d2c3c0) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7ff711d2c4e0) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7ff711d2c660) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7ff711d2ca20) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7ff711d2cb40) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7ff711ab54e0) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7ff711ab58a0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7ff711ab5ae0) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7ff7118cf840) 0 + +Vtable for QObjectData +QObjectData::_ZTV11QObjectData: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QObjectData) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))__cxa_pure_virtual + +Class QObjectData + size=48 align=8 + base size=48 base align=8 +QObjectData (0x0x7ff7118cf9c0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7ff7118cfba0) 0 empty + +Vtable for QObject +QObject::_ZTV7QObject: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QObject) +16 (int (*)(...))QObject::metaObject +24 (int (*)(...))QObject::qt_metacast +32 (int (*)(...))QObject::qt_metacall +40 (int (*)(...))QObject::~QObject +48 (int (*)(...))QObject::~QObject +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QObject + size=16 align=8 + base size=16 base align=8 +QObject (0x0x7ff7118cfb40) 0 + vptr=((& QObject::_ZTV7QObject) + 16u) + +Vtable for QObjectUserData +QObjectUserData::_ZTV15QObjectUserData: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QObjectUserData) +16 (int (*)(...))QObjectUserData::~QObjectUserData +24 (int (*)(...))QObjectUserData::~QObjectUserData + +Class QObjectUserData + size=8 align=8 + base size=8 base align=8 +QObjectUserData (0x0x7ff7118cff00) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7ff7118cff60) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7ff7115d6060) 0 empty + +Vtable for QAbstractAnimation +QAbstractAnimation::_ZTV18QAbstractAnimation: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractAnimation) +16 (int (*)(...))QAbstractAnimation::metaObject +24 (int (*)(...))QAbstractAnimation::qt_metacast +32 (int (*)(...))QAbstractAnimation::qt_metacall +40 0u +48 0u +56 (int (*)(...))QAbstractAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QAbstractAnimation + size=16 align=8 + base size=16 base align=8 +QAbstractAnimation (0x0x7ff711b9c8f0) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7ff7115d6000) 0 + primary-for QAbstractAnimation (0x0x7ff711b9c8f0) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7ff7115d6120) 0 empty + +Vtable for QAnimationDriver +QAnimationDriver::_ZTV16QAnimationDriver: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QAnimationDriver) +16 (int (*)(...))QAnimationDriver::metaObject +24 (int (*)(...))QAnimationDriver::qt_metacast +32 (int (*)(...))QAnimationDriver::qt_metacall +40 (int (*)(...))QAnimationDriver::~QAnimationDriver +48 (int (*)(...))QAnimationDriver::~QAnimationDriver +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAnimationDriver::advance +120 (int (*)(...))QAnimationDriver::elapsed +128 (int (*)(...))QAnimationDriver::start +136 (int (*)(...))QAnimationDriver::stop + +Class QAnimationDriver + size=16 align=8 + base size=16 base align=8 +QAnimationDriver (0x0x7ff711b9c958) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7ff7115d60c0) 0 + primary-for QAnimationDriver (0x0x7ff711b9c958) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7ff7115d61e0) 0 empty + +Vtable for QAnimationGroup +QAnimationGroup::_ZTV15QAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAnimationGroup) +16 (int (*)(...))QAnimationGroup::metaObject +24 (int (*)(...))QAnimationGroup::qt_metacast +32 (int (*)(...))QAnimationGroup::qt_metacall +40 0u +48 0u +56 (int (*)(...))QAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QAnimationGroup + size=16 align=8 + base size=16 base align=8 +QAnimationGroup (0x0x7ff711b9c9c0) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7ff711b9ca28) 0 + primary-for QAnimationGroup (0x0x7ff711b9c9c0) + QObject (0x0x7ff7115d6180) 0 + primary-for QAbstractAnimation (0x0x7ff711b9ca28) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7ff7115d62a0) 0 empty + +Vtable for QParallelAnimationGroup +QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QParallelAnimationGroup) +16 (int (*)(...))QParallelAnimationGroup::metaObject +24 (int (*)(...))QParallelAnimationGroup::qt_metacast +32 (int (*)(...))QParallelAnimationGroup::qt_metacall +40 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup +48 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup +56 (int (*)(...))QParallelAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QParallelAnimationGroup::duration +120 (int (*)(...))QParallelAnimationGroup::updateCurrentTime +128 (int (*)(...))QParallelAnimationGroup::updateState +136 (int (*)(...))QParallelAnimationGroup::updateDirection + +Class QParallelAnimationGroup + size=16 align=8 + base size=16 base align=8 +QParallelAnimationGroup (0x0x7ff711b9ca90) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7ff711b9caf8) 0 + primary-for QParallelAnimationGroup (0x0x7ff711b9ca90) + QAbstractAnimation (0x0x7ff711b9cb60) 0 + primary-for QAnimationGroup (0x0x7ff711b9caf8) + QObject (0x0x7ff7115d6240) 0 + primary-for QAbstractAnimation (0x0x7ff711b9cb60) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7ff7115d6360) 0 empty + +Vtable for QPauseAnimation +QPauseAnimation::_ZTV15QPauseAnimation: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QPauseAnimation) +16 (int (*)(...))QPauseAnimation::metaObject +24 (int (*)(...))QPauseAnimation::qt_metacast +32 (int (*)(...))QPauseAnimation::qt_metacall +40 (int (*)(...))QPauseAnimation::~QPauseAnimation +48 (int (*)(...))QPauseAnimation::~QPauseAnimation +56 (int (*)(...))QPauseAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QPauseAnimation::duration +120 (int (*)(...))QPauseAnimation::updateCurrentTime +128 (int (*)(...))QAbstractAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection + +Class QPauseAnimation + size=16 align=8 + base size=16 base align=8 +QPauseAnimation (0x0x7ff711b9cbc8) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7ff711b9cc30) 0 + primary-for QPauseAnimation (0x0x7ff711b9cbc8) + QObject (0x0x7ff7115d6300) 0 + primary-for QAbstractAnimation (0x0x7ff711b9cc30) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7ff7116b36c0) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7ff711782780) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7ff711782840) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7ff711782c00) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7ff711782ba0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7ff711782c60) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7ff7114ba6c0) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7ff7114ba780) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7ff7114ba720) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7ff7114ba7e0) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7ff7114ba660) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7ff71123cae0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7ff71123ccc0) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7ff71123cc60) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7ff71123cd80) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7ff71123cd20) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7ff710fcc720) 0 empty + +Vtable for QVariantAnimation +QVariantAnimation::_ZTV17QVariantAnimation: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QVariantAnimation) +16 (int (*)(...))QVariantAnimation::metaObject +24 (int (*)(...))QVariantAnimation::qt_metacast +32 (int (*)(...))QVariantAnimation::qt_metacall +40 (int (*)(...))QVariantAnimation::~QVariantAnimation +48 (int (*)(...))QVariantAnimation::~QVariantAnimation +56 (int (*)(...))QVariantAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QVariantAnimation::duration +120 (int (*)(...))QVariantAnimation::updateCurrentTime +128 (int (*)(...))QVariantAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection +144 (int (*)(...))QVariantAnimation::updateCurrentValue +152 (int (*)(...))QVariantAnimation::interpolated + +Class QVariantAnimation + size=16 align=8 + base size=16 base align=8 +QVariantAnimation (0x0x7ff710fd7208) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7ff710fd7270) 0 + primary-for QVariantAnimation (0x0x7ff710fd7208) + QObject (0x0x7ff710fcc6c0) 0 + primary-for QAbstractAnimation (0x0x7ff710fd7270) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7ff710fcc7e0) 0 empty + +Vtable for QPropertyAnimation +QPropertyAnimation::_ZTV18QPropertyAnimation: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QPropertyAnimation) +16 (int (*)(...))QPropertyAnimation::metaObject +24 (int (*)(...))QPropertyAnimation::qt_metacast +32 (int (*)(...))QPropertyAnimation::qt_metacall +40 (int (*)(...))QPropertyAnimation::~QPropertyAnimation +48 (int (*)(...))QPropertyAnimation::~QPropertyAnimation +56 (int (*)(...))QPropertyAnimation::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QVariantAnimation::duration +120 (int (*)(...))QVariantAnimation::updateCurrentTime +128 (int (*)(...))QPropertyAnimation::updateState +136 (int (*)(...))QAbstractAnimation::updateDirection +144 (int (*)(...))QPropertyAnimation::updateCurrentValue +152 (int (*)(...))QVariantAnimation::interpolated + +Class QPropertyAnimation + size=16 align=8 + base size=16 base align=8 +QPropertyAnimation (0x0x7ff710fd7340) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7ff710fd73a8) 0 + primary-for QPropertyAnimation (0x0x7ff710fd7340) + QAbstractAnimation (0x0x7ff710fd7410) 0 + primary-for QVariantAnimation (0x0x7ff710fd73a8) + QObject (0x0x7ff710fcc780) 0 + primary-for QAbstractAnimation (0x0x7ff710fd7410) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7ff710fcc8a0) 0 empty + +Vtable for QSequentialAnimationGroup +QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QSequentialAnimationGroup) +16 (int (*)(...))QSequentialAnimationGroup::metaObject +24 (int (*)(...))QSequentialAnimationGroup::qt_metacast +32 (int (*)(...))QSequentialAnimationGroup::qt_metacall +40 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup +48 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup +56 (int (*)(...))QSequentialAnimationGroup::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSequentialAnimationGroup::duration +120 (int (*)(...))QSequentialAnimationGroup::updateCurrentTime +128 (int (*)(...))QSequentialAnimationGroup::updateState +136 (int (*)(...))QSequentialAnimationGroup::updateDirection + +Class QSequentialAnimationGroup + size=16 align=8 + base size=16 base align=8 +QSequentialAnimationGroup (0x0x7ff710fd7478) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7ff710fd74e0) 0 + primary-for QSequentialAnimationGroup (0x0x7ff710fd7478) + QAbstractAnimation (0x0x7ff710fd7548) 0 + primary-for QAnimationGroup (0x0x7ff710fd74e0) + QObject (0x0x7ff710fcc840) 0 + primary-for QAbstractAnimation (0x0x7ff710fd7548) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7ff710fcc960) 0 + +Vtable for QTextCodec +QTextCodec::_ZTV10QTextCodec: 9u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QTextCodec) +16 (int (*)(...))__cxa_pure_virtual +24 (int (*)(...))QTextCodec::aliases +32 (int (*)(...))__cxa_pure_virtual +40 (int (*)(...))__cxa_pure_virtual +48 (int (*)(...))__cxa_pure_virtual +56 0u +64 0u + +Class QTextCodec + size=8 align=8 + base size=8 base align=8 +QTextCodec (0x0x7ff710fcc900) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7ff710fccae0) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7ff710fccb40) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7ff710fccba0) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7ff710fccd80) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7ff710fccf00) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7ff7111170c0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7ff7111172a0) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7ff711117360) 0 empty + +Vtable for QIODevice +QIODevice::_ZTV9QIODevice: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QIODevice) +16 (int (*)(...))QIODevice::metaObject +24 (int (*)(...))QIODevice::qt_metacast +32 (int (*)(...))QIODevice::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QIODevice::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QIODevice::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))__cxa_pure_virtual +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))__cxa_pure_virtual + +Class QIODevice + size=16 align=8 + base size=16 base align=8 +QIODevice (0x0x7ff710fd77b8) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7ff711117300) 0 + primary-for QIODevice (0x0x7ff710fd77b8) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7ff711117540) 0 empty + +Vtable for QBuffer +QBuffer::_ZTV7QBuffer: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QBuffer) +16 (int (*)(...))QBuffer::metaObject +24 (int (*)(...))QBuffer::qt_metacast +32 (int (*)(...))QBuffer::qt_metacall +40 (int (*)(...))QBuffer::~QBuffer +48 (int (*)(...))QBuffer::~QBuffer +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QBuffer::connectNotify +104 (int (*)(...))QBuffer::disconnectNotify +112 (int (*)(...))QIODevice::isSequential +120 (int (*)(...))QBuffer::open +128 (int (*)(...))QBuffer::close +136 (int (*)(...))QBuffer::pos +144 (int (*)(...))QBuffer::size +152 (int (*)(...))QBuffer::seek +160 (int (*)(...))QBuffer::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QBuffer::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBuffer::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBuffer::writeData + +Class QBuffer + size=16 align=8 + base size=16 base align=8 +QBuffer (0x0x7ff710fd78f0) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7ff710fd7958) 0 + primary-for QBuffer (0x0x7ff710fd78f0) + QObject (0x0x7ff7111174e0) 0 + primary-for QIODevice (0x0x7ff710fd7958) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7ff7111175a0) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7ff711117660) 0 + +Vtable for QTextStream +QTextStream::_ZTV11QTextStream: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTextStream) +16 (int (*)(...))QTextStream::~QTextStream +24 (int (*)(...))QTextStream::~QTextStream + +Class QTextStream + size=16 align=8 + base size=16 base align=8 +QTextStream (0x0x7ff711117960) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7ff711117ba0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7ff711117de0) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7ff710b800c0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7ff710b80240) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7ff710b806c0) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7ff710b80660) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7ff710d08780) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7ff710d08840) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7ff710d08900) 0 empty + +Vtable for QFileDevice +QFileDevice::_ZTV11QFileDevice: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QFileDevice) +16 (int (*)(...))QFileDevice::metaObject +24 (int (*)(...))QFileDevice::qt_metacast +32 (int (*)(...))QFileDevice::qt_metacall +40 (int (*)(...))QFileDevice::~QFileDevice +48 (int (*)(...))QFileDevice::~QFileDevice +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFileDevice::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QFileDevice::fileName +248 (int (*)(...))QFileDevice::resize +256 (int (*)(...))QFileDevice::permissions +264 (int (*)(...))QFileDevice::setPermissions + +Class QFileDevice + size=16 align=8 + base size=16 base align=8 +QFileDevice (0x0x7ff710d09888) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7ff710d098f0) 0 + primary-for QFileDevice (0x0x7ff710d09888) + QObject (0x0x7ff710d088a0) 0 + primary-for QIODevice (0x0x7ff710d098f0) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7ff710d08ae0) 0 empty + +Vtable for QFile +QFile::_ZTV5QFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI5QFile) +16 (int (*)(...))QFile::metaObject +24 (int (*)(...))QFile::qt_metacast +32 (int (*)(...))QFile::qt_metacall +40 (int (*)(...))QFile::~QFile +48 (int (*)(...))QFile::~QFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QFile::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFile::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QFile::fileName +248 (int (*)(...))QFile::resize +256 (int (*)(...))QFile::permissions +264 (int (*)(...))QFile::setPermissions + +Class QFile + size=16 align=8 + base size=16 base align=8 +QFile (0x0x7ff710d09a28) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7ff710d09a90) 0 + primary-for QFile (0x0x7ff710d09a28) + QIODevice (0x0x7ff710d09af8) 0 + primary-for QFileDevice (0x0x7ff710d09a90) + QObject (0x0x7ff710d08a80) 0 + primary-for QIODevice (0x0x7ff710d09af8) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7ff710d08c60) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7ff710d08f60) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7ff710a503c0) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7ff710a50600) 0 empty + +Vtable for QFileSelector +QFileSelector::_ZTV13QFileSelector: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QFileSelector) +16 (int (*)(...))QFileSelector::metaObject +24 (int (*)(...))QFileSelector::qt_metacast +32 (int (*)(...))QFileSelector::qt_metacall +40 (int (*)(...))QFileSelector::~QFileSelector +48 (int (*)(...))QFileSelector::~QFileSelector +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QFileSelector + size=16 align=8 + base size=16 base align=8 +QFileSelector (0x0x7ff710af2000) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7ff710a505a0) 0 + primary-for QFileSelector (0x0x7ff710af2000) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7ff710a506c0) 0 empty + +Vtable for QFileSystemWatcher +QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFileSystemWatcher) +16 (int (*)(...))QFileSystemWatcher::metaObject +24 (int (*)(...))QFileSystemWatcher::qt_metacast +32 (int (*)(...))QFileSystemWatcher::qt_metacall +40 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher +48 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QFileSystemWatcher + size=16 align=8 + base size=16 base align=8 +QFileSystemWatcher (0x0x7ff710af2068) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7ff710a50660) 0 + primary-for QFileSystemWatcher (0x0x7ff710af2068) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7ff710a50720) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7ff710a508a0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7ff710a50840) 0 + +Vtable for std::type_info +std::type_info::_ZTVSt9type_info: 8u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt9type_info) +16 (int (*)(...))std::type_info::~type_info +24 (int (*)(...))std::type_info::~type_info +32 (int (*)(...))std::type_info::__is_pointer_p +40 (int (*)(...))std::type_info::__is_function_p +48 (int (*)(...))std::type_info::__do_catch +56 (int (*)(...))std::type_info::__do_upcast + +Class std::type_info + size=16 align=8 + base size=16 base align=8 +std::type_info (0x0x7ff710a50a20) 0 + vptr=((& std::type_info::_ZTVSt9type_info) + 16u) + +Vtable for std::bad_cast +std::bad_cast::_ZTVSt8bad_cast: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt8bad_cast) +16 (int (*)(...))std::bad_cast::~bad_cast +24 (int (*)(...))std::bad_cast::~bad_cast +32 (int (*)(...))std::bad_cast::what + +Class std::bad_cast + size=8 align=8 + base size=8 base align=8 +std::bad_cast (0x0x7ff710af2138) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7ff710a50a80) 0 nearly-empty + primary-for std::bad_cast (0x0x7ff710af2138) + +Vtable for std::bad_typeid +std::bad_typeid::_ZTVSt10bad_typeid: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt10bad_typeid) +16 (int (*)(...))std::bad_typeid::~bad_typeid +24 (int (*)(...))std::bad_typeid::~bad_typeid +32 (int (*)(...))std::bad_typeid::what + +Class std::bad_typeid + size=8 align=8 + base size=8 base align=8 +std::bad_typeid (0x0x7ff710af21a0) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7ff710a50ae0) 0 nearly-empty + primary-for std::bad_typeid (0x0x7ff710af21a0) + +Vtable for std::bad_function_call +std::bad_function_call::_ZTVSt17bad_function_call: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt17bad_function_call) +16 (int (*)(...))std::bad_function_call::~bad_function_call +24 (int (*)(...))std::bad_function_call::~bad_function_call +32 (int (*)(...))std::bad_function_call::what + +Class std::bad_function_call + size=8 align=8 + base size=8 base align=8 +std::bad_function_call (0x0x7ff7108d5410) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7ff710873ba0) 0 nearly-empty + primary-for std::bad_function_call (0x0x7ff7108d5410) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7ff710873c60) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7ff710873cc0) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7ff710873de0) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7ff71093d300) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7ff71093d540) 0 empty + +Vtable for QProcess +QProcess::_ZTV8QProcess: 31u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI8QProcess) +16 (int (*)(...))QProcess::metaObject +24 (int (*)(...))QProcess::qt_metacast +32 (int (*)(...))QProcess::qt_metacall +40 (int (*)(...))QProcess::~QProcess +48 (int (*)(...))QProcess::~QProcess +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QProcess::isSequential +120 (int (*)(...))QProcess::open +128 (int (*)(...))QProcess::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QProcess::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QProcess::bytesAvailable +184 (int (*)(...))QProcess::bytesToWrite +192 (int (*)(...))QProcess::canReadLine +200 (int (*)(...))QProcess::waitForReadyRead +208 (int (*)(...))QProcess::waitForBytesWritten +216 (int (*)(...))QProcess::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QProcess::writeData +240 (int (*)(...))QProcess::setupChildProcess + +Class QProcess + size=16 align=8 + base size=16 base align=8 +QProcess (0x0x7ff7108d5c30) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7ff7108d5c98) 0 + primary-for QProcess (0x0x7ff7108d5c30) + QObject (0x0x7ff71093d4e0) 0 + primary-for QIODevice (0x0x7ff7108d5c98) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7ff71093d5a0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7ff71093d720) 0 empty + +Vtable for QSaveFile +QSaveFile::_ZTV9QSaveFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QSaveFile) +16 (int (*)(...))QSaveFile::metaObject +24 (int (*)(...))QSaveFile::qt_metacast +32 (int (*)(...))QSaveFile::qt_metacall +40 (int (*)(...))QSaveFile::~QSaveFile +48 (int (*)(...))QSaveFile::~QSaveFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QSaveFile::open +128 (int (*)(...))QSaveFile::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFileDevice::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QSaveFile::writeData +240 (int (*)(...))QSaveFile::fileName +248 (int (*)(...))QFileDevice::resize +256 (int (*)(...))QFileDevice::permissions +264 (int (*)(...))QFileDevice::setPermissions + +Class QSaveFile + size=16 align=8 + base size=16 base align=8 +QSaveFile (0x0x7ff7108d5d00) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7ff7108d5d68) 0 + primary-for QSaveFile (0x0x7ff7108d5d00) + QIODevice (0x0x7ff7108d5dd0) 0 + primary-for QFileDevice (0x0x7ff7108d5d68) + QObject (0x0x7ff71093d6c0) 0 + primary-for QIODevice (0x0x7ff7108d5dd0) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7ff71093d7e0) 0 empty + +Vtable for QSettings +QSettings::_ZTV9QSettings: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QSettings) +16 (int (*)(...))QSettings::metaObject +24 (int (*)(...))QSettings::qt_metacast +32 (int (*)(...))QSettings::qt_metacall +40 (int (*)(...))QSettings::~QSettings +48 (int (*)(...))QSettings::~QSettings +56 (int (*)(...))QSettings::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSettings + size=16 align=8 + base size=16 base align=8 +QSettings (0x0x7ff7108d5e38) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7ff71093d780) 0 + primary-for QSettings (0x0x7ff7108d5e38) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7ff71093d840) 0 empty + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7ff71093d9c0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7ff71093dcc0) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7ff71093dde0) 0 empty + +Vtable for QTemporaryFile +QTemporaryFile::_ZTV14QTemporaryFile: 34u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QTemporaryFile) +16 (int (*)(...))QTemporaryFile::metaObject +24 (int (*)(...))QTemporaryFile::qt_metacast +32 (int (*)(...))QTemporaryFile::qt_metacall +40 (int (*)(...))QTemporaryFile::~QTemporaryFile +48 (int (*)(...))QTemporaryFile::~QTemporaryFile +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFileDevice::isSequential +120 (int (*)(...))QTemporaryFile::open +128 (int (*)(...))QFileDevice::close +136 (int (*)(...))QFileDevice::pos +144 (int (*)(...))QFile::size +152 (int (*)(...))QFileDevice::seek +160 (int (*)(...))QFileDevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QIODevice::bytesAvailable +184 (int (*)(...))QIODevice::bytesToWrite +192 (int (*)(...))QIODevice::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QFileDevice::readData +224 (int (*)(...))QFileDevice::readLineData +232 (int (*)(...))QFileDevice::writeData +240 (int (*)(...))QTemporaryFile::fileName +248 (int (*)(...))QFile::resize +256 (int (*)(...))QFile::permissions +264 (int (*)(...))QFile::setPermissions + +Class QTemporaryFile + size=16 align=8 + base size=16 base align=8 +QTemporaryFile (0x0x7ff71066b000) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7ff71066b068) 0 + primary-for QTemporaryFile (0x0x7ff71066b000) + QFileDevice (0x0x7ff71066b0d0) 0 + primary-for QFile (0x0x7ff71066b068) + QIODevice (0x0x7ff71066b138) 0 + primary-for QFileDevice (0x0x7ff71066b0d0) + QObject (0x0x7ff71093dd80) 0 + primary-for QIODevice (0x0x7ff71066b138) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7ff71093df00) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7ff71037f3c0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7ff71037f5a0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7ff71037f720) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7ff710498600) 0 empty + +Vtable for QAbstractItemModel +QAbstractItemModel::_ZTV18QAbstractItemModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractItemModel) +16 (int (*)(...))QAbstractItemModel::metaObject +24 (int (*)(...))QAbstractItemModel::qt_metacast +32 (int (*)(...))QAbstractItemModel::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractItemModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractItemModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractItemModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractItemModel + size=16 align=8 + base size=16 base align=8 +QAbstractItemModel (0x0x7ff710484f70) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7ff7104985a0) 0 + primary-for QAbstractItemModel (0x0x7ff710484f70) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7ff710498960) 0 empty + +Vtable for QAbstractTableModel +QAbstractTableModel::_ZTV19QAbstractTableModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTableModel) +16 (int (*)(...))QAbstractTableModel::metaObject +24 (int (*)(...))QAbstractTableModel::qt_metacast +32 (int (*)(...))QAbstractTableModel::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractTableModel::index +120 (int (*)(...))QAbstractTableModel::parent +128 (int (*)(...))QAbstractTableModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractTableModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractTableModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractTableModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractTableModel + size=16 align=8 + base size=16 base align=8 +QAbstractTableModel (0x0x7ff7104f71a0) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7ff7104f7208) 0 + primary-for QAbstractTableModel (0x0x7ff7104f71a0) + QObject (0x0x7ff710498900) 0 + primary-for QAbstractItemModel (0x0x7ff7104f7208) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7ff710498a20) 0 empty + +Vtable for QAbstractListModel +QAbstractListModel::_ZTV18QAbstractListModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractListModel) +16 (int (*)(...))QAbstractListModel::metaObject +24 (int (*)(...))QAbstractListModel::qt_metacast +32 (int (*)(...))QAbstractListModel::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractListModel::index +120 (int (*)(...))QAbstractListModel::parent +128 (int (*)(...))QAbstractListModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QAbstractListModel::columnCount +152 (int (*)(...))QAbstractListModel::hasChildren +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))QAbstractItemModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractListModel::dropMimeData +240 (int (*)(...))QAbstractItemModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QAbstractListModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QAbstractListModel + size=16 align=8 + base size=16 base align=8 +QAbstractListModel (0x0x7ff7104f7270) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7ff7104f72d8) 0 + primary-for QAbstractListModel (0x0x7ff7104f7270) + QObject (0x0x7ff7104989c0) 0 + primary-for QAbstractItemModel (0x0x7ff7104f72d8) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7ff710498d20) 0 empty + +Vtable for QAbstractProxyModel +QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractProxyModel) +16 (int (*)(...))QAbstractProxyModel::metaObject +24 (int (*)(...))QAbstractProxyModel::qt_metacast +32 (int (*)(...))QAbstractProxyModel::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))QAbstractProxyModel::sibling +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QAbstractProxyModel::headerData +184 (int (*)(...))QAbstractProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QAbstractProxyModel::mimeTypes +216 (int (*)(...))QAbstractProxyModel::mimeData +224 (int (*)(...))QAbstractProxyModel::canDropMimeData +232 (int (*)(...))QAbstractProxyModel::dropMimeData +240 (int (*)(...))QAbstractProxyModel::supportedDropActions +248 (int (*)(...))QAbstractProxyModel::supportedDragActions +256 (int (*)(...))QAbstractItemModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QAbstractItemModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QAbstractProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QAbstractProxyModel::setSourceModel +392 (int (*)(...))__cxa_pure_virtual +400 (int (*)(...))__cxa_pure_virtual +408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource +416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource + +Class QAbstractProxyModel + size=16 align=8 + base size=16 base align=8 +QAbstractProxyModel (0x0x7ff7104f7410) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7ff7104f7478) 0 + primary-for QAbstractProxyModel (0x0x7ff7104f7410) + QObject (0x0x7ff710498cc0) 0 + primary-for QAbstractItemModel (0x0x7ff7104f7478) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7ff710498de0) 0 empty + +Vtable for QIdentityProxyModel +QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QIdentityProxyModel) +16 (int (*)(...))QIdentityProxyModel::metaObject +24 (int (*)(...))QIdentityProxyModel::qt_metacast +32 (int (*)(...))QIdentityProxyModel::qt_metacall +40 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel +48 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QIdentityProxyModel::index +120 (int (*)(...))QIdentityProxyModel::parent +128 (int (*)(...))QIdentityProxyModel::sibling +136 (int (*)(...))QIdentityProxyModel::rowCount +144 (int (*)(...))QIdentityProxyModel::columnCount +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QIdentityProxyModel::headerData +184 (int (*)(...))QAbstractProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QAbstractProxyModel::mimeTypes +216 (int (*)(...))QAbstractProxyModel::mimeData +224 (int (*)(...))QAbstractProxyModel::canDropMimeData +232 (int (*)(...))QIdentityProxyModel::dropMimeData +240 (int (*)(...))QAbstractProxyModel::supportedDropActions +248 (int (*)(...))QAbstractProxyModel::supportedDragActions +256 (int (*)(...))QIdentityProxyModel::insertRows +264 (int (*)(...))QIdentityProxyModel::insertColumns +272 (int (*)(...))QIdentityProxyModel::removeRows +280 (int (*)(...))QIdentityProxyModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QAbstractProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QIdentityProxyModel::match +352 (int (*)(...))QAbstractProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QIdentityProxyModel::setSourceModel +392 (int (*)(...))QIdentityProxyModel::mapToSource +400 (int (*)(...))QIdentityProxyModel::mapFromSource +408 (int (*)(...))QIdentityProxyModel::mapSelectionToSource +416 (int (*)(...))QIdentityProxyModel::mapSelectionFromSource + +Class QIdentityProxyModel + size=16 align=8 + base size=16 base align=8 +QIdentityProxyModel (0x0x7ff7104f74e0) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7ff7104f7548) 0 + primary-for QIdentityProxyModel (0x0x7ff7104f74e0) + QAbstractItemModel (0x0x7ff7104f75b0) 0 + primary-for QAbstractProxyModel (0x0x7ff7104f7548) + QObject (0x0x7ff710498d80) 0 + primary-for QAbstractItemModel (0x0x7ff7104f75b0) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7ff710498e40) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7ff71021d0c0) 0 empty + +Vtable for QItemSelectionModel +QItemSelectionModel::_ZTV19QItemSelectionModel: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QItemSelectionModel) +16 (int (*)(...))QItemSelectionModel::metaObject +24 (int (*)(...))QItemSelectionModel::qt_metacast +32 (int (*)(...))QItemSelectionModel::qt_metacall +40 (int (*)(...))QItemSelectionModel::~QItemSelectionModel +48 (int (*)(...))QItemSelectionModel::~QItemSelectionModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QItemSelectionModel::setCurrentIndex +120 (int (*)(...))QItemSelectionModel::select +128 (int (*)(...))QItemSelectionModel::select +136 (int (*)(...))QItemSelectionModel::clear +144 (int (*)(...))QItemSelectionModel::reset +152 (int (*)(...))QItemSelectionModel::clearCurrentIndex + +Class QItemSelectionModel + size=16 align=8 + base size=16 base align=8 +QItemSelectionModel (0x0x7ff7104f7820) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7ff71021d060) 0 + primary-for QItemSelectionModel (0x0x7ff7104f7820) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7ff7104f7a28) 0 + QList (0x0x7ff7104f7a90) 0 + QListSpecialMethods (0x0x7ff71021d360) 0 empty + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7ff71021d780) 0 empty + +Vtable for QSortFilterProxyModel +QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QSortFilterProxyModel) +16 (int (*)(...))QSortFilterProxyModel::metaObject +24 (int (*)(...))QSortFilterProxyModel::qt_metacast +32 (int (*)(...))QSortFilterProxyModel::qt_metacall +40 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel +48 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSortFilterProxyModel::index +120 (int (*)(...))QSortFilterProxyModel::parent +128 (int (*)(...))QSortFilterProxyModel::sibling +136 (int (*)(...))QSortFilterProxyModel::rowCount +144 (int (*)(...))QSortFilterProxyModel::columnCount +152 (int (*)(...))QSortFilterProxyModel::hasChildren +160 (int (*)(...))QSortFilterProxyModel::data +168 (int (*)(...))QSortFilterProxyModel::setData +176 (int (*)(...))QSortFilterProxyModel::headerData +184 (int (*)(...))QSortFilterProxyModel::setHeaderData +192 (int (*)(...))QAbstractProxyModel::itemData +200 (int (*)(...))QAbstractProxyModel::setItemData +208 (int (*)(...))QSortFilterProxyModel::mimeTypes +216 (int (*)(...))QSortFilterProxyModel::mimeData +224 (int (*)(...))QAbstractProxyModel::canDropMimeData +232 (int (*)(...))QSortFilterProxyModel::dropMimeData +240 (int (*)(...))QSortFilterProxyModel::supportedDropActions +248 (int (*)(...))QAbstractProxyModel::supportedDragActions +256 (int (*)(...))QSortFilterProxyModel::insertRows +264 (int (*)(...))QSortFilterProxyModel::insertColumns +272 (int (*)(...))QSortFilterProxyModel::removeRows +280 (int (*)(...))QSortFilterProxyModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QSortFilterProxyModel::fetchMore +312 (int (*)(...))QSortFilterProxyModel::canFetchMore +320 (int (*)(...))QSortFilterProxyModel::flags +328 (int (*)(...))QSortFilterProxyModel::sort +336 (int (*)(...))QSortFilterProxyModel::buddy +344 (int (*)(...))QSortFilterProxyModel::match +352 (int (*)(...))QSortFilterProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QSortFilterProxyModel::setSourceModel +392 (int (*)(...))QSortFilterProxyModel::mapToSource +400 (int (*)(...))QSortFilterProxyModel::mapFromSource +408 (int (*)(...))QSortFilterProxyModel::mapSelectionToSource +416 (int (*)(...))QSortFilterProxyModel::mapSelectionFromSource +424 (int (*)(...))QSortFilterProxyModel::filterAcceptsRow +432 (int (*)(...))QSortFilterProxyModel::filterAcceptsColumn +440 (int (*)(...))QSortFilterProxyModel::lessThan + +Class QSortFilterProxyModel + size=16 align=8 + base size=16 base align=8 +QSortFilterProxyModel (0x0x7ff7104f7b60) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7ff7104f7bc8) 0 + primary-for QSortFilterProxyModel (0x0x7ff7104f7b60) + QAbstractItemModel (0x0x7ff7104f7c30) 0 + primary-for QAbstractProxyModel (0x0x7ff7104f7bc8) + QObject (0x0x7ff71021d720) 0 + primary-for QAbstractItemModel (0x0x7ff7104f7c30) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7ff71021d840) 0 empty + +Vtable for QStringListModel +QStringListModel::_ZTV16QStringListModel: 48u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QStringListModel) +16 (int (*)(...))QStringListModel::metaObject +24 (int (*)(...))QStringListModel::qt_metacast +32 (int (*)(...))QStringListModel::qt_metacall +40 (int (*)(...))QStringListModel::~QStringListModel +48 (int (*)(...))QStringListModel::~QStringListModel +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QAbstractListModel::index +120 (int (*)(...))QAbstractListModel::parent +128 (int (*)(...))QStringListModel::sibling +136 (int (*)(...))QStringListModel::rowCount +144 (int (*)(...))QAbstractListModel::columnCount +152 (int (*)(...))QAbstractListModel::hasChildren +160 (int (*)(...))QStringListModel::data +168 (int (*)(...))QStringListModel::setData +176 (int (*)(...))QAbstractItemModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QAbstractItemModel::itemData +200 (int (*)(...))QAbstractItemModel::setItemData +208 (int (*)(...))QAbstractItemModel::mimeTypes +216 (int (*)(...))QAbstractItemModel::mimeData +224 (int (*)(...))QAbstractItemModel::canDropMimeData +232 (int (*)(...))QAbstractListModel::dropMimeData +240 (int (*)(...))QStringListModel::supportedDropActions +248 (int (*)(...))QAbstractItemModel::supportedDragActions +256 (int (*)(...))QStringListModel::insertRows +264 (int (*)(...))QAbstractItemModel::insertColumns +272 (int (*)(...))QStringListModel::removeRows +280 (int (*)(...))QAbstractItemModel::removeColumns +288 (int (*)(...))QAbstractItemModel::moveRows +296 (int (*)(...))QAbstractItemModel::moveColumns +304 (int (*)(...))QAbstractItemModel::fetchMore +312 (int (*)(...))QAbstractItemModel::canFetchMore +320 (int (*)(...))QStringListModel::flags +328 (int (*)(...))QStringListModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QAbstractItemModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QStringListModel + size=24 align=8 + base size=24 base align=8 +QStringListModel (0x0x7ff7104f7c98) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7ff7104f7d00) 0 + primary-for QStringListModel (0x0x7ff7104f7c98) + QAbstractItemModel (0x0x7ff7104f7d68) 0 + primary-for QAbstractListModel (0x0x7ff7104f7d00) + QObject (0x0x7ff71021d7e0) 0 + primary-for QAbstractItemModel (0x0x7ff7104f7d68) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7ff71021d8a0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7ff71021d960) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7ff71021da20) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7ff71021da80) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7ff71021db40) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7ff71021dba0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7ff71021dae0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7ff71021dc60) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7ff71021dcc0) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7ff71021dd80) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7ff71021dde0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7ff71021dd20) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7ff71002d000) 0 empty + +Vtable for QEventLoop +QEventLoop::_ZTV10QEventLoop: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QEventLoop) +16 (int (*)(...))QEventLoop::metaObject +24 (int (*)(...))QEventLoop::qt_metacast +32 (int (*)(...))QEventLoop::qt_metacall +40 (int (*)(...))QEventLoop::~QEventLoop +48 (int (*)(...))QEventLoop::~QEventLoop +56 (int (*)(...))QEventLoop::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QEventLoop + size=16 align=8 + base size=16 base align=8 +QEventLoop (0x0x7ff7104f7f70) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7ff71021df60) 0 + primary-for QEventLoop (0x0x7ff7104f7f70) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7ff71002d180) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7ff71002d240) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7ff71002d2a0) 0 + +Vtable for QAbstractEventDispatcher +QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher) +16 (int (*)(...))QAbstractEventDispatcher::metaObject +24 (int (*)(...))QAbstractEventDispatcher::qt_metacast +32 (int (*)(...))QAbstractEventDispatcher::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual +184 (int (*)(...))__cxa_pure_virtual +192 (int (*)(...))__cxa_pure_virtual +200 (int (*)(...))__cxa_pure_virtual +208 (int (*)(...))QAbstractEventDispatcher::startingUp +216 (int (*)(...))QAbstractEventDispatcher::closingDown + +Class QAbstractEventDispatcher + size=16 align=8 + base size=16 base align=8 +QAbstractEventDispatcher (0x0x7ff7100380d0) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7ff71002d1e0) 0 + primary-for QAbstractEventDispatcher (0x0x7ff7100380d0) + +Vtable for QAbstractNativeEventFilter +QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class QAbstractNativeEventFilter + size=16 align=8 + base size=16 base align=8 +QAbstractNativeEventFilter (0x0x7ff71002d300) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7ff71002d360) 0 + +Vtable for QEvent +QEvent::_ZTV6QEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QEvent) +16 (int (*)(...))QEvent::~QEvent +24 (int (*)(...))QEvent::~QEvent + +Class QEvent + size=24 align=8 + base size=20 base align=8 +QEvent (0x0x7ff71002d4e0) 0 + vptr=((& QEvent::_ZTV6QEvent) + 16u) + +Vtable for QTimerEvent +QTimerEvent::_ZTV11QTimerEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTimerEvent) +16 (int (*)(...))QTimerEvent::~QTimerEvent +24 (int (*)(...))QTimerEvent::~QTimerEvent + +Class QTimerEvent + size=24 align=8 + base size=24 base align=8 +QTimerEvent (0x0x7ff7100381a0) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7ff71002d540) 0 + primary-for QTimerEvent (0x0x7ff7100381a0) + +Vtable for QChildEvent +QChildEvent::_ZTV11QChildEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QChildEvent) +16 (int (*)(...))QChildEvent::~QChildEvent +24 (int (*)(...))QChildEvent::~QChildEvent + +Class QChildEvent + size=32 align=8 + base size=32 base align=8 +QChildEvent (0x0x7ff710038208) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7ff71002d5a0) 0 + primary-for QChildEvent (0x0x7ff710038208) + +Vtable for QDynamicPropertyChangeEvent +QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI27QDynamicPropertyChangeEvent) +16 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent +24 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent + +Class QDynamicPropertyChangeEvent + size=32 align=8 + base size=32 base align=8 +QDynamicPropertyChangeEvent (0x0x7ff710038270) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7ff71002d600) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7ff710038270) + +Vtable for QDeferredDeleteEvent +QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QDeferredDeleteEvent) +16 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent +24 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent + +Class QDeferredDeleteEvent + size=24 align=8 + base size=24 base align=8 +QDeferredDeleteEvent (0x0x7ff7100382d8) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7ff71002d660) 0 + primary-for QDeferredDeleteEvent (0x0x7ff7100382d8) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7ff71002d720) 0 empty + +Vtable for QCoreApplication +QCoreApplication::_ZTV16QCoreApplication: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QCoreApplication) +16 (int (*)(...))QCoreApplication::metaObject +24 (int (*)(...))QCoreApplication::qt_metacast +32 (int (*)(...))QCoreApplication::qt_metacall +40 (int (*)(...))QCoreApplication::~QCoreApplication +48 (int (*)(...))QCoreApplication::~QCoreApplication +56 (int (*)(...))QCoreApplication::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QCoreApplication::notify +120 (int (*)(...))QCoreApplication::compressEvent + +Class QCoreApplication + size=16 align=8 + base size=16 base align=8 +QCoreApplication (0x0x7ff710038340) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7ff71002d6c0) 0 + primary-for QCoreApplication (0x0x7ff710038340) + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7ff71002d7e0) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7ff71002d960) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7ff71002db40) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7ff71002dba0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7ff71002dd80) 0 empty + +Vtable for QMimeData +QMimeData::_ZTV9QMimeData: 17u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QMimeData) +16 (int (*)(...))QMimeData::metaObject +24 (int (*)(...))QMimeData::qt_metacast +32 (int (*)(...))QMimeData::qt_metacall +40 (int (*)(...))QMimeData::~QMimeData +48 (int (*)(...))QMimeData::~QMimeData +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QMimeData::hasFormat +120 (int (*)(...))QMimeData::formats +128 (int (*)(...))QMimeData::retrieveData + +Class QMimeData + size=16 align=8 + base size=16 base align=8 +QMimeData (0x0x7ff7100384e0) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7ff71002dd20) 0 + primary-for QMimeData (0x0x7ff7100384e0) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7ff71002de40) 0 empty + +Vtable for QObjectCleanupHandler +QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QObjectCleanupHandler) +16 (int (*)(...))QObjectCleanupHandler::metaObject +24 (int (*)(...))QObjectCleanupHandler::qt_metacast +32 (int (*)(...))QObjectCleanupHandler::qt_metacall +40 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler +48 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QObjectCleanupHandler + size=24 align=8 + base size=24 base align=8 +QObjectCleanupHandler (0x0x7ff710038548) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7ff71002dde0) 0 + primary-for QObjectCleanupHandler (0x0x7ff710038548) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7ff70fd690c0) 0 empty + +Vtable for QSharedMemory +QSharedMemory::_ZTV13QSharedMemory: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QSharedMemory) +16 (int (*)(...))QSharedMemory::metaObject +24 (int (*)(...))QSharedMemory::qt_metacast +32 (int (*)(...))QSharedMemory::qt_metacall +40 (int (*)(...))QSharedMemory::~QSharedMemory +48 (int (*)(...))QSharedMemory::~QSharedMemory +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSharedMemory + size=16 align=8 + base size=16 base align=8 +QSharedMemory (0x0x7ff7100385b0) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7ff70fd69060) 0 + primary-for QSharedMemory (0x0x7ff7100385b0) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7ff70fd69180) 0 empty + +Vtable for QSignalMapper +QSignalMapper::_ZTV13QSignalMapper: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QSignalMapper) +16 (int (*)(...))QSignalMapper::metaObject +24 (int (*)(...))QSignalMapper::qt_metacast +32 (int (*)(...))QSignalMapper::qt_metacall +40 (int (*)(...))QSignalMapper::~QSignalMapper +48 (int (*)(...))QSignalMapper::~QSignalMapper +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSignalMapper + size=16 align=8 + base size=16 base align=8 +QSignalMapper (0x0x7ff710038618) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7ff70fd69120) 0 + primary-for QSignalMapper (0x0x7ff710038618) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7ff70fd69240) 0 empty + +Vtable for QSocketNotifier +QSocketNotifier::_ZTV15QSocketNotifier: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QSocketNotifier) +16 (int (*)(...))QSocketNotifier::metaObject +24 (int (*)(...))QSocketNotifier::qt_metacast +32 (int (*)(...))QSocketNotifier::qt_metacall +40 (int (*)(...))QSocketNotifier::~QSocketNotifier +48 (int (*)(...))QSocketNotifier::~QSocketNotifier +56 (int (*)(...))QSocketNotifier::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QSocketNotifier + size=16 align=8 + base size=16 base align=8 +QSocketNotifier (0x0x7ff710038680) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7ff70fd691e0) 0 + primary-for QSocketNotifier (0x0x7ff710038680) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7ff70fd692a0) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7ff70fd693c0) 0 empty + +Vtable for QTimer +QTimer::_ZTV6QTimer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QTimer) +16 (int (*)(...))QTimer::metaObject +24 (int (*)(...))QTimer::qt_metacast +32 (int (*)(...))QTimer::qt_metacall +40 (int (*)(...))QTimer::~QTimer +48 (int (*)(...))QTimer::~QTimer +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QTimer::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QTimer + size=32 align=8 + base size=29 base align=8 +QTimer (0x0x7ff7100386e8) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7ff70fd69360) 0 + primary-for QTimer (0x0x7ff7100386e8) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7ff70fd69540) 0 empty + +Vtable for QTranslator +QTranslator::_ZTV11QTranslator: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QTranslator) +16 (int (*)(...))QTranslator::metaObject +24 (int (*)(...))QTranslator::qt_metacast +32 (int (*)(...))QTranslator::qt_metacall +40 (int (*)(...))QTranslator::~QTranslator +48 (int (*)(...))QTranslator::~QTranslator +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QTranslator::translate +120 (int (*)(...))QTranslator::isEmpty + +Class QTranslator + size=16 align=8 + base size=16 base align=8 +QTranslator (0x0x7ff7100387b8) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7ff70fd694e0) 0 + primary-for QTranslator (0x0x7ff7100387b8) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7ff70fd695a0) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7ff70fd69780) 0 + +Vtable for QFactoryInterface +QFactoryInterface::_ZTV17QFactoryInterface: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QFactoryInterface) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class QFactoryInterface + size=8 align=8 + base size=8 base align=8 +QFactoryInterface (0x0x7ff70fd697e0) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7ff70fd69900) 0 empty + +Vtable for QLibrary +QLibrary::_ZTV8QLibrary: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI8QLibrary) +16 (int (*)(...))QLibrary::metaObject +24 (int (*)(...))QLibrary::qt_metacast +32 (int (*)(...))QLibrary::qt_metacall +40 (int (*)(...))QLibrary::~QLibrary +48 (int (*)(...))QLibrary::~QLibrary +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QLibrary + size=32 align=8 + base size=25 base align=8 +QLibrary (0x0x7ff710038888) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7ff70fd698a0) 0 + primary-for QLibrary (0x0x7ff710038888) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7ff70fd69a80) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7ff70fd69c60) 0 empty + +Vtable for QPluginLoader +QPluginLoader::_ZTV13QPluginLoader: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QPluginLoader) +16 (int (*)(...))QPluginLoader::metaObject +24 (int (*)(...))QPluginLoader::qt_metacast +32 (int (*)(...))QPluginLoader::qt_metacall +40 (int (*)(...))QPluginLoader::~QPluginLoader +48 (int (*)(...))QPluginLoader::~QPluginLoader +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QPluginLoader + size=32 align=8 + base size=25 base align=8 +QPluginLoader (0x0x7ff710038a28) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7ff70fd69c00) 0 + primary-for QPluginLoader (0x0x7ff710038a28) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7ff70fd69cc0) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7ff70fd69ea0) 0 empty + +Vtable for QAbstractState +QAbstractState::_ZTV14QAbstractState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QAbstractState) +16 (int (*)(...))QAbstractState::metaObject +24 (int (*)(...))QAbstractState::qt_metacast +32 (int (*)(...))QAbstractState::qt_metacall +40 0u +48 0u +56 (int (*)(...))QAbstractState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QAbstractState + size=16 align=8 + base size=16 base align=8 +QAbstractState (0x0x7ff710038af8) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7ff70fd69e40) 0 + primary-for QAbstractState (0x0x7ff710038af8) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7ff70fd69f60) 0 empty + +Vtable for QAbstractTransition +QAbstractTransition::_ZTV19QAbstractTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTransition) +16 (int (*)(...))QAbstractTransition::metaObject +24 (int (*)(...))QAbstractTransition::qt_metacast +32 (int (*)(...))QAbstractTransition::qt_metacall +40 0u +48 0u +56 (int (*)(...))QAbstractTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QAbstractTransition + size=16 align=8 + base size=16 base align=8 +QAbstractTransition (0x0x7ff710038b60) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7ff70fd69f00) 0 + primary-for QAbstractTransition (0x0x7ff710038b60) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7ff70febb060) 0 empty + +Vtable for QEventTransition +QEventTransition::_ZTV16QEventTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QEventTransition) +16 (int (*)(...))QEventTransition::metaObject +24 (int (*)(...))QEventTransition::qt_metacast +32 (int (*)(...))QEventTransition::qt_metacall +40 (int (*)(...))QEventTransition::~QEventTransition +48 (int (*)(...))QEventTransition::~QEventTransition +56 (int (*)(...))QEventTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QEventTransition::eventTest +120 (int (*)(...))QEventTransition::onTransition + +Class QEventTransition + size=16 align=8 + base size=16 base align=8 +QEventTransition (0x0x7ff710038bc8) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7ff710038c30) 0 + primary-for QEventTransition (0x0x7ff710038bc8) + QObject (0x0x7ff70febb000) 0 + primary-for QAbstractTransition (0x0x7ff710038c30) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7ff70febb120) 0 empty + +Vtable for QFinalState +QFinalState::_ZTV11QFinalState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QFinalState) +16 (int (*)(...))QFinalState::metaObject +24 (int (*)(...))QFinalState::qt_metacast +32 (int (*)(...))QFinalState::qt_metacall +40 (int (*)(...))QFinalState::~QFinalState +48 (int (*)(...))QFinalState::~QFinalState +56 (int (*)(...))QFinalState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QFinalState::onEntry +120 (int (*)(...))QFinalState::onExit + +Class QFinalState + size=16 align=8 + base size=16 base align=8 +QFinalState (0x0x7ff710038c98) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7ff710038d00) 0 + primary-for QFinalState (0x0x7ff710038c98) + QObject (0x0x7ff70febb0c0) 0 + primary-for QAbstractState (0x0x7ff710038d00) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7ff70febb1e0) 0 empty + +Vtable for QHistoryState +QHistoryState::_ZTV13QHistoryState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QHistoryState) +16 (int (*)(...))QHistoryState::metaObject +24 (int (*)(...))QHistoryState::qt_metacast +32 (int (*)(...))QHistoryState::qt_metacall +40 (int (*)(...))QHistoryState::~QHistoryState +48 (int (*)(...))QHistoryState::~QHistoryState +56 (int (*)(...))QHistoryState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QHistoryState::onEntry +120 (int (*)(...))QHistoryState::onExit + +Class QHistoryState + size=16 align=8 + base size=16 base align=8 +QHistoryState (0x0x7ff710038d68) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7ff710038dd0) 0 + primary-for QHistoryState (0x0x7ff710038d68) + QObject (0x0x7ff70febb180) 0 + primary-for QAbstractState (0x0x7ff710038dd0) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7ff70febb2a0) 0 empty + +Vtable for QSignalTransition +QSignalTransition::_ZTV17QSignalTransition: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QSignalTransition) +16 (int (*)(...))QSignalTransition::metaObject +24 (int (*)(...))QSignalTransition::qt_metacast +32 (int (*)(...))QSignalTransition::qt_metacall +40 (int (*)(...))QSignalTransition::~QSignalTransition +48 (int (*)(...))QSignalTransition::~QSignalTransition +56 (int (*)(...))QSignalTransition::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QSignalTransition::eventTest +120 (int (*)(...))QSignalTransition::onTransition + +Class QSignalTransition + size=16 align=8 + base size=16 base align=8 +QSignalTransition (0x0x7ff710038e38) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7ff710038ea0) 0 + primary-for QSignalTransition (0x0x7ff710038e38) + QObject (0x0x7ff70febb240) 0 + primary-for QAbstractTransition (0x0x7ff710038ea0) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7ff70febb360) 0 empty + +Vtable for QState +QState::_ZTV6QState: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI6QState) +16 (int (*)(...))QState::metaObject +24 (int (*)(...))QState::qt_metacast +32 (int (*)(...))QState::qt_metacall +40 (int (*)(...))QState::~QState +48 (int (*)(...))QState::~QState +56 (int (*)(...))QState::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QState::onEntry +120 (int (*)(...))QState::onExit + +Class QState + size=16 align=8 + base size=16 base align=8 +QState (0x0x7ff710038f08) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7ff710038f70) 0 + primary-for QState (0x0x7ff710038f08) + QObject (0x0x7ff70febb300) 0 + primary-for QAbstractState (0x0x7ff710038f70) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7ff70febb480) 0 empty + +Vtable for QStateMachine::SignalEvent +QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN13QStateMachine11SignalEventE) +16 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent +24 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent + +Class QStateMachine::SignalEvent + size=48 align=8 + base size=48 base align=8 +QStateMachine::SignalEvent (0x0x7ff70ff22138) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7ff70febb4e0) 0 + primary-for QStateMachine::SignalEvent (0x0x7ff70ff22138) + +Vtable for QStateMachine::WrappedEvent +QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN13QStateMachine12WrappedEventE) +16 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent +24 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent + +Class QStateMachine::WrappedEvent + size=40 align=8 + base size=40 base align=8 +QStateMachine::WrappedEvent (0x0x7ff70ff221a0) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7ff70febb540) 0 + primary-for QStateMachine::WrappedEvent (0x0x7ff70ff221a0) + +Vtable for QStateMachine +QStateMachine::_ZTV13QStateMachine: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI13QStateMachine) +16 (int (*)(...))QStateMachine::metaObject +24 (int (*)(...))QStateMachine::qt_metacast +32 (int (*)(...))QStateMachine::qt_metacall +40 (int (*)(...))QStateMachine::~QStateMachine +48 (int (*)(...))QStateMachine::~QStateMachine +56 (int (*)(...))QStateMachine::event +64 (int (*)(...))QStateMachine::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QStateMachine::onEntry +120 (int (*)(...))QStateMachine::onExit +128 (int (*)(...))QStateMachine::beginSelectTransitions +136 (int (*)(...))QStateMachine::endSelectTransitions +144 (int (*)(...))QStateMachine::beginMicrostep +152 (int (*)(...))QStateMachine::endMicrostep + +Class QStateMachine + size=16 align=8 + base size=16 base align=8 +QStateMachine (0x0x7ff70ff22000) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7ff70ff22068) 0 + primary-for QStateMachine (0x0x7ff70ff22000) + QAbstractState (0x0x7ff70ff220d0) 0 + primary-for QState (0x0x7ff70ff22068) + QObject (0x0x7ff70febb420) 0 + primary-for QAbstractState (0x0x7ff70ff220d0) + +Vtable for QException +QException::_ZTV10QException: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI10QException) +16 (int (*)(...))QException::~QException +24 (int (*)(...))QException::~QException +32 (int (*)(...))std::exception::what +40 (int (*)(...))QException::raise +48 (int (*)(...))QException::clone + +Class QException + size=8 align=8 + base size=8 base align=8 +QException (0x0x7ff70ff22208) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7ff70febb5a0) 0 nearly-empty + primary-for QException (0x0x7ff70ff22208) + +Vtable for QUnhandledException +QUnhandledException::_ZTV19QUnhandledException: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QUnhandledException) +16 (int (*)(...))QUnhandledException::~QUnhandledException +24 (int (*)(...))QUnhandledException::~QUnhandledException +32 (int (*)(...))std::exception::what +40 (int (*)(...))QUnhandledException::raise +48 (int (*)(...))QUnhandledException::clone + +Class QUnhandledException + size=8 align=8 + base size=8 base align=8 +QUnhandledException (0x0x7ff70ff22270) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7ff70ff222d8) 0 nearly-empty + primary-for QUnhandledException (0x0x7ff70ff22270) + std::exception (0x0x7ff70febb600) 0 nearly-empty + primary-for QException (0x0x7ff70ff222d8) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7ff70febb660) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7ff70febb720) 0 + +Vtable for QRunnable +QRunnable::_ZTV9QRunnable: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QRunnable) +16 (int (*)(...))__cxa_pure_virtual +24 0u +32 0u + +Class QRunnable + size=16 align=8 + base size=12 base align=8 +QRunnable (0x0x7ff70febb780) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7ff70febb7e0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7ff70ff22410) 0 + QBasicMutex (0x0x7ff70febba20) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7ff70febba80) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7ff70febbb40) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7ff70febbba0) 0 + +Vtable for QtPrivate::ResultStoreBase +QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9QtPrivate15ResultStoreBaseE) +16 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase +24 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase + +Class QtPrivate::ResultStoreBase + size=48 align=8 + base size=44 base align=8 +QtPrivate::ResultStoreBase (0x0x7ff70febbd20) 0 + vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16u) + +Vtable for QFutureInterfaceBase +QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QFutureInterfaceBase) +16 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase +24 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase + +Class QFutureInterfaceBase + size=16 align=8 + base size=16 base align=8 +QFutureInterfaceBase (0x0x7ff70febbde0) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7ff70fc9f180) 0 empty + +Vtable for QFutureWatcherBase +QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFutureWatcherBase) +16 (int (*)(...))QFutureWatcherBase::metaObject +24 (int (*)(...))QFutureWatcherBase::qt_metacast +32 (int (*)(...))QFutureWatcherBase::qt_metacall +40 0u +48 0u +56 (int (*)(...))QFutureWatcherBase::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QFutureWatcherBase::connectNotify +104 (int (*)(...))QFutureWatcherBase::disconnectNotify +112 (int (*)(...))__cxa_pure_virtual +120 (int (*)(...))__cxa_pure_virtual + +Class QFutureWatcherBase + size=16 align=8 + base size=16 base align=8 +QFutureWatcherBase (0x0x7ff70ff22c98) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7ff70fc9f120) 0 + primary-for QFutureWatcherBase (0x0x7ff70ff22c98) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7ff70fc9f2a0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7ff70fc9f540) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7ff70fc9f5a0) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7ff70fc9f600) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7ff70fc9f6c0) 0 empty + +Vtable for QThread +QThread::_ZTV7QThread: 15u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI7QThread) +16 (int (*)(...))QThread::metaObject +24 (int (*)(...))QThread::qt_metacast +32 (int (*)(...))QThread::qt_metacall +40 (int (*)(...))QThread::~QThread +48 (int (*)(...))QThread::~QThread +56 (int (*)(...))QThread::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QThread::run + +Class QThread + size=16 align=8 + base size=16 base align=8 +QThread (0x0x7ff70fd07270) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7ff70fc9f660) 0 + primary-for QThread (0x0x7ff70fd07270) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7ff70fc9f780) 0 empty + +Vtable for QThreadPool +QThreadPool::_ZTV11QThreadPool: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI11QThreadPool) +16 (int (*)(...))QThreadPool::metaObject +24 (int (*)(...))QThreadPool::qt_metacast +32 (int (*)(...))QThreadPool::qt_metacall +40 (int (*)(...))QThreadPool::~QThreadPool +48 (int (*)(...))QThreadPool::~QThreadPool +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify + +Class QThreadPool + size=16 align=8 + base size=16 base align=8 +QThreadPool (0x0x7ff70fd072d8) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7ff70fc9f720) 0 + primary-for QThreadPool (0x0x7ff70fd072d8) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7ff70fc9f7e0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7ff70fc9f8a0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7ff70fc9fd80) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7ff70fa64000) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7ff70fa64240) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7ff70fa641e0) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7ff70fa643c0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7ff70fa64480) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7ff70fb2e240) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7ff70fb2e420) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7ff70fb2e480) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7ff70fb2e4e0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7ff70fb2e540) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7ff70fb2e6c0) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7ff70fb2e840) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7ff70fb2e9c0) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7ff70fb2eb40) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7ff70f8a3300) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7ff70f8a3480) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7ff70f8a3600) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7ff70f8a36c0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7ff70f8a3900) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7ff70f8a3b40) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7ff70f8a3cc0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7ff70f8a3e40) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7ff70f72c2a0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7ff70f72c480) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7ff70f72c840) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7ff70f4102a0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7ff70f410480) 0 empty + +Vtable for QTimeLine +QTimeLine::_ZTV9QTimeLine: 15u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QTimeLine) +16 (int (*)(...))QTimeLine::metaObject +24 (int (*)(...))QTimeLine::qt_metacast +32 (int (*)(...))QTimeLine::qt_metacall +40 (int (*)(...))QTimeLine::~QTimeLine +48 (int (*)(...))QTimeLine::~QTimeLine +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QTimeLine::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QTimeLine::valueForTime + +Class QTimeLine + size=16 align=8 + base size=16 base align=8 +QTimeLine (0x0x7ff70f4410d0) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7ff70f410420) 0 + primary-for QTimeLine (0x0x7ff70f4410d0) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7ff70f410540) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7ff70f4104e0) 0 + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7ff70f4108a0) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7ff70f410840) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7ff70f53e660) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7ff70f20d360) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7ff70f20b8f0) 0 + QVector (0x0x7ff70f20d600) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7ff70f20d660) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7ff70f20d7e0) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7ff70f20d960) 0 + +Vtable for QXmlStreamEntityResolver +QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QXmlStreamEntityResolver) +16 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver +24 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver +32 (int (*)(...))QXmlStreamEntityResolver::resolveEntity +40 (int (*)(...))QXmlStreamEntityResolver::resolveUndeclaredEntity + +Class QXmlStreamEntityResolver + size=8 align=8 + base size=8 base align=8 +QXmlStreamEntityResolver (0x0x7ff70f20dae0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7ff70f20db40) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7ff70f20dc60) 0 + +Class QGeoAddress + size=8 align=8 + base size=8 base align=8 +QGeoAddress (0x0x7ff70f20dd80) 0 + +Class QGeoCoordinate + size=8 align=8 + base size=8 base align=8 +QGeoCoordinate (0x0x7ff70f32b0c0) 0 + +Class QGeoShape + size=8 align=8 + base size=8 base align=8 +QGeoShape (0x0x7ff70f32b3c0) 0 + +Class QGeoAreaMonitorInfo + size=8 align=8 + base size=8 base align=8 +QGeoAreaMonitorInfo (0x0x7ff70f32b6c0) 0 + +Class QGeoPositionInfo + size=8 align=8 + base size=8 base align=8 +QGeoPositionInfo (0x0x7ff70f32b780) 0 + +Class QGeoPositionInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoPositionInfoSource::QPrivateSignal (0x0x7ff70f32b840) 0 empty + +Vtable for QGeoPositionInfoSource +QGeoPositionInfoSource::_ZTV22QGeoPositionInfoSource: 23u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QGeoPositionInfoSource) +16 (int (*)(...))QGeoPositionInfoSource::metaObject +24 (int (*)(...))QGeoPositionInfoSource::qt_metacast +32 (int (*)(...))QGeoPositionInfoSource::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoPositionInfoSource::setUpdateInterval +120 (int (*)(...))QGeoPositionInfoSource::setPreferredPositioningMethods +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual + +Class QGeoPositionInfoSource + size=24 align=8 + base size=24 base align=8 +QGeoPositionInfoSource (0x0x7ff70f20bf70) 0 + vptr=((& QGeoPositionInfoSource::_ZTV22QGeoPositionInfoSource) + 16u) + QObject (0x0x7ff70f32b7e0) 0 + primary-for QGeoPositionInfoSource (0x0x7ff70f20bf70) + +Class QGeoAreaMonitorSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoAreaMonitorSource::QPrivateSignal (0x0x7ff70f32ba20) 0 empty + +Vtable for QGeoAreaMonitorSource +QGeoAreaMonitorSource::_ZTV21QGeoAreaMonitorSource: 23u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QGeoAreaMonitorSource) +16 (int (*)(...))QGeoAreaMonitorSource::metaObject +24 (int (*)(...))QGeoAreaMonitorSource::qt_metacast +32 (int (*)(...))QGeoAreaMonitorSource::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoAreaMonitorSource::setPositionInfoSource +120 (int (*)(...))QGeoAreaMonitorSource::positionInfoSource +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual +160 (int (*)(...))__cxa_pure_virtual +168 (int (*)(...))__cxa_pure_virtual +176 (int (*)(...))__cxa_pure_virtual + +Class QGeoAreaMonitorSource + size=24 align=8 + base size=24 base align=8 +QGeoAreaMonitorSource (0x0x7ff70f20bb60) 0 + vptr=((& QGeoAreaMonitorSource::_ZTV21QGeoAreaMonitorSource) + 16u) + QObject (0x0x7ff70f32b9c0) 0 + primary-for QGeoAreaMonitorSource (0x0x7ff70f20bb60) + +Class QGeoCircle + size=8 align=8 + base size=8 base align=8 +QGeoCircle (0x0x7ff70f20bc98) 0 + QGeoShape (0x0x7ff70f32ba80) 0 + +Class QGeoLocation + size=8 align=8 + base size=8 base align=8 +QGeoLocation (0x0x7ff70f32bd20) 0 + +Class QGeoSatelliteInfo + size=8 align=8 + base size=8 base align=8 +QGeoSatelliteInfo (0x0x7ff70f004060) 0 + +Class QGeoSatelliteInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QGeoSatelliteInfoSource::QPrivateSignal (0x0x7ff70f004120) 0 empty + +Vtable for QGeoSatelliteInfoSource +QGeoSatelliteInfoSource::_ZTV23QGeoSatelliteInfoSource: 20u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QGeoSatelliteInfoSource) +16 (int (*)(...))QGeoSatelliteInfoSource::metaObject +24 (int (*)(...))QGeoSatelliteInfoSource::qt_metacast +32 (int (*)(...))QGeoSatelliteInfoSource::qt_metacall +40 0u +48 0u +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QGeoSatelliteInfoSource::setUpdateInterval +120 (int (*)(...))__cxa_pure_virtual +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))__cxa_pure_virtual +152 (int (*)(...))__cxa_pure_virtual + +Class QGeoSatelliteInfoSource + size=24 align=8 + base size=24 base align=8 +QGeoSatelliteInfoSource (0x0x7ff70effc068) 0 + vptr=((& QGeoSatelliteInfoSource::_ZTV23QGeoSatelliteInfoSource) + 16u) + QObject (0x0x7ff70f0040c0) 0 + primary-for QGeoSatelliteInfoSource (0x0x7ff70effc068) + +Vtable for QGeoPositionInfoSourceFactory +QGeoPositionInfoSourceFactory::_ZTV29QGeoPositionInfoSourceFactory: 7u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI29QGeoPositionInfoSourceFactory) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual +40 (int (*)(...))__cxa_pure_virtual +48 (int (*)(...))__cxa_pure_virtual + +Class QGeoPositionInfoSourceFactory + size=8 align=8 + base size=8 base align=8 +QGeoPositionInfoSourceFactory (0x0x7ff70f0041e0) 0 nearly-empty + vptr=((& QGeoPositionInfoSourceFactory::_ZTV29QGeoPositionInfoSourceFactory) + 16u) + +Class QGeoRectangle + size=8 align=8 + base size=8 base align=8 +QGeoRectangle (0x0x7ff70effc0d0) 0 + QGeoShape (0x0x7ff70f0042a0) 0 + +Class QNmeaPositionInfoSource::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNmeaPositionInfoSource::QPrivateSignal (0x0x7ff70f0046c0) 0 empty + +Vtable for QNmeaPositionInfoSource +QNmeaPositionInfoSource::_ZTV23QNmeaPositionInfoSource: 24u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QNmeaPositionInfoSource) +16 (int (*)(...))QNmeaPositionInfoSource::metaObject +24 (int (*)(...))QNmeaPositionInfoSource::qt_metacast +32 (int (*)(...))QNmeaPositionInfoSource::qt_metacall +40 (int (*)(...))QNmeaPositionInfoSource::~QNmeaPositionInfoSource +48 (int (*)(...))QNmeaPositionInfoSource::~QNmeaPositionInfoSource +56 (int (*)(...))QObject::event +64 (int (*)(...))QObject::eventFilter +72 (int (*)(...))QObject::timerEvent +80 (int (*)(...))QObject::childEvent +88 (int (*)(...))QObject::customEvent +96 (int (*)(...))QObject::connectNotify +104 (int (*)(...))QObject::disconnectNotify +112 (int (*)(...))QNmeaPositionInfoSource::setUpdateInterval +120 (int (*)(...))QGeoPositionInfoSource::setPreferredPositioningMethods +128 (int (*)(...))QNmeaPositionInfoSource::lastKnownPosition +136 (int (*)(...))QNmeaPositionInfoSource::supportedPositioningMethods +144 (int (*)(...))QNmeaPositionInfoSource::minimumUpdateInterval +152 (int (*)(...))QNmeaPositionInfoSource::error +160 (int (*)(...))QNmeaPositionInfoSource::startUpdates +168 (int (*)(...))QNmeaPositionInfoSource::stopUpdates +176 (int (*)(...))QNmeaPositionInfoSource::requestUpdate +184 (int (*)(...))QNmeaPositionInfoSource::parsePosInfoFromNmeaData + +Class QNmeaPositionInfoSource + size=32 align=8 + base size=32 base align=8 +QNmeaPositionInfoSource (0x0x7ff70effc270) 0 + vptr=((& QNmeaPositionInfoSource::_ZTV23QNmeaPositionInfoSource) + 16u) + QGeoPositionInfoSource (0x0x7ff70effc2d8) 0 + primary-for QNmeaPositionInfoSource (0x0x7ff70effc270) + QObject (0x0x7ff70f004660) 0 + primary-for QGeoPositionInfoSource (0x0x7ff70effc2d8) + diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt new file mode 100644 index 0000000..8430084 --- /dev/null +++ b/tests/auto/cmake/CMakeLists.txt @@ -0,0 +1,19 @@ + +cmake_minimum_required(VERSION 2.8) + +project(qmake_cmake_files) + +enable_testing() + +find_package(Qt5Core REQUIRED) + +include("${_Qt5CTestMacros}") + +set(qt_module_includes + Location QPlaceCategory + Positioning QGeoRectangle +) + +test_module_includes( + ${qt_module_includes} +) diff --git a/tests/auto/cmake/cmake.pro b/tests/auto/cmake/cmake.pro new file mode 100644 index 0000000..69540e9 --- /dev/null +++ b/tests/auto/cmake/cmake.pro @@ -0,0 +1,7 @@ + +# Cause make to do nothing. +TEMPLATE = subdirs + +CMAKE_QT_MODULES_UNDER_TEST = location positioning + +CONFIG += ctest_testcase diff --git a/tests/auto/declarative_core/declarative_core.pro b/tests/auto/declarative_core/declarative_core.pro new file mode 100644 index 0000000..30c2b7f --- /dev/null +++ b/tests/auto/declarative_core/declarative_core.pro @@ -0,0 +1,14 @@ +# QML tests in this directory must not depend on an OpenGL context. +# QML tests that do require an OpenGL context must go in ../../declarative_ui. + +TEMPLATE = app +TARGET = tst_declarative_core +CONFIG += qmltestcase +SOURCES += main.cpp + +CONFIG -= app_bundle + +QT += location quick + +OTHER_FILES = *.qml *.js +TESTDATA = $$OTHER_FILES diff --git a/tests/auto/declarative_core/main.cpp b/tests/auto/declarative_core/main.cpp new file mode 100644 index 0000000..041dbb7 --- /dev/null +++ b/tests/auto/declarative_core/main.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +static void initializeLibraryPath() +{ + // Set custom path since CI doesn't install test plugins +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif +} + +Q_COREAPP_STARTUP_FUNCTION(initializeLibraryPath) + +QUICK_TEST_MAIN(declarative_core) diff --git a/tests/auto/declarative_core/tst_address.qml b/tests/auto/declarative_core/tst_address.qml new file mode 100644 index 0000000..94f986c --- /dev/null +++ b/tests/auto/declarative_core/tst_address.qml @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtTest 1.0 +import QtPositioning 5.2 + +TestCase { + id: testCase + + name: "Address" + + Address { + id: address + + street: "742 Evergreen Tce" + district: "Pressboard Estates" + city: "Springfield" + state: "Oregon" + postalCode: "8900" + country: "United States" + countryCode: "USA" + } + + function test_qmlAddressText() { + compare(address.isTextGenerated, true); + compare(address.text, "742 Evergreen Tce
Springfield, Oregon 8900
United States"); + var textChangedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + textChangedSpy.target = address; + textChangedSpy.signalName = "textChanged" + + var isTextGeneratedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + isTextGeneratedSpy.target = address + isTextGeneratedSpy.signalName = "isTextGeneratedChanged" + + address.countryCode = "FRA"; + compare(address.text, "742 Evergreen Tce
8900 Springfield
United States"); + compare(textChangedSpy.count, 1); + textChangedSpy.clear(); + compare(isTextGeneratedSpy.count, 0); + + address.text = "address label"; + compare(address.isTextGenerated, false); + compare(address.text, "address label"); + compare(textChangedSpy.count, 1); + textChangedSpy.clear(); + compare(isTextGeneratedSpy.count, 1); + isTextGeneratedSpy.clear(); + + address.countryCode = "USA"; + compare(address.text, "address label"); + compare(textChangedSpy.count, 0); + textChangedSpy.clear(); + compare(isTextGeneratedSpy.count, 0); + + address.text = ""; + compare(address.isTextGenerated, true); + compare(address.text, "742 Evergreen Tce
Springfield, Oregon 8900
United States"); + compare(textChangedSpy.count, 1); + textChangedSpy.clear(); + compare(isTextGeneratedSpy.count, 1); + isTextGeneratedSpy.clear(); + } +} diff --git a/tests/auto/declarative_core/tst_category.qml b/tests/auto/declarative_core/tst_category.qml new file mode 100644 index 0000000..51809dc --- /dev/null +++ b/tests/auto/declarative_core/tst_category.qml @@ -0,0 +1,236 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "Category" + + Category { id: emptyCategory } + + function test_empty() { + compare(emptyCategory.categoryId, ""); + compare(emptyCategory.name, ""); + compare(emptyCategory.visibility, Category.UnspecifiedVisibility); + compare(emptyCategory.status, Category.Ready); + compare(emptyCategory.plugin, null); + verify(emptyCategory.icon); + } + + Category { + id: qmlCategory + + plugin: testPlugin + + categoryId: "test-category-id" + name: "Test Category" + visibility: Category.DeviceVisibility + + icon: Icon { + Component.onCompleted: { + parameters.singleUrl = "http://example.com/icons/test-category.png" + } + } + } + + function test_qmlConstructedCategory() { + compare(qmlCategory.categoryId, "test-category-id"); + compare(qmlCategory.name, "Test Category"); + compare(qmlCategory.visibility, Category.DeviceVisibility); + compare(qmlCategory.status, Category.Ready); + compare(qmlCategory.plugin, testPlugin); + verify(qmlCategory.icon); + compare(qmlCategory.icon.url(), "http://example.com/icons/test-category.png"); + compare(qmlCategory.icon.parameters.singleUrl, "http://example.com/icons/test-category.png"); + compare(qmlCategory.icon.plugin, qmlCategory.plugin); + } + + Category { + id: testCategory + } + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + } + + Plugin { + id: invalidPlugin + } + + Icon { + id: testIcon + } + + Category { + id: saveCategory + + name: "Test Category" + visibility: Place.DeviceVisibility + } + + VisualDataModel { + id: categoryModel + + model: CategoryModel { + plugin: testPlugin + } + delegate: Item { } + } + + function test_setAndGet_data() { + return [ + { tag: "name", property: "name", signal: "nameChanged", value: "Test Category", reset: "" }, + { tag: "categoryId", property: "categoryId", signal: "categoryIdChanged", value: "test-category-id-1", reset: "" }, + { tag: "visibility", property: "visibility", signal: "visibilityChanged", value: Place.PublicVisibility, reset: Place.UnspecifiedVisibility }, + { tag: "plugin", property: "plugin", signal: "pluginChanged", value: testPlugin }, + { tag: "icon", property: "icon", signal: "iconChanged", value: testIcon } + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testCategory, data); + } + + function test_save() { + categoryModel.model.update(); + tryCompare(categoryModel.model, "status", CategoryModel.Ready); + compare(categoryModel.count, 0); + + saveCategory.plugin = testPlugin; + saveCategory.categoryId = "invalid-category-id"; + + saveCategory.save(); + + compare(saveCategory.status, Category.Saving); + verify(saveCategory.errorString().length === 0); + + tryCompare(saveCategory, "status", Category.Error); + verify(saveCategory.errorString().length > 0); + + // try again without an invalid categoryId + saveCategory.categoryId = ""; + saveCategory.save(); + + compare(saveCategory.status, Category.Saving); + + tryCompare(saveCategory, "status", Category.Ready); + verify(saveCategory.errorString().length === 0); + + verify(saveCategory.categoryId !== ""); + + + // Verify that the category was added to the model + categoryModel.model.update(); + compare(categoryModel.model.status, CategoryModel.Loading); + + tryCompare(categoryModel.model, "status", CategoryModel.Ready); + + compare(categoryModel.count, 1); + var modelCategory = categoryModel.model.data(categoryModel.modelIndex(0), + CategoryModel.CategoryRole); + compare(modelCategory.categoryId, saveCategory.categoryId); + compare(modelCategory.name, saveCategory.name); + + + // Remove a category + saveCategory.remove(); + + compare(saveCategory.status, Category.Removing); + + tryCompare(saveCategory, "status", Category.Ready); + verify(saveCategory.errorString().length === 0); + + + // Verify that the category was removed from the model + categoryModel.model.update(); + compare(categoryModel.model.status, CategoryModel.Loading); + + tryCompare(categoryModel.model, "status", CategoryModel.Ready); + + compare(categoryModel.count, 0); + + + // Try again, this time fail because category does not exist + saveCategory.remove(); + + compare(saveCategory.status, Category.Removing); + + tryCompare(saveCategory, "status", Category.Error); + + verify(saveCategory.errorString().length > 0); + } + + function test_saveWithoutPlugin() { + saveCategory.plugin = null; + saveCategory.categoryId = ""; + + saveCategory.save(); + + tryCompare(saveCategory, "status", Category.Error); + + verify(saveCategory.errorString().length > 0); + compare(saveCategory.categoryId, ""); + + saveCategory.plugin = invalidPlugin; + + saveCategory.save(); + + compare(saveCategory.status, Category.Error); + + verify(saveCategory.errorString().length > 0); + compare(saveCategory.categoryId, ""); + } + + function test_removeWithoutPlugin() { + saveCategory.plugin = null; + saveCategory.categoryId = "test-category-id"; + + saveCategory.remove(); + + compare(saveCategory.status, Category.Error); + + verify(saveCategory.errorString().length > 0); + compare(saveCategory.categoryId, "test-category-id"); + + saveCategory.plugin = invalidPlugin; + + saveCategory.remove(); + + compare(saveCategory.status, Category.Error); + + verify(saveCategory.errorString().length > 0); + compare(saveCategory.categoryId, "test-category-id"); + } +} diff --git a/tests/auto/declarative_core/tst_categorymodel.qml b/tests/auto/declarative_core/tst_categorymodel.qml new file mode 100644 index 0000000..0b6e50a --- /dev/null +++ b/tests/auto/declarative_core/tst_categorymodel.qml @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "CategoryModel" + + CategoryModel { + id: testModel + } + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + PluginParameter { + name: "initializePlaceData" + value: true + } + ] + } + + Plugin { + id: uninitializedPlugin + } + + Plugin { + id: nonExistantPlugin + name: "nonExistentName" + } + + function test_setAndGet_data() { + return [ + { tag: "plugin", property: "plugin", signal: "pluginChanged", value: testPlugin }, + { tag: "hierarchical", property: "hierarchical", signal: "hierarchicalChanged", value: false, reset: true }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testModel, data); + } + + function test_hierarchicalModel() { + var modelSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + var categoryModel = Qt.createQmlObject('import QtQuick 2.0; import QtLocation 5.3;' + + 'VisualDataModel { model: CategoryModel {} delegate: Item {} }', + testCase, "VisualDataModel"); + + modelSpy.target = categoryModel.model; + modelSpy.signalName = "statusChanged"; + + compare(categoryModel.model.status, CategoryModel.Null); + compare(categoryModel.count, 0); + + + // set the plugin + categoryModel.model.plugin = testPlugin; + categoryModel.model.update(); + tryCompare(categoryModel.model, "status", CategoryModel.Loading); + compare(modelSpy.count, 1); + + tryCompare(categoryModel.model, "status", CategoryModel.Ready); + compare(modelSpy.count, 2); + compare(categoryModel.model.errorString(), ""); + + var expectedNames = [ "Accommodation", "Park" ]; + + compare(categoryModel.count, expectedNames.length); + + for (var i = 0; i < expectedNames.length; ++i) { + var category = categoryModel.model.data(categoryModel.modelIndex(i), + CategoryModel.CategoryRole); + compare(category.name, expectedNames[i]); + } + + + // check that "Accommodation" has children + categoryModel.rootIndex = categoryModel.modelIndex(0); + + expectedNames = [ "Camping", "Hotel", "Motel" ]; + + compare(categoryModel.count, expectedNames.length); + + for (i = 0; i < expectedNames.length; ++i) { + category = categoryModel.model.data(categoryModel.modelIndex(i), + CategoryModel.CategoryRole); + compare(category.name, expectedNames[i]); + + var parentCategory = categoryModel.model.data(categoryModel.modelIndex(i), + CategoryModel.ParentCategoryRole); + compare(parentCategory.name, "Accommodation"); + } + + categoryModel.rootIndex = categoryModel.parentModelIndex(); + + compare(categoryModel.count, 2); + + + // check that "Park" has no children + categoryModel.rootIndex = categoryModel.modelIndex(1); + + compare(categoryModel.count, 0); + + categoryModel.rootIndex = categoryModel.parentModelIndex(); + + + // clean up + categoryModel.model.plugin = null; + categoryModel.model.update(); + + // check that the model is empty when an error is encountered + tryCompare(categoryModel, "count", 0); + compare(categoryModel.model.status, CategoryModel.Error); + } + + function test_flatModel() { + var modelSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + var categoryModel = Qt.createQmlObject('import QtQuick 2.0; import QtLocation 5.3;' + + 'VisualDataModel { model: CategoryModel {} delegate: Item {} }', + testCase, "VisualDataModel"); + + modelSpy.target = categoryModel.model; + modelSpy.signalName = "statusChanged"; + + compare(categoryModel.model.status, CategoryModel.Null); + compare(categoryModel.count, 0); + + + // set the plugin + categoryModel.model.hierarchical = false; + categoryModel.model.plugin = testPlugin; + + categoryModel.model.update(); + tryCompare(categoryModel.model, "status", CategoryModel.Loading); + compare(modelSpy.count, 1); + + tryCompare(categoryModel.model, "status", CategoryModel.Ready); + compare(modelSpy.count, 2); + + var expectedNames = [ "Accommodation", "Camping", "Hotel", "Motel", "Park" ]; + + compare(categoryModel.count, expectedNames.length); + + for (var i = 0; i < expectedNames.length; ++i) { + var category = categoryModel.model.data(categoryModel.modelIndex(i), + CategoryModel.CategoryRole); + var name = categoryModel.model.data(categoryModel.modelIndex(i), 0); // DisplayRole + + compare(name, expectedNames[i]); + compare(category.name, expectedNames[i]); + } + + + // check that no category has children + for (i = 0; i < categoryModel.count; ++i) { + categoryModel.rootIndex = categoryModel.modelIndex(i); + + compare(categoryModel.count, 0); + + categoryModel.rootIndex = categoryModel.parentModelIndex(); + } + + + // clean up + categoryModel.model.hierarchical = true; + categoryModel.model.plugin = null; + + + // check that the model is empty when an error is encountered + categoryModel.model.update(); + tryCompare(categoryModel, "count", 0); + compare(categoryModel.model.status, CategoryModel.Error); + } + + function test_error() { + var testModel = Qt.createQmlObject('import QtLocation 5.3; CategoryModel {}', testCase, "CategoryModel"); + + var statusChangedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + statusChangedSpy.target = testModel; + statusChangedSpy.signalName = "statusChanged"; + + //try updating without a plugin instance + testModel.update(); + tryCompare(statusChangedSpy, "count", 2); + compare(testModel.status, CategoryModel.Error); + statusChangedSpy.clear(); + //Aside: there is some difficulty in checking the transition to the Loading state + //since the model transitions from Loading to Error before the next event loop + //iteration. + + //try updating with an uninitialized plugin instance. + testModel.plugin = uninitializedPlugin; + testModel.update(); + tryCompare(statusChangedSpy, "count", 2); + compare(testModel.status, CategoryModel.Error); + statusChangedSpy.clear(); + + //try searching with plugin a instance + //that has been provided a non-existent name + testModel.plugin = nonExistantPlugin; + testModel.update(); + tryCompare(statusChangedSpy, "count", 2); + compare(testModel.status, CategoryModel.Error); + } +} diff --git a/tests/auto/declarative_core/tst_contactdetail.qml b/tests/auto/declarative_core/tst_contactdetail.qml new file mode 100644 index 0000000..a91c19f --- /dev/null +++ b/tests/auto/declarative_core/tst_contactdetail.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "ContactDetail" + + ContactDetail { id: emptyContactDetail } + + function test_empty() { + compare(emptyContactDetail.label, ""); + compare(emptyContactDetail.value, ""); + } + + ContactDetail { + id: qmlContactDetail + + label: "Phone" + value: "12345" + } + + function test_qmlConstructedContactDetail() { + compare(qmlContactDetail.label, "Phone"); + compare(qmlContactDetail.value, "12345"); + } + + ContactDetail { + id: testContactDetail + } + + function test_setAndGet_data() { + return [ + { tag: "label", property: "label", signal: "labelChanged", value: "Phone", reset: "" }, + { tag: "value", property: "value", signal: "valueChanged", value: "12345", reset: "" }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testContactDetail, data); + } +} diff --git a/tests/auto/declarative_core/tst_coordinate.qml b/tests/auto/declarative_core/tst_coordinate.qml new file mode 100644 index 0000000..79ff8d0 --- /dev/null +++ b/tests/auto/declarative_core/tst_coordinate.qml @@ -0,0 +1,359 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtPositioning 5.5 + +Item { + id: item + + property variant empty: QtPositioning.coordinate() + property variant base: QtPositioning.coordinate(1.0, 1.0, 5.0) + property variant zero: QtPositioning.coordinate(0, 0) + property variant plusone: QtPositioning.coordinate(0, 1) + property variant minusone: QtPositioning.coordinate(0, -1) + property variant north: QtPositioning.coordinate(3, 0) + + SignalSpy { id: coordSpy; target: item; signalName: "baseChanged" } + + property variant inside: QtPositioning.coordinate(0.5, 0.5) + property variant outside: QtPositioning.coordinate(2, 2) + property variant tl: QtPositioning.coordinate(1, 0) + property variant br: QtPositioning.coordinate(0, 1) + property variant box: QtPositioning.rectangle(tl, br) + + + Address { + id: validTestAddress + street: "53 Brandl St" + city: "Eight Mile Plains" + country: "Australia" + countryCode: "AUS" + } + + Location { + id: testLocation + coordinate: inside + boundingBox: box + address: validTestAddress + } + + Location { + id: invalidLocation + } + + + Item { + id: coordinateItem + property variant coordinate + property int animationDuration: 100 + property var coordinateList: [] + property int coordinateCount: 0 + + CoordinateAnimation { + id: coordinateAnimation + target: coordinateItem + property: "coordinate" + duration: coordinateItem.animationDuration + } + onCoordinateChanged: { + if (!coordinateList) { + coordinateList = [] + } + coordinateList[coordinateCount] = QtPositioning.coordinate(coordinate.latitude,coordinate.longitude) + coordinateCount++ + } + + SignalSpy { id: coordinateAnimationStartSpy; target: coordinateAnimation; signalName: "started" } + SignalSpy { id: coordinateAnimationStopSpy; target: coordinateAnimation; signalName: "stopped" } + SignalSpy { id: coordinateAnimationDirectionSpy; target: coordinateAnimation; signalName: "directionChanged" } + } + + TestCase { + name: "GeoLocation" + + function test_Location_complete() + { + compare (testLocation.coordinate.longitude, inside.longitude) + compare (testLocation.coordinate.latitude, inside.latitude) + + compare (testLocation.boundingBox.contains(inside), true) + compare (testLocation.boundingBox.contains(outside), false) + compare (testLocation.boundingBox.bottomRight.longitude, br.longitude) + compare (testLocation.boundingBox.bottomRight.latitude, br.latitude) + compare (testLocation.boundingBox.topLeft.longitude, tl.longitude) + compare (testLocation.boundingBox.topLeft.latitude, tl.latitude) + + compare (testLocation.address.country, "Australia") + compare (testLocation.address.countryCode, "AUS") + compare (testLocation.address.city, "Eight Mile Plains") + compare (testLocation.address.street, "53 Brandl St") + } + + function test_Location_invalid() + { + compare(invalidLocation.coordinate.isValid, false) + compare(invalidLocation.boundingBox.isEmpty, true) + compare(invalidLocation.boundingBox.isValid, false) + compare(invalidLocation.address.city, "") + } + } + + TestCase { + name: "Coordinate" + + function test_validity() + { + compare(empty.isValid, false) + + empty.longitude = 0.0; + empty.latitude = 0.0; + + compare(empty.isValid, true) + } + + function test_accessors() + { + compare(base.longitude, 1.0) + compare(base.latitude, 1.0) + compare(base.altitude, 5.0) + + coordSpy.clear(); + + base.longitude = 2.0; + base.latitude = 3.0; + base.altitude = 6.0; + + compare(base.longitude, 2.0) + compare(base.latitude, 3.0) + compare(base.altitude, 6.0) + compare(coordSpy.count, 3) + } + + function test_comparison_data() + { + return [ + { tag: "empty", coord1: empty, coord2: QtPositioning.coordinate(), result: true }, + { tag: "zero", coord1: zero, coord2: QtPositioning.coordinate(0, 0), result: true }, + { tag: "plusone", coord1: plusone, coord2: QtPositioning.coordinate(0, 1), result: true }, + { tag: "minusone", coord1: minusone, coord2: QtPositioning.coordinate(0, -1), result: true }, + { tag: "north", coord1: north, coord2: QtPositioning.coordinate(3, 0), result: true }, + { tag: "lat,long.alt", coord1: QtPositioning.coordinate(1.1, 2.2, 3.3), coord2: QtPositioning.coordinate(1.1, 2.2, 3.3), result: true }, + { tag: "not equal1", coord1: plusone, coord2: minusone, result: false }, + { tag: "not equal2", coord1: plusone, coord2: north, result: false } + ] + } + + function test_comparison(data) + { + compare(data.coord1 === data.coord2, data.result) + compare(data.coord1 !== data.coord2, !data.result) + compare(data.coord1 == data.coord2, data.result) + compare(data.coord1 != data.coord2, !data.result) + } + + function test_distance() + { + compare(zero.distanceTo(plusone), zero.distanceTo(minusone)) + compare(2*plusone.distanceTo(zero), plusone.distanceTo(minusone)) + compare(zero.distanceTo(plusone) > 0, true) + } + + function test_azimuth() + { + compare(zero.azimuthTo(north), 0) + compare(zero.azimuthTo(plusone), 90) + compare(zero.azimuthTo(minusone), 270) + compare(minusone.azimuthTo(plusone), 360 - plusone.azimuthTo(minusone)) + } + + function test_atDistanceAndAzimuth() + { + // 112km is approximately one degree of arc + + var coord_0d = zero.atDistanceAndAzimuth(112000, 0) + compare(coord_0d.latitude > 0.95, true) + compare(coord_0d.latitude < 1.05, true) + compare(coord_0d.longitude < 0.05, true) + compare(coord_0d.longitude > -0.05, true) + compare(zero.distanceTo(coord_0d), 112000) + compare(zero.azimuthTo(coord_0d), 0) + + var coord_90d = zero.atDistanceAndAzimuth(112000, 90) + compare(coord_90d.longitude > 0.95, true) + compare(coord_90d.longitude < 1.05, true) + compare(coord_90d.latitude < 0.05, true) + compare(coord_90d.latitude > -0.05, true) + compare(zero.distanceTo(coord_90d), 112000) + compare(zero.azimuthTo(coord_90d), 90) + + var coord_30d = zero.atDistanceAndAzimuth(20000, 30) + compare(coord_30d.longitude > 0, true) + compare(coord_30d.latitude > 0, true) + compare(zero.distanceTo(coord_30d), 20000) + compare(zero.azimuthTo(coord_30d), 30) + + var coord_30d2 = coord_30d.atDistanceAndAzimuth(200, 30) + compare(zero.distanceTo(coord_30d2), 20200) + } + } + + TestCase { + name: "CoordinateAnimation" + + function init() + { + coordinateAnimation.stop() + coordinateAnimationStartSpy.clear() + coordinateAnimationStopSpy.clear() + coordinateAnimationDirectionSpy.clear() + coordinateAnimation.from = QtPositioning.coordinate(50,50) + coordinateAnimation.to = QtPositioning.coordinate(50,50) + coordinateAnimation.direction = CoordinateAnimation.Shortest + coordinateItem.coordinate = QtPositioning.coordinate(50,50) + coordinateItem.coordinateList = [] + coordinateItem.coordinateCount = 0 + } + + function initTestCase() + { + compare(coordinateAnimation.direction, CoordinateAnimation.Shortest) + compare(coordinateAnimationDirectionSpy.count,0) + coordinateAnimation.direction = CoordinateAnimation.Shortest + compare(coordinateAnimationDirectionSpy.count,0) + coordinateAnimation.direction = CoordinateAnimation.West + compare(coordinateAnimationDirectionSpy.count,1) + coordinateAnimation.direction = CoordinateAnimation.East + compare(coordinateAnimationDirectionSpy.count,2) + } + + function toMercator(coord) + { + var pi = Math.PI + var lon = coord.longitude / 360.0 + 0.5; + + var lat = coord.latitude; + lat = 0.5 - (Math.log(Math.tan((pi / 4.0) + (pi / 2.0) * lat / 180.0)) / pi) / 2.0; + lat = Math.max(0.0, lat); + lat = Math.min(1.0, lat); + + return {'latitude': lat, 'longitude': lon}; + } + + function coordinate_animation(from, to, movingEast) + { + var fromMerc = toMercator(from) + var toMerc = toMercator(to) + var delta = (toMerc.latitude - fromMerc.latitude) / (toMerc.longitude - fromMerc.longitude) + + compare(coordinateItem.coordinateList.length, 0); + coordinateAnimation.from = from + coordinateAnimation.to = to + coordinateAnimation.start() + tryCompare(coordinateAnimationStartSpy,"count",1) + tryCompare(coordinateAnimationStopSpy,"count",1) + + //check correct start position + compare(coordinateItem.coordinateList[0], from) + //check correct end position + compare(coordinateItem.coordinateList[coordinateItem.coordinateList.length - 1],to) + + var i + var lastLongitude + for (i in coordinateItem.coordinateList) { + var coordinate = coordinateItem.coordinateList[i] + var mercCoordinate = toMercator(coordinate) + + //check that coordinates from the animation is along a straight line between from and to + var estimatedLatitude = fromMerc.latitude + (mercCoordinate.longitude - fromMerc.longitude) * delta + verify(mercCoordinate.latitude - estimatedLatitude < 0.00000000001); + + //check that each step has moved in the right direction + + if (lastLongitude) { + if (movingEast) { + if (coordinate.longitude > 0 && lastLongitude < 0) + verify(coordinate.longitude < lastLongitude + 360) + else + verify(coordinate.longitude < lastLongitude) + } else { + if (coordinate.longitude < 0 && lastLongitude > 0) + verify(coordinate.longitude + 360 > lastLongitude) + else + verify(coordinate.longitude > lastLongitude) + } + } + lastLongitude = coordinate.longitude + } + } + + function test_default_coordinate_animation() + { + //shortest + coordinate_animation(QtPositioning.coordinate(58.0,12.0), + QtPositioning.coordinate(62.0,24.0), + false) + } + + function test_east_direction_coordinate_animation(data) + { + coordinateAnimation.direction = CoordinateAnimation.East + coordinate_animation(data.from, + data.to, + true) + } + + function test_east_direction_coordinate_animation_data() + { + return [ + { from: QtPositioning.coordinate(58.0,24.0), to: QtPositioning.coordinate(58.0,12.0) }, + { from: QtPositioning.coordinate(58.0,12.0), to: QtPositioning.coordinate(58.0,24.0) }, + ] + } + + + function test_west_direction_coordinate_animation(data) + { + coordinateAnimation.direction = CoordinateAnimation.West + coordinate_animation(data.from, + data.to, + false) + } + + function test_west_direction_coordinate_animation_data() + { + return [ + { from: QtPositioning.coordinate(58.0,24.0),to: QtPositioning.coordinate(58.0,12.0) }, + { from: QtPositioning.coordinate(58.0,12.0),to: QtPositioning.coordinate(58.0,24.0) }, + ] + } + + + } +} diff --git a/tests/auto/declarative_core/tst_editorialmodel.qml b/tests/auto/declarative_core/tst_editorialmodel.qml new file mode 100644 index 0000000..4cb38e5 --- /dev/null +++ b/tests/auto/declarative_core/tst_editorialmodel.qml @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "EditorialModel" + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + PluginParameter { + name: "initializePlaceData" + value: true + } + ] + } + + EditorialModel { + id: testModel + } + + Place { + id: testPlace + name: "Test Place" + } + + Place { + id: parkViewHotel + placeId: "4dcc74ce-fdeb-443e-827c-367438017cf1" + plugin: testPlugin + } + + Place { + id: seaViewHotel + placeId: "8f72057a-54b2-4e95-a7bb-97b4d2b5721e" + plugin: testPlugin + } + + function test_setAndGet_data() { + return [ + { tag: "place", property: "place", signal: "placeChanged", value: testPlace }, + { tag: "batchSize", property: "batchSize", signal: "batchSizeChanged", value: 10, reset: 1 }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testModel, data); + } + + function test_consecutive_fetch_data() { + return [ + { tag: "batchSize 1", batchSize: 1 }, + { tag: "batchSize 2", batchSize: 2 }, + { tag: "batchSize 5", batchSize: 5 }, + { tag: "batchSize 10", batchSize: 10 }, + ]; + } + + function test_consecutive_fetch(data) { + var expectedEditorials = [ + { + "title": "Editorial 1", + "text": "Editorial 1 Text", + "language": "en" + }, + { + "title": "Editorial 2", + "text": "Editorial 2 Text", + "language": "en" + }, + { + "title": "Editorial 3", + "text": "Editorial 3 Text", + "language": "en" + }, + { + "title": "", + "text": "", + "language": "", + }, + { + "title": "Editorial 5", + "text": "Editorial 5 Text", + "language": "en" + } + ] + + var model = createModel(); + Utils.testConsecutiveFetch(testCase, model, parkViewHotel, expectedEditorials, data); + model.destroy(); + } + + function test_reset() { + var model = createModel(); + Utils.testReset(testCase, model, parkViewHotel); + model.destroy(); + } + + function test_fetch_data() { + return [ + { + tag: "fetch all editorials in a single batch", + model: createModel(), + batchSize: 10, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 5 + }, + { + tag: "fetch from a place with no editorials", + model: createModel(), + batchSize: 1, + place: seaViewHotel, + expectedTotalCount: 0, + expectedCount: 0 + }, + { + tag: "fetch with batch size one less than the total", + model: createModel(), + batchSize: 4, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 4 + }, + { + tag: "fetch with batch size equal to the total", + model: createModel(), + batchSize: 5, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 5 + }, + { + tag: "fetch with batch size larger than the total", + model: createModel(), + batchSize: 6, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 5 + } + ] + } + + function test_fetch(data) { + Utils.testFetch(testCase, data); + data.model.destroy(); + } + + function createModel() { + return Qt.createQmlObject('import QtLocation 5.3; EditorialModel {}', + testCase, "editorialModel"); + } +} diff --git a/tests/auto/declarative_core/tst_geocoding.qml b/tests/auto/declarative_core/tst_geocoding.qml new file mode 100644 index 0000000..1eadf87 --- /dev/null +++ b/tests/auto/declarative_core/tst_geocoding.qml @@ -0,0 +1,641 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import QtPositioning 5.2 + +Item { + Plugin { id: testPlugin1; name: "qmlgeo.test.plugin"; allowExperimental: true} + Plugin { id: errorPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true + parameters: [ + PluginParameter { name: "error"; value: "1"}, + PluginParameter { name: "errorString"; value: "This error was expected. No worries !"} + ] + } + + + property variant coordinate1: QtPositioning.coordinate(51, 41) + property variant coordinate2: QtPositioning.coordinate(52, 42) + property variant coordinate3: QtPositioning.coordinate(53, 43) + property variant emptyCoordinate: QtPositioning.coordinate() + + property variant boundingBox1: QtPositioning.rectangle(coordinate1, coordinate2) + property variant boundingBox2: QtPositioning.rectangle(coordinate1, coordinate3) + property variant boundingCircle1: QtPositioning.circle(coordinate1, 100) + property variant boundingCircle2: QtPositioning.circle(coordinate2, 100) + + property variant emptyBox: QtPositioning.rectangle() + + GeocodeModel {id: emptyModel} + + Address {id: emptyAddress} + SignalSpy {id: querySpy; target: emptyModel; signalName: "queryChanged"} + SignalSpy {id: autoUpdateSpy; target: emptyModel; signalName: "autoUpdateChanged"} + SignalSpy {id: pluginSpy; target: emptyModel ; signalName: "pluginChanged"} + SignalSpy {id: boundsSpy; target: emptyModel; signalName: "boundsChanged"} + SignalSpy {id: limitSpy; target: emptyModel; signalName: "limitChanged"} + SignalSpy {id: offsetSpy; target: emptyModel; signalName: "offsetChanged"} + + TestCase { + id: testCase1 + name: "GeocodeModel" + function test_model_defaults_and_setters() { + // Query: address + compare (querySpy.count, 0) + emptyModel.query = address1 + compare (querySpy.count, 1) + compare (emptyModel.query.street, address1.street) + emptyModel.query = address1 + compare (querySpy.count, 1) + compare (emptyModel.query.street, address1.street) + // Query: coordinate + emptyModel.query = coordinate1 + compare (querySpy.count, 2) + compare (emptyModel.query.latitude, coordinate1.latitude) + emptyModel.query = coordinate1 + compare (querySpy.count, 2) + compare (emptyModel.query.latitude, coordinate1.latitude) + // Query: string + emptyModel.query = "Kuortane, Finland" + compare (querySpy.count, 3) + compare (emptyModel.query, "Kuortane, Finland") + emptyModel.query = "Kuortane, Finland" + compare (querySpy.count, 3) + compare (emptyModel.query, "Kuortane, Finland") + + // limit and offset + compare (limitSpy.count, 0) + compare (offsetSpy.count, 0) + compare(emptyModel.limit, -1) + compare(emptyModel.offset, 0) + emptyModel.limit = 2 + compare (limitSpy.count, 1) + emptyModel.limit = 2 + compare (limitSpy.count, 1) + emptyModel.offset = 10 + compare (offsetSpy.count, 1) + emptyModel.offset = 10 + compare (offsetSpy.count, 1) + + // bounding box + compare(boundsSpy.count, 0) + emptyModel.bounds = boundingBox1 + compare(boundsSpy.count, 1) + compare(emptyModel.bounds.topLeft.latitude, boundingBox1.topLeft.latitude) + compare(emptyModel.bounds.bottomRight.longitude, boundingBox1.bottomRight.longitude) + emptyModel.bounds = boundingBox1 + compare(boundsSpy.count, 1) + compare(emptyModel.bounds.topLeft.latitude, boundingBox1.topLeft.latitude) + compare(emptyModel.bounds.bottomRight.longitude, boundingBox1.bottomRight.longitude) + emptyModel.bounds = boundingBox2 + compare(boundsSpy.count, 2) + compare(emptyModel.bounds.topLeft.latitude, boundingBox2.topLeft.latitude) + compare(emptyModel.bounds.bottomRight.longitude, boundingBox2.bottomRight.longitude) + emptyModel.bounds = QtPositioning.rectangle(); + compare(boundsSpy.count, 3) + + + // bounding circle + boundsSpy.clear() + emptyModel.bounds = boundingCircle1 + compare(boundsSpy.count, 1) + compare(emptyModel.bounds.center.latitude, coordinate1.latitude) + emptyModel.bounds = boundingCircle1 + compare(boundsSpy.count, 1) + compare(emptyModel.bounds.center.latitude, coordinate1.latitude) + emptyModel.bounds = boundingCircle2 + compare(boundsSpy.count, 2) + compare(emptyModel.bounds.center.latitude, coordinate2.latitude) + var dynamicCircle = QtPositioning.circle(QtPositioning.coordinate(8, 9)); + emptyModel.bounds = dynamicCircle + compare(boundsSpy.count, 3) + compare(emptyModel.bounds.center.latitude, dynamicCircle.center.latitude) + + // status + compare (emptyModel.status, GeocodeModel.Null) + + // error + compare (emptyModel.errorString, "") + compare (emptyModel.error, GeocodeModel.NoError) + + // count + compare( emptyModel.count, 0) + + // auto update + compare (autoUpdateSpy.count, 0) + compare (emptyModel.autoUpdate, false) + emptyModel.autoUpdate = true + compare (emptyModel.autoUpdate, true) + compare (autoUpdateSpy.count, 1) + emptyModel.autoUpdate = true + compare (emptyModel.autoUpdate, true) + compare (autoUpdateSpy.count, 1) + + // mustn't crash even we don't have plugin + emptyModel.update() + + // Plugin + compare(pluginSpy.count, 0) + emptyModel.plugin = testPlugin1 + compare(pluginSpy.count, 1) + compare(emptyModel.plugin, testPlugin1) + emptyModel.plugin = testPlugin1 + compare(pluginSpy.count, 1) + emptyModel.plugin = errorPlugin + compare(pluginSpy.count, 2) + } + // Test that model acts gracefully when plugin is not set or is invalid + // (does not support geocoding) + GeocodeModel {id: errorModel; plugin: errorPlugin} + GeocodeModel {id: errorModelNoPlugin} + SignalSpy {id: countInvalidSpy; target: errorModel; signalName: "countChanged"} + SignalSpy {id: errorSpy; target: errorModel; signalName: "errorChanged"} + function test_error_plugin() { + // test plugin not set + compare(errorModelNoPlugin.error,GeocodeModel.NoError) + errorModelNoPlugin.update() + compare(errorModelNoPlugin.error,GeocodeModel.EngineNotSetError) + console.log(errorModelNoPlugin.errorString) + + //plugin set but otherwise not offering anything + compare(errorModel.error,GeocodeModel.EngineNotSetError) + compare(errorModel.errorString,"This error was expected. No worries !") + errorSpy.clear() + errorModel.update() + compare(errorModel.error,GeocodeModel.EngineNotSetError) + compare(errorModel.errorString,qsTr("Cannot geocode, geocode manager not set.")) + compare(errorSpy.count, 1) + errorSpy.clear() + errorModel.cancel() + compare(errorModel.error,GeocodeModel.NoError) + compare(errorModel.errorString,"") + compare(errorSpy.count, 1) + errorSpy.clear() + errorModel.reset() + compare(errorModel.error,GeocodeModel.NoError) + compare(errorModel.errorString,"") + compare(errorSpy.count, 0) + errorSpy.clear() + errorModel.update() + compare(errorModel.error,GeocodeModel.EngineNotSetError) + compare(errorModel.errorString,qsTr("Cannot geocode, geocode manager not set.")) + compare(errorSpy.count, 1) + errorSpy.clear() + var location = errorModel.get(-1) + compare(location, null) + } + + } + Address {id: address1; street: "wellknown street"; city: "expected city"; county: "2"} + Address {id: errorAddress1; street: "error"; county: "2"} // street is the error reason + + property variant rcoordinate1: QtPositioning.coordinate(51, 2) + property variant errorCoordinate1: QtPositioning.coordinate(73, 2) // (latiude mod 70) is the error code + property variant slackCoordinate1: QtPositioning.coordinate(60, 3) + Address {id: slackAddress1; street: "Slacker st"; city: "Lazy town"; county: "4"} + + property variant automaticCoordinate1: QtPositioning.coordinate(60, 3) + Address {id: automaticAddress1; street: "Auto st"; city: "Detroit"; county: "4"} + + Plugin { + id: testPlugin2; + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "supported"; value: true}, + PluginParameter { name: "finishRequestImmediately"; value: true}, + PluginParameter { name: "validateWellKnownValues"; value: true} + ] + } + + Plugin { + id: immediatePlugin; + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "supported"; value: true}, + PluginParameter { name: "finishRequestImmediately"; value: true}, + PluginParameter { name: "validateWellKnownValues"; value: false} + ] + } + + Plugin { + id: slackPlugin; + allowExperimental: true + name: "qmlgeo.test.plugin" + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "supported"; value: true}, + PluginParameter { name: "finishRequestImmediately"; value: false}, + PluginParameter { name: "validateWellKnownValues"; value: false} + ] + } + + Plugin { + id: autoPlugin; + allowExperimental: true + name: "qmlgeo.test.plugin" + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "supported"; value: true}, + PluginParameter { name: "finishRequestImmediately"; value: false}, + PluginParameter { name: "validateWellKnownValues"; value: false} + ] + } + + GeocodeModel {id: testModel; plugin: testPlugin2} + SignalSpy {id: locationsSpy; target: testModel; signalName: "locationsChanged"} + SignalSpy {id: countSpy; target: testModel; signalName: "countChanged"} + SignalSpy {id: testQuerySpy; target: testModel; signalName: "queryChanged"} + SignalSpy {id: testStatusSpy; target: testModel; signalName: "statusChanged"} + + GeocodeModel {id: slackModel; plugin: slackPlugin; } + SignalSpy {id: locationsSlackSpy; target: slackModel; signalName: "locationsChanged"} + SignalSpy {id: countSlackSpy; target: slackModel; signalName: "countChanged"} + SignalSpy {id: querySlackSpy; target: slackModel; signalName: "queryChanged"} + SignalSpy {id: errorStringSlackSpy; target: slackModel; signalName: "errorChanged"} + SignalSpy {id: errorSlackSpy; target: slackModel; signalName: "errorChanged"} + SignalSpy {id: pluginSlackSpy; target: slackModel; signalName: "pluginChanged"} + + GeocodeModel {id: immediateModel; plugin: immediatePlugin} + SignalSpy {id: locationsImmediateSpy; target: immediateModel; signalName: "locationsChanged"} + SignalSpy {id: countImmediateSpy; target: immediateModel; signalName: "countChanged"} + SignalSpy {id: queryImmediateSpy; target: immediateModel; signalName: "queryChanged"} + SignalSpy {id: statusImmediateSpy; target: immediateModel; signalName: "statusChanged"} + SignalSpy {id: errorStringImmediateSpy; target: immediateModel; signalName: "errorChanged"} + SignalSpy {id: errorImmediateSpy; target: immediateModel; signalName: "errorChanged"} + + GeocodeModel {id: automaticModel; plugin: autoPlugin; query: automaticAddress1; autoUpdate: true} + SignalSpy {id: automaticLocationsSpy; target: automaticModel; signalName: "locationsChanged"} + + TestCase { + name: "GeocodeModelGeocoding" + function clear_slack_model() { + slackModel.reset() + locationsSlackSpy.clear() + countSlackSpy.clear() + querySlackSpy.clear() + errorStringSlackSpy.clear() + errorSlackSpy.clear() + slackModel.limit = -1 + slackModel.offset = 0 + } + function clear_immediate_model() { + immediateModel.reset() + locationsImmediateSpy.clear() + countImmediateSpy.clear() + queryImmediateSpy.clear() + errorStringImmediateSpy.clear() + errorImmediateSpy.clear() + statusImmediateSpy.clear() + immediateModel.limit = -1 + immediateModel.offset = 0 + } + function test_reset() { + clear_immediate_model(); + immediateModel.query = errorAddress1 + immediateModel.update() + compare (immediateModel.errorString, errorAddress1.street) + compare (immediateModel.error, GeocodeModel.CommunicationError) + compare (immediateModel.count, 0) + compare (statusImmediateSpy.count, 2) + compare (immediateModel.status, GeocodeModel.Error) + immediateModel.reset() + compare (immediateModel.errorString, "") + compare (immediateModel.error, GeocodeModel.NoError) + compare (immediateModel.status, GeocodeModel.Null) + // Check that ongoing req is aborted + clear_slack_model() + slackModel.query = slackAddress1 + slackAddress1.county = "5" + slackModel.update() + tryCompare(countSlackSpy, "count", 0) + compare (locationsSlackSpy.count, 0) + compare (slackModel.count, 0) + slackModel.reset() + tryCompare(countSlackSpy, "count", 0) + compare (locationsSlackSpy.count, 0) + compare (slackModel.count, 0) + // Check that results are cleared + slackModel.update() + tryCompare(slackModel, "count", 5) + slackModel.reset() + compare (slackModel.count, 0) + // Check that changing plugin resets any ongoing requests + clear_slack_model() + slackModel.query = slackAddress1 + slackAddress1.county = "7" + compare (pluginSlackSpy.count, 0) + slackModel.update() + tryCompare(countSlackSpy, "count", 0) + slackModel.plugin = errorPlugin + tryCompare(countSlackSpy, "count", 0) + compare (pluginSlackSpy.count, 1) + // switch back and check that works + slackModel.plugin = slackPlugin + compare (pluginSlackSpy.count, 2) + slackModel.update() + tryCompare(countSlackSpy, "count", 0) + tryCompare(countSlackSpy, "count", 1) + } + function test_error_geocode() { + // basic immediate geocode error + clear_immediate_model() + immediateModel.query = errorAddress1 + immediateModel.update() + compare (errorStringImmediateSpy.count, 1) + compare (immediateModel.errorString, errorAddress1.street) + compare (immediateModel.error, GeocodeModel.CommunicationError) // county of the address (2) + compare (immediateModel.count, 0) + compare (statusImmediateSpy.count, 2) + compare (immediateModel.status, GeocodeModel.Error) + // basic delayed geocode error + clear_slack_model() + slackModel.query = errorAddress1 + errorAddress1.street = "error code 2" + slackModel.update() + compare (errorStringSlackSpy.count, 0) + compare (errorSlackSpy.count, 0) + tryCompare (errorStringSlackSpy, "count", 1) + tryCompare (errorSlackSpy, "count", 1) + compare (slackModel.errorString, errorAddress1.street) + compare (slackModel.error, GeocodeModel.CommunicationError) + compare (slackModel.count, 0) + // Check that we recover + slackModel.query = address1 + slackModel.update() + tryCompare(countSlackSpy, "count", 1) + compare (slackModel.count, 2) + compare (errorStringSlackSpy.count, 2) + compare (errorSlackSpy.count, 2) + compare (slackModel.errorString, "") + compare (slackModel.error, GeocodeModel.NoError) + } + + function test_error_reverse_geocode() { + // basic immediate geocode error + clear_immediate_model() + immediateModel.query = errorCoordinate1 + immediateModel.update() + if (immediateModel.errorString != "") + compare (errorStringImmediateSpy.count, 1) // the previous error is cleared upon update() + else + compare (errorImmediateSpy.count, 1) + compare (immediateModel.errorString, "error") + compare (immediateModel.error, GeocodeModel.ParseError) + compare (immediateModel.count, 0) + compare (statusImmediateSpy.count, 2) + compare (immediateModel.status, GeocodeModel.Error) + // basic delayed geocode error + clear_slack_model() + slackModel.query = errorCoordinate1 + slackModel.update() + compare (errorStringSlackSpy.count, 0) + compare (errorSlackSpy.count, 0) + if (slackModel.errorString != "") + tryCompare (errorStringSlackSpy, "count", 2) + else + tryCompare (errorStringSlackSpy, "count", 1) + compare (slackModel.errorString, "error") + compare (slackModel.error, GeocodeModel.ParseError) + compare (slackModel.count, 0) + // Check that we recover + slackModel.query = rcoordinate1 + slackModel.update() + tryCompare(countSlackSpy, "count", 1) + compare (slackModel.count, 2) + compare (errorStringSlackSpy.count, 2) + compare (errorSlackSpy.count, 2) + compare (slackModel.errorString, "") + compare (slackModel.error, GeocodeModel.NoError) + } + function test_address_geocode() { + testQuerySpy.clear() + locationsSpy.clear() + testStatusSpy.clear() + testModel.reset() + countSpy.clear() + compare (locationsSpy.count, 0) + compare (testModel.errorString, "") + compare (testModel.error, GeocodeModel.NoError) + compare (testModel.count, 0) + testModel.query = address1 + compare (testQuerySpy.count, 1) + testModel.update() + tryCompare (locationsSpy, "count", 1) // 5 sec + compare (testModel.errorString, "") + compare (testModel.error, GeocodeModel.NoError) + compare (testModel.count, 2) + compare (testQuerySpy.count, 1) + compare (testStatusSpy.count, 2) + compare (testModel.status, GeocodeModel.Ready) + compare (testModel.get(0).address.street, "wellknown street") + compare (testModel.get(0).address.city, "expected city") + } + + function test_freetext_geocode() { + testQuerySpy.clear() + locationsSpy.clear() + testStatusSpy.clear() + testModel.reset() + countSpy.clear() + compare (locationsSpy.count, 0) + compare (testModel.errorString, "") + compare (testModel.error, GeocodeModel.NoError) + compare (testModel.count, 0) + testModel.limit = 5 // number of places echoed back + testModel.offset = 10 // 'county' set in the places + // Test successful case + testModel.query = "Freetext geocode" + compare(testQuerySpy.count, 1) + testModel.update(); + tryCompare (locationsSpy, "count", 1) // 5 sec + tryCompare(countSpy, "count", 1) + tryCompare(testModel, "count", 5) + compare(testModel.get(0).address.county, "10") + // Test error case + testModel.query = "2" // tells plugin to echo error '2' + compare(testQuerySpy.count, 2) + testModel.update(); + tryCompare (locationsSpy, "count", 2) // 5 sec + tryCompare(countSpy, "count", 2) + tryCompare(testModel, "count", 0) + compare(testModel.errorString, "2") + compare (testModel.error, GeocodeModel.CommunicationError) + testModel.reset() + tryCompare(countSpy, "count", 2) + compare (testModel.count, 0) + } + + function test_delayed_freetext_geocode() { + clear_slack_model() + slackModel.limit = 5 // number of places echoed back + slackModel.offset = 10 // 'county' set in the places + // Basic successful case + slackModel.query = "freetext geocode" + compare (querySlackSpy.count, 1) + slackModel.update() + tryCompare(countSlackSpy, "count", 0) + compare (locationsSlackSpy.count, 0) + compare (slackModel.count, 0) + tryCompare(countSlackSpy, "count", 1); //waits up to 5s + compare (slackModel.count, 5) + compare (locationsSlackSpy.count, 1) + // Frequent updates, previous requests are aborted + slackModel.reset() + locationsSlackSpy.clear() + countSlackSpy.clear() + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + tryCompare(countSlackSpy, "count", 1); //waits up to 5s + compare (locationsSlackSpy.count, 1) + compare(slackModel.count, 5) // limit + } + + function test_geocode_auto_updates() { + compare (automaticModel.count, 4) // should be something already + compare (automaticLocationsSpy.count, 1) + // change query and its contents and verify that autoupdate occurs + automaticAddress1.county = 6 + tryCompare(automaticLocationsSpy, "count", 2) + compare (automaticModel.count, 6) + automaticAddress1.street = "The Avenue" + tryCompare(automaticLocationsSpy, "count", 3) + compare (automaticModel.count, 6) + automaticModel.query = automaticCoordinate1 + tryCompare(automaticLocationsSpy, "count", 4) + compare (automaticModel.count, 3) + } + + function test_delayed_geocode() { + // basic delayed response + slackModel.reset() + querySlackSpy.clear() + countSlackSpy.clear() + locationsSlackSpy.clear() + slackModel.query = slackAddress1 + slackAddress1.county = "7" + compare (querySlackSpy.count, 1) + slackModel.update() + tryCompare(countSlackSpy, "count", 0) + compare (locationsSlackSpy.count, 0) + compare (slackModel.count, 0) + tryCompare(countSlackSpy, "count", 1); //waits up to 5s + compare (locationsSlackSpy.count, 1) + compare (slackModel.count, 7) // slackAddress1.county) + // Frequent updates, previous requests are aborted + slackModel.reset() + locationsSlackSpy.clear() + countSlackSpy.clear() + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + tryCompare(countSlackSpy, "count", 1); //waits up to 5s + compare (locationsSlackSpy.count, 1) + compare(slackModel.count, 7) // slackAddress1.county + } + function test_reverse_geocode() { + testModel.reset() + testQuerySpy.clear() + locationsSpy.clear() + testStatusSpy.clear() + countSpy.clear() + compare (testModel.errorString, "") + compare (testModel.error, GeocodeModel.NoError) + compare (testModel.count, 0) + compare (testQuerySpy.count, 0) + testModel.query = rcoordinate1 + compare (testQuerySpy.count, 1) + testModel.update() + tryCompare (locationsSpy, "count", 1) // 5 sec + tryCompare(countSpy, "count", 1) + compare (testModel.errorString, "") + compare (testModel.error, GeocodeModel.NoError) + compare (testModel.count, 2) + testModel.reset() + tryCompare(countSpy, "count", 2) + compare (testModel.count, 0) + } + function test_delayed_reverse_geocode() { + clear_slack_model() + slackModel.query = slackCoordinate1 + compare (querySlackSpy.count, 1) + slackModel.update() + tryCompare(countSlackSpy, "count", 0) + compare (locationsSlackSpy.count, 0) + compare (slackModel.count, 0) + + tryCompare(countSlackSpy, "count", 1); //waits up to 5s + compare (locationsSlackSpy.count, 1) + compare (slackModel.count, 3) // slackCoordinate1.longitude + // Frequent updates, previous requests are aborted + slackModel.reset() + locationsSlackSpy.clear() + countSlackSpy.clear() + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + slackModel.update() + tryCompare(locationsSlackSpy, "count", 0) + compare(countSlackSpy.count, 0) + + tryCompare(countSlackSpy, "count", 1); //waits up to 5s + compare(locationsSlackSpy.count, 1) + compare(slackModel.count, 3) // slackCoordinate1.longitude + } + } +} diff --git a/tests/auto/declarative_core/tst_imagemodel.qml b/tests/auto/declarative_core/tst_imagemodel.qml new file mode 100644 index 0000000..2fa5093 --- /dev/null +++ b/tests/auto/declarative_core/tst_imagemodel.qml @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "ImageModel" + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + PluginParameter { + name: "initializePlaceData" + value: true + } + ] + } + + ImageModel { + id: testModel + } + + Place { + id: testPlace + name: "Test Place" + } + + Place { + id: parkViewHotel + placeId: "4dcc74ce-fdeb-443e-827c-367438017cf1" + plugin: testPlugin + } + + Place { + id: seaViewHotel + placeId: "8f72057a-54b2-4e95-a7bb-97b4d2b5721e" + plugin: testPlugin + } + + function test_setAndGet_data() { + return [ + { tag: "place", property: "place", signal: "placeChanged", value: testPlace }, + { tag: "batchSize", property: "batchSize", signal: "batchSizeChanged", value: 10, reset: 1 }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testModel, data); + } + + function test_consecutive_fetch_data() { + return [ + { tag: "batchSize 1", batchSize: 1 }, + { tag: "batchSize 2", batchSize: 2 }, + { tag: "batchSize 5", batchSize: 5 }, + { tag: "batchSize 10", batchSize: 10 }, + ]; + } + + function test_consecutive_fetch(data) { + var expectedImages = [ + { + "url": "http://somewhere.com/image1.png", + "imageId": "0001", + "mimeType": "image/png" + }, + { + "url": "http://somewhere.com/image2.png", + "imageId": "0002", + "mimeType": "image/png" + }, + { + "url": "http://somewhere.com/image3.png", + "imageId": "0003", + "mimeType": "image/png" + }, + { + "url": "", + "imageId": "", + "mimeType": "" + }, + { + "url": "http://somewhere.com/image5.png", + "imageId": "0005", + "mimeType": "image/png" + } + ] + + var model = createModel(); + Utils.testConsecutiveFetch(testCase, model, parkViewHotel, expectedImages, data); + model.destroy(); + } + + function test_reset() { + var model = createModel(); + Utils.testReset(testCase, model, parkViewHotel); + model.destroy(); + } + + function test_fetch_data() { + return [ + { + tag: "fetch all images in a single batch", + model: createModel(), + batchSize: 10, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 5 + }, + { + tag: "fetch from a place with no images", + model: createModel(), + batchSize: 1, + place: seaViewHotel, + expectedTotalCount: 0, + expectedCount: 0 + }, + { + tag: "fetch with batch size one less than the total", + model: createModel(), + batchSize: 4, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 4 + }, + { + tag: "fetch with batch size equal to the total", + model: createModel(), + batchSize: 5, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 5 + }, + { + tag: "fetch with batch size larger than the total", + model: createModel(), + batchSize: 6, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 5 + } + ] + } + + function test_fetch(data) { + Utils.testFetch(testCase, data); + data.model.destroy(); + } + + function createModel() { + return Qt.createQmlObject('import QtLocation 5.3; ImageModel {}', + testCase, "imageModel"); + } +} diff --git a/tests/auto/declarative_core/tst_place.qml b/tests/auto/declarative_core/tst_place.qml new file mode 100644 index 0000000..459b8f3 --- /dev/null +++ b/tests/auto/declarative_core/tst_place.qml @@ -0,0 +1,627 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import QtPositioning 5.2 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "Place" + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + } + + Place { + id: favoritePlace + name: "Favorite Place" + } + + Place { id: emptyPlace } + + Place { id: emptyPlace2 } + + Place { id: testPlace } + + Place { + id: savePlace + + name: "Test place" + + visibility: Place.DeviceVisibility + + location: Location { + address: Address { + country: "country" + countryCode: "cc" + state: "state" + county: "county" + city: "city" + district: "district" + street: "123 Fake Street" + postalCode: "1234" + } + + coordinate { + latitude: 10 + longitude: 10 + altitude: 100 + } + + boundingBox { + center: QtPositioning.coordinate(10, 10, 100) + width: 100 + height: 100 + } + } + + ratings: Ratings { + average: 3.5 + count: 10 + } + + supplier: Supplier { + name: "Supplier 1" + supplierId: "supplier-id-1" + url: "http://www.example.com/supplier-id-1/" + icon: Icon{ + plugin: testPlugin + Component.onCompleted: { + parameters.singleUrl = "http://www.example.com/supplier-id-1/icon" + } + } + } + + categories: [ + Category { + name: "Category 1" + categoryId: "category-id-1" + plugin: testPlugin + }, + Category { + name: "Category 2" + categoryId: "category-id-2" + plugin: testPlugin + } + ] + + icon: Icon { + Component.onCompleted: { + savePlace.icon.parameters.singleUrl = "http://example.com/test-place.png"; + } + } + } + + Place { + id: dummyPlace + placeId: "487" + name: "dummyPlace" + visibility: Place.PublicVisibility + } + + // compares two places property by property + function compare_place(place1, place2) { + // check simple properties + var simpleProperties = ["name", "placeId", "primaryPhone", "primaryFax", "primaryEmail", + "primaryUrl", "visibility"]; + for (x in simpleProperties) { + if (place1[simpleProperties[x]] !== place2[simpleProperties[x]]) + return false; + } + + // check categories + if (place1.categories.length !== place2.categories.length) + return false; + for (var i = 0; i < place1.categories.length; ++i) { + // fixme, what if the order of the two lists are not the same + if (place1.categories[i].categoryId !== place2.categories[i].categoryId) + return false; + if (place1.categories[i].name !== place2.categories[i].name) + return false; + } + + // check supplier + if (place1.supplier === null && place2.supplier !== null) + return false; + if (place1.supplier !== null && place2.supplier === null) + return false; + if (place1.supplier !== null && place2.supplier !== null) { + if (place1.supplier.supplierId !== place2.supplier.supplierId) + return false; + if (place1.supplier.name !== place2.supplier.name) + return false; + if (place1.supplier.url !== place2.supplier.url) + return false; + + // check supplier icon + if (place1.supplier.icon === null && place2.supplier.icon !== null) + return false; + if (place1.supplier.icon !== null && place2.supplier.icon === null) + return false; + if (place1.supplier.icon !== null && place2.supplier.icon !== null) { + if (place1.supplier.icon.parameters.keys().length !== place2.supplier.icon.parameters.keys().length) { + return false; + } + + var keys = place1.supplier.icon.parameters.keys() + place2.supplier.icon.parameters.keys(); + for (var i = 0; i < keys.length; ++i) { + if (place1.supplier.icon.parameters[keys[i]] != place2.supplier.icon.parameters[keys[i]]) { + return false; + } + } + + if (place1.supplier.icon.plugin !== place2.supplier.icon.plugin) + return false; + } + } + + // check ratings + if (place1. ratings === null && place2.ratings !== null) + return false; + if (place1.ratings !== null && place2.ratings === null) + return false; + if (place1.ratings !== null && place2.ratings !== null) { + if (place1.ratings.average !== place2.ratings.average) + return false; + if (place1.ratings.count !== place2.ratings.count) + return false; + } + + // check location + if (place1.location === null && place2.location !== null) + return false; + if (place1.location !== null && place2.location === null) + return false; + if (place1.location !== null && place2.location !== null) { + if (place1.location.address.country !== place2.location.address.country) + return false; + if (place1.location.address.countryCode !== place2.location.address.countryCode) + return false; + if (place1.location.address.state !== place2.location.address.state) + return false; + if (place1.location.address.county !== place2.location.address.county) + return false; + if (place1.location.address.city !== place2.location.address.city) + return false; + if (place1.location.address.district !== place2.location.address.district) + return false; + if (place1.location.address.street !== place2.location.address.street) + return false; + if (place1.location.address.postalCode !== place2.location.address.postalCode) + return false; + + if (place1.location.coordinate !== place2.location.coordinate) + return false; + if (place1.location.boundingBox !== place2.location.boundingBox) + return false; + } + + // check icon + if (place1.icon === null && place2.icon !== null) { + return false; + } + if (place1.icon !== null && place2.icon === null) { + return false; + } + if (place1.icon !== null && place2.icon !== null) { + if (place1.icon.plugin !== place2.icon.plugin) { + console.log(place1.icon.plugin + " " + place2.icon.plugin); + return false; + } + + if (place1.icon.parameters.keys().length !== place2.icon.parameters.keys().length) { + return false; + } + + var keys = place1.icon.parameters.keys() + place2.icon.parameters.keys(); + for (var i = 0; i < keys.length; ++i) { + if (place1.icon.parameters[keys[i]] + != place2.icon.parameters[keys[i]]) { + return false; + } + } + } + + // check extended attributes + + return true; + } + + function test_emptyPlace() { + // basic properties + compare(emptyPlace.plugin, null); + compare(emptyPlace.categories.length, 0); + compare(emptyPlace.name, ""); + compare(emptyPlace.placeId, ""); + compare(emptyPlace.detailsFetched, false); + compare(emptyPlace.status, Place.Ready); + compare(emptyPlace.primaryPhone, ""); + compare(emptyPlace.primaryFax, ""); + compare(emptyPlace.primaryEmail, ""); + compare(emptyPlace.primaryWebsite, ""); + compare(emptyPlace.visibility, Place.UnspecifiedVisibility); + compare(emptyPlace.attribution, ""); + + // complex properties + compare(emptyPlace.ratings.average, 0); + compare(emptyPlace.location.address.street, ''); + compare(emptyPlace.location.address.district, ''); + compare(emptyPlace.location.address.city, ''); + compare(emptyPlace.location.address.county, ''); + compare(emptyPlace.location.address.state, ''); + compare(emptyPlace.location.address.country, ''); + + compare(emptyPlace.icon.plugin, null); + + compare(emptyPlace.supplier.name, ''); + compare(emptyPlace.supplier.supplierId, ''); + compare(emptyPlace.supplier.url, ''); + + compare(emptyPlace.supplier.icon.plugin, null); + + compare(emptyPlace.reviewModel.totalCount, -1); + compare(emptyPlace.imageModel.totalCount, -1); + compare(emptyPlace.editorialModel.totalCount, -1); + compare(emptyPlace.categories.length, 0); + + verify(compare_place(emptyPlace, emptyPlace)); + verify(compare_place(emptyPlace, emptyPlace2)); + } + + function test_setAndGet_data() { + return [ + { tag: "name", property: "name", signal: "nameChanged", value: "Test Place", reset: "" }, + { tag: "placeId", property: "placeId", signal: "placeIdChanged", value: "test-place-id-1", reset: "" }, + { tag: "visibility", property: "visibility", signal: "visibilityChanged", value: Place.PublicVisibility, reset: Place.UnspecifiedVisibility }, + { tag: "attribution", property: "attribution", signal: "attributionChanged", value: "Place data from...", reset: "" }, + { tag: "favorite", property: "favorite", signal: "favoriteChanged", value: favoritePlace } + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testPlace, data); + } + + function test_categories() { + var categories = new Array(2); + categories[0] = Qt.createQmlObject('import QtLocation 5.3; Category { categoryId: "cat-id-1"; name: "Category 1" }', testCase, "Category1"); + categories[1] = Qt.createQmlObject('import QtLocation 5.3; Category { categoryId: "cat-id-2"; name: "Category 2" }', testCase, "Category2"); + + var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = testPlace; + signalSpy.signalName = "categoriesChanged"; + + // set categories to something new + testPlace.categories = categories; + compare(testPlace.categories.length, categories.length); + + for (var i = 0; i < categories.length; ++i) { + compare(testPlace.categories[i].categoryId, categories[i].categoryId); + compare(testPlace.categories[i].name, categories[i].name); + } + + compare(signalSpy.count, 2); + + // set categories to the same (signal spy should not increase?) + testPlace.categories = categories; + compare(testPlace.categories.length, categories.length); + + for (var i = 0; i < categories.length; ++i) { + compare(testPlace.categories[i].categoryId, categories[i].categoryId); + compare(testPlace.categories[i].name, categories[i].name); + } + + compare(signalSpy.count, 5); // clear + append + append + + // reset by assignment + testPlace.categories = new Array(0); + compare(testPlace.categories.length, 0); + compare(signalSpy.count, 6); + + signalSpy.destroy(); + } + + function test_supplier() { + var supplier = Qt.createQmlObject('import QtLocation 5.3; Supplier { supplierId: "sup-id-1"; name: "Category 1" }', testCase, "Supplier1"); + + var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = testPlace; + signalSpy.signalName = "supplierChanged"; + + // set supplier to something new + testPlace.supplier = supplier; + compare(testPlace.supplier, supplier); + + compare(testPlace.supplier.supplierId, supplier.supplierId); + compare(testPlace.supplier.name, supplier.name); + + compare(signalSpy.count, 1); + + // set supplier to the same + testPlace.supplier = supplier; + compare(testPlace.supplier, supplier); + + compare(testPlace.supplier.supplierId, supplier.supplierId); + compare(testPlace.supplier.name, supplier.name); + + compare(signalSpy.count, 1); + + // reset by assignment + testPlace.supplier = null; + compare(testPlace.supplier, null); + compare(signalSpy.count, 2); + + signalSpy.destroy(); + } + + function test_location() { + var location = Qt.createQmlObject('import QtPositioning 5.2; Location { coordinate: QtPositioning.coordinate(10.0, 20.0) }', testCase, "Location1"); + + var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = testPlace; + signalSpy.signalName = "locationChanged"; + + testPlace.location = location; + compare(testPlace.location.coordinate.latitude, 10.0); + compare(signalSpy.count, 1); + + testPlace.location = location; + compare(testPlace.location.coordinate.latitude, 10.0); + compare(signalSpy.count, 1); + + testPlace.location = null; + compare(testPlace.location, null); + compare(signalSpy.count, 2); + + location.destroy(); + signalSpy.destroy(); + } + + function test_ratings() { + var ratings = Qt.createQmlObject('import QtLocation 5.3; Ratings { average: 3; count: 100 }', testCase, "Rating1"); + + var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = testPlace; + signalSpy.signalName = "ratingsChanged"; + + testPlace.ratings = ratings; + compare(testPlace.ratings.average, 3); + compare(testPlace.ratings.count, 100); + compare(signalSpy.count, 1); + + testPlace.ratings = ratings; + compare(testPlace.ratings.average, 3); + compare(testPlace.ratings.count, 100); + compare(signalSpy.count, 1); + + testPlace.ratings = null; + compare(testPlace.ratings, null); + compare(signalSpy.count, 2); + + ratings.destroy(); + signalSpy.destroy(); + } + + function test_extendedAttributes() { + verify(testPlace.extendedAttributes); + + testPlace.extendedAttributes["foo"] = Qt.createQmlObject('import QtLocation 5.3; PlaceAttribute { text: "Foo"; label: "Foo label" }', testCase, 'PlaceAttribute'); + + verify(testPlace.extendedAttributes.foo); + compare(testPlace.extendedAttributes.foo.text, "Foo"); + compare(testPlace.extendedAttributes.foo.label, "Foo label"); + + testPlace.extendedAttributes["foo"] = null; + verify(!testPlace.extendedAttributes.foo); + } + + function test_contactDetailsProperty() { + verify(testPlace.contactDetails); + + testPlace.contactDetails["phone"] = Qt.createQmlObject('import QtLocation 5.3; ContactDetail { label: "Test Label"; value: "Detail Value" }', testCase, 'ContactDetail'); + + verify(testPlace.contactDetails.phone); + compare(testPlace.contactDetails.phone[0].label, "Test Label"); + compare(testPlace.contactDetails.phone[0].value, "Detail Value"); + + testPlace.contactDetails["phone"] = null; + verify(!testPlace.contactDetails.phone); + } + + function test_saveload() { + // Save a place + var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = savePlace; + signalSpy.signalName = "statusChanged"; + + savePlace.plugin = testPlugin; + savePlace.icon.plugin = testPlugin; + savePlace.placeId = "invalid-place-id"; + + savePlace.save(); + + compare(savePlace.status, Place.Saving); + + tryCompare(savePlace, "status", Place.Error); + + // try again without an invalid placeId + savePlace.placeId = ""; + savePlace.save(); + + compare(savePlace.status, Place.Saving); + + tryCompare(savePlace, "status", Place.Ready); + + verify(savePlace.placeId !== ""); + + signalSpy.destroy(); + + + // Read a place + var readPlace = Qt.createQmlObject('import QtLocation 5.3; Place { }', testCase, "test_saveload"); + + signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = readPlace; + signalSpy.signalName = "statusChanged"; + + readPlace.plugin = testPlugin; + + readPlace.getDetails(); + + compare(readPlace.status, Place.Fetching); + tryCompare(readPlace, "status", Place.Error); + + readPlace.placeId = "invalid-id"; + + readPlace.getDetails(); + + compare(readPlace.status, Place.Fetching); + tryCompare(readPlace, "status", Place.Error); + + readPlace.placeId = savePlace.placeId; + + // verify that read place is not currently the same as what we saved + verify(!compare_place(readPlace, savePlace)); + + readPlace.getDetails(); + + compare(readPlace.status, Place.Fetching); + tryCompare(readPlace, "status", Place.Ready); + + // verify that read place is the same as what we saved + verify(compare_place(readPlace, savePlace)); + + signalSpy.destroy(); + + + // Remove a place + var removePlace = Qt.createQmlObject('import QtLocation 5.3; Place { }', testCase, "test_saveload"); + + signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = removePlace; + signalSpy.signalName = "statusChanged"; + + removePlace.plugin = testPlugin; + + removePlace.remove(); + + compare(removePlace.status, Place.Removing); + tryCompare(removePlace, "status", Place.Error); + + removePlace.placeId = "invalid-id"; + + removePlace.remove(); + + compare(removePlace.status, Place.Removing); + tryCompare(removePlace, "status", Place.Error); + + removePlace.placeId = savePlace.placeId; + + removePlace.remove(); + + compare(removePlace.status, Place.Removing); + tryCompare(removePlace, "status", Place.Ready); + + removePlace.getDetails(); + + compare(removePlace.status, Place.Fetching); + tryCompare(removePlace, "status", Place.Error); + + signalSpy.destroy(); + } + + function test_copy() { + var place = Qt.createQmlObject('import QtLocation 5.3; Place { }', this); + place.plugin = testPlugin; + place.copyFrom(dummyPlace); + compare(place.placeId, ""); + compare(place.name, "dummyPlace"); + compare(place.visibility, Place.UnspecifiedVisibility); + } + + function test_contactDetails(data) { + var place = Qt.createQmlObject('import QtLocation 5.3; Place {}', this); + + var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = place; + signalSpy.signalName = data.signalName; + + var detail1 = Qt.createQmlObject('import QtLocation 5.3; ContactDetail {}', this); + detail1.label = "Detail1"; + detail1.value = "555-detail1"; + + place.contactDetails[data.contactType] = detail1; + compare(place.contactDetails[data.contactType].length, 1); + compare(place.contactDetails[data.contactType][0].label, "Detail1"); + compare(place.contactDetails[data.contactType][0].value, "555-detail1"); + + compare(place[data.primaryValue], "555-detail1"); + compare(signalSpy.count, 1); + signalSpy.clear(); + + var listView = Qt.createQmlObject('import QtQuick 2.0; ListView { delegate:Text{text:modelData.label + ":" + modelData.value } }', this); + listView.model = place.contactDetails[data.contactType]; + compare(listView.count, 1); + + var detail2 = Qt.createQmlObject('import QtLocation 5.3; ContactDetail {}', this); + detail2.label = "Detail2"; + detail2.value = "555-detail2"; + + var details = new Array(); + details.push(detail2); + details.push(detail1); + + place.contactDetails[data.contactType] = details; + compare(place.contactDetails[data.contactType].length, 2); + compare(place.contactDetails[data.contactType][0].label, "Detail2"); + compare(place.contactDetails[data.contactType][0].value, "555-detail2"); + compare(place.contactDetails[data.contactType][1].label, "Detail1"); + compare(place.contactDetails[data.contactType][1].value, "555-detail1"); + + compare(place[data.primaryValue], "555-detail2"); + compare(signalSpy.count, 1); + signalSpy.clear(); + listView.model = place.contactDetails[data.contactType]; + compare(listView.count, 2); + } + + function test_contactDetails_data() { + return [ + { tag: "phone", contactType: "phone", signalName: "primaryPhoneChanged", primaryValue: "primaryPhone"}, + { tag: "fax", contactType: "fax", signalName: "primaryFaxChanged", primaryValue: "primaryFax"}, + { tag: "email", contactType: "email", signalName: "primaryEmailChanged", primaryValue: "primaryEmail"}, + { tag: "website", contactType: "website", signalName: "primaryWebsiteChanged", primaryValue: "primaryWebsite"} + ]; + } +} diff --git a/tests/auto/declarative_core/tst_placeattribute.qml b/tests/auto/declarative_core/tst_placeattribute.qml new file mode 100644 index 0000000..ae61aed --- /dev/null +++ b/tests/auto/declarative_core/tst_placeattribute.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "PlaceAttribute" + + PlaceAttribute { + id: testAttribute + } + + function test_setAndGet_data() { + return [ + { tag: "label", property: "label", signal: "labelChanged", value: "Test Label", reset: "" }, + { tag: "text", property: "text", signal: "textChanged", value: "Test Text", reset: "" }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testAttribute, data); + } +} diff --git a/tests/auto/declarative_core/tst_placeicon.qml b/tests/auto/declarative_core/tst_placeicon.qml new file mode 100644 index 0000000..c0f099d --- /dev/null +++ b/tests/auto/declarative_core/tst_placeicon.qml @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "Icon" + + Icon { id: emptyIcon } + + function test_empty() { + compare(emptyIcon.plugin, null); + compare(emptyIcon.parameters.keys().length, 0) + } + + + Icon { + id: qmlIconSingleUrl + } + + function test_qmlSingleUrlIcon() { + qmlIconSingleUrl.parameters.singleUrl = "http://example.com/icon.png" + + var u = qmlIconSingleUrl.url(Qt.size(64, 64)); + compare(u, "http://example.com/icon.png"); + + u = qmlIconSingleUrl.url(Qt.size(20, 20)); + compare(u, "http://example.com/icon.png"); + + qmlIconSingleUrl.parameters.singleUrl = "/home/user/icon.png" + u = qmlIconSingleUrl.url(Qt.size(20, 20)); + compare(u, "file:///home/user/icon.png"); + } + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + } + + Icon { + id: qmlIconParams + plugin: testPlugin + } + + function test_qmlIconParams() { + compare(qmlIconParams.plugin, testPlugin); + qmlIconParams.parameters.s = "http://example.com/icon_small.png" + qmlIconParams.parameters.m = "http://example.com/icon_medium.png" + qmlIconParams.parameters.l = "http://example.com/icon_large.png" + + compare(qmlIconParams.url(Qt.size(10, 10)), "http://example.com/icon_small.png"); + compare(qmlIconParams.url(Qt.size(20, 20)), "http://example.com/icon_small.png"); + compare(qmlIconParams.url(Qt.size(24, 24)), "http://example.com/icon_small.png"); + compare(qmlIconParams.url(Qt.size(25, 25)), "http://example.com/icon_medium.png"); + compare(qmlIconParams.url(Qt.size(30, 30)), "http://example.com/icon_medium.png"); + compare(qmlIconParams.url(Qt.size(39, 39)), "http://example.com/icon_medium.png"); + compare(qmlIconParams.url(Qt.size(40, 40)), "http://example.com/icon_large.png"); + compare(qmlIconParams.url(Qt.size(50, 50)), "http://example.com/icon_large.png"); + compare(qmlIconParams.url(Qt.size(60, 60)), "http://example.com/icon_large.png"); + } + + Icon { + id: testIcon + } + + function test_setAndGet_data() { + return [ + { tag: "plugin", property: "plugin", signal: "pluginChanged", value: testPlugin }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testIcon, data); + } +} diff --git a/tests/auto/declarative_core/tst_placesearchmodel.qml b/tests/auto/declarative_core/tst_placesearchmodel.qml new file mode 100644 index 0000000..2d3c599 --- /dev/null +++ b/tests/auto/declarative_core/tst_placesearchmodel.qml @@ -0,0 +1,293 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import QtPositioning 5.2 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "PlaceSearchModel" + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + PluginParameter { + name: "initializePlaceData" + value: true + } + ] + } + + Plugin { + id: favoritePlugin + name: "foo" + } + + Plugin { + id: uninitializedPlugin + } + + Category { + id: testCategory1 + categoryId: "da3606c1-3448-43b3-a4a3-ca24b12dd94a" + name: "Test Category 1" + } + + Category { + id: testCategory2 + categoryId: "bb8ead84-ec2a-48a9-9c8f-d4ffd3134b21" + name: "Test Category 2" + } + + function compareArray(a, b) { + if (a.length !== b.length) + return false; + + for (var i = 0; i < a.length; ++i) { + if (b.indexOf(a[i]) < 0) + return false; + } + + return true; + } + + function test_setAndGet_data() { + var testSearchArea = QtPositioning.circle(QtPositioning.coordinate(10, 20), 5000); + + return [ + { tag: "plugin", property: "plugin", signal: "pluginChanged", value: testPlugin }, + { tag: "searchArea", property: "searchArea", signal: "searchAreaChanged", value: testSearchArea, reset: QtPositioning.shape() }, + { tag: "limit", property: "limit", signal: "limitChanged", value: 10, reset: -1 }, + + { tag: "searchTerm", property: "searchTerm", signal: "searchTermChanged", value: "Test term", reset: "" }, + { tag: "recommendationId", property: "recommendationId", signal: "recommendationIdChanged", value: "Test-place-id", reset: "" }, + { tag: "relevanceHint", property: "relevanceHint", signal: "relevanceHintChanged", value: PlaceSearchModel.DistanceHint, reset: PlaceSearchModel.UnspecifiedHint }, + { tag: "visibilityScope", property: "visibilityScope", signal: "visibilityScopeChanged", value: Place.DeviceVisibility, reset: Place.UnspecifiedVisibility }, + { tag: "favoritesPlugin", property: "favoritesPlugin", signal: "favoritesPluginChanged", value: favoritePlugin }, + { tag: "category", property: "categories", signal: "categoriesChanged", value: testCategory1, expectedValue: [ testCategory1 ], reset: [], array: true }, + { tag: "categories", property: "categories", signal: "categoriesChanged", value: [ testCategory1, testCategory2 ], reset: [], array: true }, + ]; + } + + function test_setAndGet(data) { + var testModel = Qt.createQmlObject('import QtLocation 5.3; PlaceSearchModel {}', testCase, "PlaceSearchModel"); + Utils.testObjectProperties(testCase, testModel, data); + delete testModel; + } + + function test_search_data() { + var park = Qt.createQmlObject('import QtLocation 5.3; Category {name: "Park"; categoryId: "c2e1252c-b997-44fc-8165-e53dd00f66a7"}', testCase, "Category"); + return [ + { + tag: "searchTerm, multiple results", + property: "searchTerm", + value: "view", + reset: "", + places: [ + "4dcc74ce-fdeb-443e-827c-367438017cf1", + "8f72057a-54b2-4e95-a7bb-97b4d2b5721e" + ] + }, + { + tag: "searchTerm, single result", + property: "searchTerm", + value: "park", + reset: "", + places: [ + "4dcc74ce-fdeb-443e-827c-367438017cf1" + ] + }, + { + tag: "categories, single result", + property: "categories", + value: [ park ], + places: [ + "dacb2181-3f67-4e6a-bd4d-635e99ad5b03" + ] + }, + { + tag: "recommendations", + property: "recommendationId", + value: "4dcc74ce-fdeb-443e-827c-367438017cf1", + reset: "", + places: [ + "8f72057a-54b2-4e95-a7bb-97b4d2b5721e", + "dacb2181-3f67-4e6a-bd4d-635e99ad5b03" + ] + }, + { + tag: "no recommendations", + property: "recommendationId", + value: "8f72057a-54b2-4e95-a7bb-97b4d2b5721e", + reset: "", + places: [ ] + } + ]; + } + + function test_search(data) { + var testModel = Qt.createQmlObject('import QtLocation 5.3; PlaceSearchModel {}', testCase, "PlaceSearchModel"); + testModel.plugin = testPlugin; + + var statusChangedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + statusChangedSpy.target = testModel; + statusChangedSpy.signalName = "statusChanged"; + + var countChangedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + countChangedSpy.target = testModel; + countChangedSpy.signalName = "rowCountChanged"; + + compare(testModel.status, PlaceSearchModel.Null); + + testModel[data.property] = data.value; + testModel.update(); + + compare(testModel.status, PlaceSearchModel.Loading); + compare(statusChangedSpy.count, 1); + + tryCompare(testModel, "status", PlaceSearchModel.Ready); + compare(statusChangedSpy.count, 2); + + if (data.places.length > 0) + compare(countChangedSpy.count, 1); + else + compare(countChangedSpy.count, 0); + + for (var i = 0; i < testModel.count; ++i) { + compare(testModel.data(i, "type"), PlaceSearchModel.PlaceResult); + + var place = testModel.data(i, "place"); + + verify(data.places.indexOf(place.placeId) >= 0); + } + + testModel.reset(); + + compare(statusChangedSpy.count, 3); + compare(testModel.status, PlaceSearchModel.Null); + if (data.places.length > 0) + compare(countChangedSpy.count, 2); + else + compare(countChangedSpy.count, 0); + compare(testModel.count, 0); + + countChangedSpy.destroy(); + statusChangedSpy.destroy(); + + if (data.reset === undefined) { + testModel[data.property] = null; + } else { + testModel[data.property] = data.reset; + } + + delete testModel; + delete statusChangedSpy; + delete countChangedSpy; + } + + function test_cancel() { + var testModel = Qt.createQmlObject('import QtLocation 5.3; PlaceSearchModel {}', testCase, "PlaceSearchModel"); + testModel.plugin = testPlugin; + + var statusChangedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + statusChangedSpy.target = testModel; + statusChangedSpy.signalName = "statusChanged"; + + //try cancelling from an initially null state + compare(testModel.status, PlaceSearchModel.Null); + testModel.searchTerm = "view"; + testModel.update(); + tryCompare(testModel, "status", PlaceSearchModel.Loading); + testModel.cancel(); + tryCompare(testModel, "status", PlaceSearchModel.Ready); + compare(statusChangedSpy.count, 2); + + testModel.update(); + tryCompare(testModel, "status", PlaceSearchModel.Loading); + tryCompare(testModel, "status", PlaceSearchModel.Ready); + compare(statusChangedSpy.count, 4); + + var numResults = testModel.count; + verify(numResults > 0); + + //try cancelling from an initially ready state + testModel.update(); + tryCompare(testModel, "status", PlaceSearchModel.Loading); + testModel.cancel(); + tryCompare(testModel, "status", PlaceSearchModel.Ready); + compare(testModel.count, numResults); + compare(statusChangedSpy.count, 6); + + //chack that an encountering an error will cause the model + //to clear its data + testModel.plugin = null; + testModel.update(); + tryCompare(testModel, "count", 0); + compare(testModel.status, PlaceSearchModel.Error); + + delete testModel; + delete statusChangedSpy; + } + + function test_error() { + var testModel = Qt.createQmlObject('import QtLocation 5.3; PlaceSearchModel {}', testCase, "PlaceSearchModel"); + + var statusChangedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + statusChangedSpy.target = testModel; + statusChangedSpy.signalName = "statusChanged"; + + //try searching without a plugin instance + testModel.update(); + tryCompare(statusChangedSpy, "count", 2); + compare(testModel.status, PlaceSearchModel.Error); + statusChangedSpy.clear(); + //Aside: there is some difficulty in checking the transition to the Loading state + //since the model transitions from Loading to Error before the next event loop + //iteration. + + //try searching with an uninitialized plugin instance. + testModel.plugin = uninitializedPlugin; + testModel.update(); + tryCompare(statusChangedSpy, "count", 2); + compare(testModel.status, PlaceSearchModel.Error); + statusChangedSpy.clear(); + + //try searching with plugin a instance + //that has been provided a non-existent name + testModel.plugin = favoritePlugin; + testModel.update(); + tryCompare(statusChangedSpy, "count", 2); + compare(testModel.status, PlaceSearchModel.Error); + } +} diff --git a/tests/auto/declarative_core/tst_placesearchsuggestionmodel.qml b/tests/auto/declarative_core/tst_placesearchsuggestionmodel.qml new file mode 100644 index 0000000..1334756 --- /dev/null +++ b/tests/auto/declarative_core/tst_placesearchsuggestionmodel.qml @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import QtPositioning 5.2 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "PlaceSearchSuggestionModel" + + PlaceSearchSuggestionModel { + id: testModel + } + + PlaceSearchSuggestionModel { + id: testModelError + } + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + } + + Plugin { + id: nonExistantPlugin + name: "nonExistantName" + } + + Plugin { + id: uninitializedPlugin + } + + function test_setAndGet_data() { + var testSearchArea = QtPositioning.circle(QtPositioning.coordinate(10, 20), 5000); + return [ + { tag: "plugin", property: "plugin", signal: "pluginChanged", value: testPlugin }, + { tag: "searchArea", property: "searchArea", signal: "searchAreaChanged", value: testSearchArea, reset: QtPositioning.shape() }, + { tag: "limit", property: "limit", signal: "limitChanged", value: 10, reset: -1 }, + + { tag: "searchTerm", property: "searchTerm", signal: "searchTermChanged", value: "Test term", reset: "" }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testModel, data); + } + + SignalSpy { id: statusChangedSpy; target: testModel; signalName: "statusChanged" } + SignalSpy { id: suggestionsChangedSpy; target: testModel; signalName: "suggestionsChanged" } + + function test_suggestions() { + compare(statusChangedSpy.count, 0); + testModel.plugin = testPlugin; + + compare(testModel.status, PlaceSearchSuggestionModel.Null); + + testModel.searchTerm = "test"; + testModel.update(); + + compare(testModel.status, PlaceSearchSuggestionModel.Loading); + compare(statusChangedSpy.count, 1); + + tryCompare(testModel, "status", PlaceSearchSuggestionModel.Ready); + compare(statusChangedSpy.count, 2); + + var expectedSuggestions = [ "test1", "test2", "test3" ]; + + compare(suggestionsChangedSpy.count, 1); + compare(testModel.suggestions, expectedSuggestions); + + testModel.reset(); + + compare(statusChangedSpy.count, 3); + compare(testModel.status, PlaceSearchSuggestionModel.Null); + compare(suggestionsChangedSpy.count, 2); + compare(testModel.suggestions, []); + + testModel.update(); + + compare(statusChangedSpy.count, 4); + compare(testModel.status, PlaceSearchSuggestionModel.Loading); + + testModel.cancel(); + + compare(statusChangedSpy.count, 5); + compare(testModel.status, PlaceSearchSuggestionModel.Ready); + + //check that an encountering an error will cause the model + //to clear its data + testModel.plugin = null; + testModel.update(); + tryCompare(testModel.suggestions, "length", 0); + compare(testModel.status, PlaceSearchSuggestionModel.Error); + } + + SignalSpy { id: statusChangedSpyError; target: testModelError; signalName: "statusChanged" } + + function test_error() { + compare(statusChangedSpyError.count, 0); + //try searching without a plugin instance + testModelError.update(); + tryCompare(statusChangedSpyError, "count", 2); + compare(testModelError.status, PlaceSearchSuggestionModel.Error); + statusChangedSpyError.clear(); + //Aside: there is some difficulty in checking the transition to the Loading state + //since the model transitions from Loading to Error before the next event loop + //iteration. + + //try searching with an uninitialized plugin instance. + testModelError.plugin = uninitializedPlugin; + testModelError.update(); + tryCompare(statusChangedSpyError, "count", 2); + compare(testModelError.status, PlaceSearchSuggestionModel.Error); + statusChangedSpyError.clear(); + + //try searching with plugin a instance + //that has been provided a non-existent name + testModelError.plugin = nonExistantPlugin; + testModelError.update(); + tryCompare(statusChangedSpyError, "count", 2); + compare(testModelError.status, PlaceSearchSuggestionModel.Error); + } +} diff --git a/tests/auto/declarative_core/tst_plugin.qml b/tests/auto/declarative_core/tst_plugin.qml new file mode 100644 index 0000000..3dabba0 --- /dev/null +++ b/tests/auto/declarative_core/tst_plugin.qml @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 + +Item { + + Plugin { id: unattachedPlugin } + Plugin { id: herePlugin; name: "here"} + Plugin { id: invalidPlugin; name: "invalid"; allowExperimental: true } + Plugin { id: testPlugin; + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "supported"; value: true}, + PluginParameter { name: "finishRequestImmediately"; value: true}, + PluginParameter { name: "validateWellKnownValues"; value: true} + ] + } + SignalSpy {id: invalidAttachedSpy; target: invalidPlugin; signalName: "attached"} + + Plugin { + id: requiredPlugin + allowExperimental: true + required { + mapping: Plugin.OfflineMappingFeature; + geocoding: Plugin.OfflineGeocodingFeature; + places: Plugin.AnyPlacesFeatures; + } + } + + TestCase { + name: "Plugin properties" + function test_plugin() { + verify (invalidPlugin.availableServiceProviders.length > 0) + verify (invalidPlugin.availableServiceProviders.indexOf('qmlgeo.test.plugin') > -1) // at least test plugin must be present + + // invalid plugins should have no features + verify(invalidPlugin.isAttached) + verify(!(invalidPlugin.supportsMapping())) + verify(!(invalidPlugin.supportsGeocoding())) + verify(!(invalidPlugin.supportsRouting())) + verify(!(invalidPlugin.supportsPlaces())) + + if (invalidPlugin.availableServiceProviders.indexOf('qmlgeo.test.plugin') > -1) { + verify(testPlugin.isAttached) + verify(testPlugin.supportsMapping()) + verify(testPlugin.supportsGeocoding()) + verify(testPlugin.supportsPlaces()) + verify(testPlugin.supportsRouting()) + } + + if (invalidPlugin.availableServiceProviders.indexOf('here')) { + verify(herePlugin.isAttached) + verify(herePlugin.supportsMapping(Plugin.OnlineMappingFeature)) + verify(herePlugin.supportsGeocoding(Plugin.OnlineGeocodingFeature)) + verify(herePlugin.supportsRouting(Plugin.OnlineRoutingFeature)) + } + + verify(!unattachedPlugin.isAttached) + + // test changing name of plugin + invalidAttachedSpy.clear() + compare(invalidAttachedSpy.count, 0) + invalidPlugin.name = 'qmlgeo.test.plugin' + tryCompare(invalidAttachedSpy, 'count', 1) + verify(invalidPlugin.isAttached) + + verify(invalidPlugin.supportsMapping()) + verify(invalidPlugin.supportsGeocoding()) + verify(invalidPlugin.supportsRouting()) + verify(invalidPlugin.supportsPlaces()) + + invalidPlugin.name = '' + compare(invalidAttachedSpy.count, 2) + + verify(!invalidPlugin.supportsMapping()) + verify(!invalidPlugin.supportsGeocoding()) + verify(!invalidPlugin.supportsRouting()) + verify(!invalidPlugin.supportsPlaces()) + } + + function test_required() { + // the required plugin should either get here or qmlgeo.test.plugin + // either way the name will be non-empty and it'll meet the spec + verify(requiredPlugin.name !== "") + verify(requiredPlugin.supportsMapping(requiredPlugin.required.mapping)) + verify(requiredPlugin.supportsGeocoding(requiredPlugin.required.geocoding)) + verify(requiredPlugin.supportsPlaces(requiredPlugin.required.places)) + } + + function test_placesFeatures() { + verify(testPlugin.supportsPlaces(Plugin.SavePlaceFeature)) + verify(testPlugin.supportsPlaces(Plugin.SaveCategoryFeature)) + verify(testPlugin.supportsPlaces(Plugin.SearchSuggestionsFeature)) + verify(!testPlugin.supportsPlaces(Plugin.RemovePlaceFeature)) + } + + function test_locale() { + compare(herePlugin.locales, [Qt.locale().name]); + + //try assignment of a single locale + herePlugin.locales = "fr_FR"; + compare(herePlugin.locales, ["fr_FR"]); + + //try assignment of multiple locales + herePlugin.locales = ["fr_FR","en_US"]; + compare(herePlugin.locales, ["fr_FR","en_US"]); + + //check that assignment of empty locale list defaults to system locale + herePlugin.locales = []; + compare(herePlugin.locales, [Qt.locale().name]); + } + } +} diff --git a/tests/auto/declarative_core/tst_plugin_error.qml b/tests/auto/declarative_core/tst_plugin_error.qml new file mode 100644 index 0000000..50b0359 --- /dev/null +++ b/tests/auto/declarative_core/tst_plugin_error.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 + +Item { + + Plugin { id: testPlugin; + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "error"; value: "1"}, + PluginParameter { name: "errorString"; value: "This error was expected. No worries !"} + ] + } + + Map { + id: map + } + + SignalSpy {id: errorSpy; target: map; signalName: "errorChanged"} + + TestCase { + name: "MappingManagerError" + function test_error() { + verify (map.error === Map.NoError); + map.plugin = testPlugin; + verify (map.error === Map.NotSupportedError); + verify (map.errorString == "This error was expected. No worries !"); + compare(errorSpy.count, 1); + } + } +} diff --git a/tests/auto/declarative_core/tst_position.qml b/tests/auto/declarative_core/tst_position.qml new file mode 100644 index 0000000..1bde087 --- /dev/null +++ b/tests/auto/declarative_core/tst_position.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtPositioning 5.3 + +TestCase { + id: testCase + + name: "Position" + + Position { id: defaultPosition } + + SignalSpy { id: latitudeValidSpy; target: defaultPosition; signalName: "latitudeValidChanged" } + SignalSpy { id: longitudeValidSpy; target: defaultPosition; signalName: "longitudeValidChanged" } + SignalSpy { id: altitudeValidSpy; target: defaultPosition; signalName: "altitudeValidChanged" } + SignalSpy { id: timestampSpy; target: defaultPosition; signalName: "timestampChanged" } + SignalSpy { id: speedSpy; target: defaultPosition; signalName: "speedChanged" } + SignalSpy { id: speedValidSpy; target: defaultPosition; signalName: "speedValidChanged" } + SignalSpy { id: coordinateSpy; target: defaultPosition; signalName: "coordinateChanged" } + SignalSpy { id: horizontalAccuracySpy; target: defaultPosition; signalName: "horizontalAccuracyChanged" } + SignalSpy { id: horizontalAccuracyValidSpy; target: defaultPosition; signalName: "horizontalAccuracyValidChanged" } + SignalSpy { id: verticalAccuracySpy; target: defaultPosition; signalName: "verticalAccuracyChanged" } + SignalSpy { id: verticalAccuracyValidSpy; target: defaultPosition; signalName: "verticalAccuracyValidChanged" } + SignalSpy { id: directionSpy; target: defaultPosition; signalName: "directionChanged" } + SignalSpy { id: verticalSpeedSpy; target: defaultPosition; signalName: "verticalSpeedChanged" } + + function test_defaults() { + compare(defaultPosition.latitudeValid, false); + compare(defaultPosition.longitudeValid, false); + compare(defaultPosition.altitudeValid, false); + compare(defaultPosition.speedValid, false); + compare(defaultPosition.horizontalAccuracyValid, false); + compare(defaultPosition.verticalAccuracyValid, false); + verify(!defaultPosition.directionValid); + verify(isNaN(defaultPosition.direction)); + verify(!defaultPosition.verticalSpeedValid); + verify(isNaN(defaultPosition.verticalSpeed)); + } + + function test_modifiers() { + latitudeValidSpy.clear(); + longitudeValidSpy.clear(); + altitudeValidSpy.clear(); + timestampSpy.clear(); + speedSpy.clear(); + speedValidSpy.clear(); + coordinateSpy.clear(); + horizontalAccuracySpy.clear(); + horizontalAccuracyValidSpy.clear(); + verticalAccuracySpy.clear(); + verticalAccuracyValidSpy.clear(); + directionSpy.clear(); + verticalSpeedSpy.clear(); + + defaultPosition.horizontalAccuracy = 10; + compare(horizontalAccuracySpy.count, 1); + compare(horizontalAccuracyValidSpy.count, 1); + compare(defaultPosition.horizontalAccuracy, 10); + compare(defaultPosition.horizontalAccuracyValid, true); + + defaultPosition.verticalAccuracy = 10; + compare(verticalAccuracySpy.count, 1); + compare(verticalAccuracyValidSpy.count, 1); + compare(defaultPosition.verticalAccuracy, 10); + compare(defaultPosition.verticalAccuracyValid, true); + + // some extra precautions + compare(horizontalAccuracyValidSpy.count, 1); + compare(speedSpy.count, 0); + compare(speedValidSpy.count, 0); + } +} diff --git a/tests/auto/declarative_core/tst_positionsource.qml b/tests/auto/declarative_core/tst_positionsource.qml new file mode 100644 index 0000000..a663f3a --- /dev/null +++ b/tests/auto/declarative_core/tst_positionsource.qml @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtPositioning 5.2 + +TestCase { + id: testCase + + name: "PositionSource" + + PositionSource { id: defaultSource } + PositionSource + { + id: activeDefaultSource + active: true + } + + SignalSpy { id: defaultSourceSpy; target: defaultSource; signalName: "positionChanged" } + + function test_activeDefaultSource() { + wait(0); + verify(activeDefaultSource.name !== ""); + compare(activeDefaultSource.active, true); + } + + function test_invalidSource() { + activeDefaultSource.name = "invalid_positioning_source"; + verify(!activeDefaultSource.active); + verify(!activeDefaultSource.valid); + } + + function test_defaults() { + // at least the test.source plugin should be available + verify(defaultSource.name != ""); + compare(defaultSource.active, false); + } + + function test_inactive() { + defaultSourceSpy.clear(); + compare(defaultSourceSpy.count, 0); + wait(1000); + compare(defaultSourceSpy.count, 0); + } + + PositionSource { id: testSetSource; name: "nonexistent bogus plugin" } + SignalSpy { id: testingSourcePluginSpy; target: testSetSource; signalName: "nameChanged" } + + function test_setplugin() { + testingSourcePluginSpy.clear(); + + // On construction, if the provided source name is invalid, the default source will be + // used. Test that the source is valid as expected. + verify(testSetSource.name !== ""); + //we don't really know what the default source is named. + //It may not be "test.source" + var defaultSourceName = testSetSource.name; + verify(testSetSource.valid); + + // Test that setting name to "" will still use the default. + testSetSource.name = ""; + compare(testingSourcePluginSpy.count, 0); + compare(testSetSource.name, defaultSourceName); + verify(testSetSource.valid); + + testSetSource.name = "test.source"; + if (defaultSourceName === "test.source") + compare(testingSourcePluginSpy.count, 0); + compare(testSetSource.name, "test.source"); + verify(testSetSource.valid); + testingSourcePluginSpy.clear(); + + testSetSource.name = "bogus"; + compare(testingSourcePluginSpy.count, 1); + verify(!testSetSource.valid); + } + + PositionSource { id: testingSource; name: "test.source"; updateInterval: 1000 } + SignalSpy { id: updateSpy; target: testingSource; signalName: "positionChanged" } + SignalSpy { id: directionValidSpy; target: testingSource.position; signalName: "directionValidChanged" } + SignalSpy { id: directionSpy; target: testingSource.position; signalName: "directionChanged" } + + function test_updateInterval() { + testingSource.updateInterval = 1000; + compare(testingSource.updateInterval, 1000); + testingSource.updateInterval = 1200; + compare(testingSource.updateInterval, 1200); + testingSource.updateInterval = 800; + compare(testingSource.updateInterval, 1000); + } + + function test_preferredPositioningMethods() { + testingSource.preferredPositioningMethods = PositionSource.AllPositioningMethods; + compare(testingSource.preferredPositioningMethods, PositionSource.AllPositioningMethods); + testingSource.preferredPositioningMethods = PositionSource.SatellitePositioningMethods; + compare(testingSource.preferredPositioningMethods, PositionSource.SatellitePositioningMethods); + testingSource.preferredPositioningMethods = PositionSource.NonSatellitePositioningMethods; + compare(testingSource.preferredPositioningMethods, PositionSource.NonSatellitePositioningMethods); + } + + function test_updates() { + updateSpy.clear(); + + compare(directionValidSpy.count, 0) + compare(directionSpy.count, 0) + + testingSource.active = true; + + tryCompare(updateSpy, "count", 1, 1500); + compare(testingSource.position.coordinate.longitude, 0.1); + compare(testingSource.position.coordinate.latitude, 0.1); + compare(directionValidSpy.count, 1) + compare(directionSpy.count, 1) + fuzzyCompare(testingSource.position.direction, 45, 0.1) + verify(!testingSource.position.speedValid) + verify(isNaN(testingSource.position.speed)) + + tryCompare(updateSpy, "count", 2, 1500); + compare(testingSource.position.coordinate.longitude, 0.2); + compare(testingSource.position.coordinate.latitude, 0.2); + compare(directionValidSpy.count, 1) + compare(directionSpy.count, 2) + fuzzyCompare(testingSource.position.direction, 45, 0.1) + verify(testingSource.position.speedValid) + verify(testingSource.position.speed > 10000) + + testingSource.active = false; + wait(2500); + compare(updateSpy.count, 2); + compare(testingSource.position.coordinate.longitude, 0.2); + compare(testingSource.position.coordinate.latitude, 0.2); + compare(directionValidSpy.count, 1) + compare(directionSpy.count, 2) + fuzzyCompare(testingSource.position.direction, 45, 0.1) + verify(testingSource.position.speedValid) + verify(testingSource.position.speed > 10000) + } +} diff --git a/tests/auto/declarative_core/tst_ratings.qml b/tests/auto/declarative_core/tst_ratings.qml new file mode 100644 index 0000000..5628432 --- /dev/null +++ b/tests/auto/declarative_core/tst_ratings.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "Ratings" + + Ratings { id: emptyRatings } + + function test_empty() { + compare(emptyRatings.average, 0.0); + compare(emptyRatings.maximum, 0.0); + compare(emptyRatings.count, 0); + } + + Ratings { + id: qmlRatings + + average: 3.5 + maximum: 5.0 + count: 7 + } + + function test_qmlConstructedRatings() { + compare(qmlRatings.average, 3.5); + compare(qmlRatings.maximum, 5.0); + compare(qmlRatings.count, 7); + } + + Ratings { + id: testRatings + } + + function test_setAndGet_data() { + return [ + { tag: "average", property: "average", signal: "averageChanged", value: 4.5, reset: 0.0 }, + { tag: "maximum", property: "maximum", signal: "maximumChanged", value: 5.0, reset: 0.0 }, + { tag: "count", property: "count", signal: "countChanged", value: 10, reset: 0 }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testRatings, data); + } +} diff --git a/tests/auto/declarative_core/tst_reviewmodel.qml b/tests/auto/declarative_core/tst_reviewmodel.qml new file mode 100644 index 0000000..192026f --- /dev/null +++ b/tests/auto/declarative_core/tst_reviewmodel.qml @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + name: "ReviewModel" + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + PluginParameter { + name: "initializePlaceData" + value: true + } + ] + } + + ReviewModel { + id: testModel + } + + Place { + id: testPlace + name: "Test Place" + } + + Place { + id: parkViewHotel + placeId: "4dcc74ce-fdeb-443e-827c-367438017cf1" + plugin: testPlugin + } + + Place { + id: seaViewHotel + placeId: "8f72057a-54b2-4e95-a7bb-97b4d2b5721e" + plugin: testPlugin + } + + function test_setAndGet_data() { + return [ + { tag: "place", property: "place", signal: "placeChanged", value: testPlace }, + { tag: "batchSize", property: "batchSize", signal: "batchSizeChanged", value: 10, reset: 1 }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testModel, data); + } + + function test_consecutive_fetch_data() { + return [ + { tag: "batchSize 1", batchSize: 1 }, + { tag: "batchSize 2", batchSize: 2 }, + { tag: "batchSize 5", batchSize: 5 }, + { tag: "batchSize 10", batchSize: 10 }, + ]; + } + + function test_consecutive_fetch(data) { + //Note: in javascript the months go from 0(Jan) to 11(Dec) + var expectedReviews = [ + { + "title": "Park View Review 1", + "text": "Park View Review 1 Text", + "dateTime": new Date(2004, 8, 22, 13, 1), + "language": "en", + "rating": 3.5, + "reviewId": "0001" + }, + { + "title": "Park View Review 2", + "text": "Park View Review 2 Text", + "dateTime": new Date(2005, 8, 14, 4, 17), + "language": "en", + "rating": 1, + "reviewId": "0002" + }, + { + "title": "Park View Review 3", + "text": "Park View Review 3 Text", + "dateTime": new Date(2005, 9, 14, 4, 12), + "language": "en", + "rating": 5, + "reviewId": "0003" + }, + { + "title": "", + "text": "", + "dateTime": new Date(""), + "language": "", + "rating": 0, + "reviewId": "" + }, + { + "title": "Park View Review 5", + "text": "Park View Review 5 Text", + "dateTime": new Date(2005, 10, 20, 14, 53), + "language": "en", + "rating": 2.3, + "reviewId": "0005" + } + ] + + var model = createModel(); + Utils.testConsecutiveFetch(testCase, model, parkViewHotel, expectedReviews, data); + model.destroy(); + } + + function test_reset() { + var model = createModel(); + Utils.testReset(testCase, model, parkViewHotel); + model.destroy(); + } + + function test_fetch_data() { + return [ + { + tag: "fetch all reviews in a single batch", + model: createModel(), + batchSize: 10, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 5 + }, + { + tag: "fetch from a place with no reviews", + model: createModel(), + batchSize: 1, + place: seaViewHotel, + expectedTotalCount: 0, + expectedCount: 0 + }, + { + tag: "fetch with batch size one less than the total", + model: createModel(), + batchSize: 4, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 4 + }, + { + tag: "fetch with batch size equal to the total", + model: createModel(), + batchSize: 5, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 5 + }, + { + tag: "fetch with batch size larger than the total", + model: createModel(), + batchSize: 6, + place: parkViewHotel, + expectedTotalCount: 5, + expectedCount: 5 + } + ] + } + + function test_fetch(data) { + Utils.testFetch(testCase, data); + data.model.destroy(); + } + + function createModel() { + return Qt.createQmlObject('import QtLocation 5.3; ReviewModel {}', + testCase, "reviewModel"); + } +} diff --git a/tests/auto/declarative_core/tst_routing.qml b/tests/auto/declarative_core/tst_routing.qml new file mode 100644 index 0000000..fdbfe7b --- /dev/null +++ b/tests/auto/declarative_core/tst_routing.qml @@ -0,0 +1,805 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import QtPositioning 5.2 + +Item { + Plugin { id: testPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true } + Plugin { id: errorPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true + parameters: [ + PluginParameter { name: "error"; value: "1"}, + PluginParameter { name: "errorString"; value: "This error was expected. No worries !"} + ] + } + + property variant coordinate1: QtPositioning.coordinate(51, 0) + property variant coordinate2: QtPositioning.coordinate(52, 0) + + property variant boundingBox1: QtPositioning.rectangle() + property variant boundingBox2: QtPositioning.rectangle() + + property variant circle1: QtPositioning.circle() + property variant circle2: QtPositioning.circle(tr, 4000) + + Component.onCompleted: { + boundingBox1.topLeft = bl + boundingBox1.bottomRight = bl + boundingBox1.width = 10 + + boundingBox2.topLeft = bl + boundingBox2.bottomRight = bl + boundingBox2.width = 20 + } + + property variant bl: QtPositioning.coordinate(0, 0) + property variant tl: QtPositioning.coordinate(1, 0) + property variant tr: QtPositioning.coordinate(1, 1) + property variant br: QtPositioning.coordinate(0, 1) + property variant ntr: QtPositioning.coordinate(3, 3) + + property variant unitBox: QtPositioning.rectangle(tl, br) + + Route {id: emptyRoute} + TestCase { + name: "RouteManeuver RouteSegment and MapRoute" + RouteSegment {id: emptySegment} + RouteManeuver {id: emptyManeuver} + + // TODO enable when we have map route + //MapRoute {id: emptyMapRoute} + + property variant emptyBox: QtPositioning.rectangle() + + property variant emptyCoordinate: QtPositioning.coordinate() + + // TODO enable when we have map route + /* + SignalSpy {id: mapRouteDetailLevelSpy; target: emptyMapRoute; signalName: "detailLevelChanged"} + SignalSpy {id: mapRouteColorSpy; target: emptyMapRoute.border; signalName: "colorChanged"} + SignalSpy {id: mapRouteWidthSpy; target: emptyMapRoute.border; signalName: "widthChanged"} + SignalSpy {id: mapRouteRouteSpy; target: emptyMapRoute; signalName: "routeChanged"} + function test_maproute_defaults() { + compare(mapRouteRouteSpy.count, 0) + compare(mapRouteColorSpy.count, 0) + compare(mapRouteDetailLevelSpy.count, 0) + compare (emptyMapRoute.detailLevel, 6) + emptyMapRoute.border.color = 'green' + emptyMapRoute.detailLevel = 3 + compare(mapRouteRouteSpy.count, 0) + compare(mapRouteColorSpy.count, 1) + compare(mapRouteDetailLevelSpy.count, 1) + emptyMapRoute.border.color = 'green' + emptyMapRoute.detailLevel = 3 + compare(mapRouteColorSpy.count, 1) + compare(mapRouteDetailLevelSpy.count, 1) + emptyMapRoute.route = emptyRoute + compare(mapRouteRouteSpy.count, 1) + compare(emptyMapRoute.route, emptyRoute) + // width + compare(mapRouteWidthSpy.count, 0) + emptyMapRoute.border.width = 123 + compare(mapRouteWidthSpy.count, 1) + compare(emptyMapRoute.border.width, 123) + emptyMapRoute.border.width = 123 + compare(mapRouteWidthSpy.count, 1) + emptyMapRoute.border.width = -1 + compare(mapRouteWidthSpy.count, 1) + compare(emptyMapRoute.border.width, 123) + emptyMapRoute.border.width = 0 + compare(mapRouteWidthSpy.count, 1) + compare(emptyMapRoute.border.width, 123) + } + */ + + function test_route_defaults() { + compare(emptyRoute.travelTime, 0) + compare(emptyRoute.distance,0) + compare(emptyRoute.path.length,0) + compare(emptyRoute.segments.length,0) + compare(emptyRoute.bounds.topLeft.latitude, emptyBox.topLeft.latitude) + compare(emptyRoute.bounds.bottomRight.longitude, emptyBox.bottomRight.longitude) + } + + function test_routesegment_defaults() { + compare(emptySegment.travelTime, 0) + compare(emptySegment.distance, 0) + compare(emptySegment.path.length, 0) + compare(emptySegment.maneuver.valid, emptyManeuver.valid) + compare(emptySegment.maneuver.instructionText, emptyManeuver.instructionText) + compare(emptySegment.maneuver.waypointValid, emptyManeuver.waypointValid) + } + function test_maneuver_defaults() { + compare(emptyManeuver.valid, false) + compare(emptyManeuver.instructionText, "") + compare(emptyManeuver.direction, RouteManeuver.NoDirection) + compare(emptyManeuver.timeToNextInstruction,0) + compare(emptyManeuver.distanceToNextInstruction,0) + compare(emptyManeuver.waypoint.latitude, emptyCoordinate.latitude) + compare(emptyManeuver.waypoint.longitude, emptyCoordinate.longitude) + compare(emptyManeuver.position.latitude, emptyCoordinate.latitude) + compare(emptyManeuver.position.longitude, emptyCoordinate.longitude) + } + } + + TestCase { + name: "MapRouteModel and MapRouteQuery" + RouteModel {id: emptyModel} + RouteQuery {id: emptyQuery} + + function test_model_default_properties() { + compare (emptyModel.autoUpdate, false, "Automatic update") + compare (emptyModel.status, RouteModel.Null, "Model status") + compare (emptyModel.errorString, "", "Model error") + compare (emptyModel.error, RouteModel.NoError) + compare (emptyModel.count, 0, "Model count") + emptyModel.get(192) // don't do stupid + + compare (emptyQuery.numberAlternativeRoutes, 0, "Number of alternative routes") + compare (emptyQuery.travelModes, RouteQuery.CarTravel, "Travel mode") + compare (emptyQuery.routeOptimizations, RouteQuery.FastestRoute, "Route optimization") + compare (emptyQuery.segmentDetail, RouteQuery.BasicSegmentData) + compare (emptyQuery.maneuverDetail, RouteQuery.BasicManeuvers) + compare (emptyQuery.waypoints.length, 0, "Waypoints") + compare (emptyQuery.excludedAreas.length, 0, "excluded areas") + // Bug in QtQml. Todo, enable when QList support is done + //compare (emptyQuery.featureTypes.length, 0, "Feature types") + } + + SignalSpy {id: autoUpdateSpy; target: emptyModel; signalName: "autoUpdateChanged"} + SignalSpy {id: pluginSpy; target: emptyModel ; signalName: "pluginChanged"} + + SignalSpy {id: travelModesSpy; target: emptyQuery; signalName: "travelModesChanged"} + SignalSpy {id: waypointsSpy; target: emptyQuery; signalName: "waypointsChanged"} + SignalSpy {id: exclusionSpy; target: emptyQuery; signalName: "excludedAreasChanged"} + SignalSpy {id: featureTypesSpy; target: emptyQuery; signalName: "featureTypesChanged"} + SignalSpy {id: segmentDetailSpy; target: emptyQuery; signalName: "segmentDetailChanged"} + SignalSpy {id: maneuverDetailSpy; target: emptyQuery; signalName: "maneuverDetailChanged"} + SignalSpy {id: numberAlterNativeRoutesSpy; target: emptyQuery; signalName: "numberAlternativeRoutesChanged"} + SignalSpy {id: routeOptimizationsSpy; target: emptyQuery; signalName: "routeOptimizationsChanged"} + SignalSpy {id: queryDetailsChangedSpy; target: emptyQuery; signalName: "queryDetailsChanged"} + function test_model_setters() { + // Autoupdate + compare(autoUpdateSpy.count, 0) + emptyModel.autoUpdate = true + compare(autoUpdateSpy.count, 1) + compare(emptyModel.autoUpdate, true) + emptyModel.autoUpdate = true // mustn't retrigger 'changed' -signal + compare(autoUpdateSpy.count, 1) + emptyModel.autoUpdate = false + compare(autoUpdateSpy.count, 2) + + // Travelmodes + compare(travelModesSpy.count, 0) + emptyQuery.travelModes = RouteQuery.BicycleTravel + compare(travelModesSpy.count, 1) + compare(emptyQuery.travelModes, RouteQuery.BicycleTravel) + emptyQuery.travelModes = RouteQuery.BicycleTravel | RouteQuery.PedestrianTravel + compare(emptyQuery.travelModes, RouteQuery.BicycleTravel | RouteQuery.PedestrianTravel) + compare(travelModesSpy.count, 2) + compare(queryDetailsChangedSpy.count, 2) + + // Basic adding and removing of waypoint + queryDetailsChangedSpy.clear() + compare(waypointsSpy.count, 0) + emptyQuery.addWaypoint(coordinate1) + compare(waypointsSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + emptyQuery.addWaypoint(coordinate1) + compare(waypointsSpy.count, 2) + compare(queryDetailsChangedSpy.count, 2) + compare(emptyQuery.waypoints.length, 2) + emptyQuery.removeWaypoint(coordinate1) + compare(waypointsSpy.count, 3) + compare(queryDetailsChangedSpy.count, 3) + compare(emptyQuery.waypoints.length, 1) + emptyQuery.removeWaypoint(coordinate2) // coordinate2 isn't in the list, must not impact + compare(waypointsSpy.count, 3) + compare(queryDetailsChangedSpy.count, 3) + emptyQuery.removeWaypoint(coordinate1) + compare(waypointsSpy.count, 4) + emptyQuery.removeWaypoint(coordinate1) // doesn't exist anymore, must not impact + compare(waypointsSpy.count, 4) + compare(emptyQuery.waypoints.length, 0) + // Check correct ordering of waypoints + waypointsSpy.clear() + emptyQuery.addWaypoint(coordinate1) + emptyQuery.addWaypoint(coordinate2) + emptyQuery.addWaypoint(coordinate1) + emptyQuery.addWaypoint(coordinate2) + compare(waypointsSpy.count, 4) + compare(emptyQuery.waypoints[0], coordinate1) + compare(emptyQuery.waypoints[1], coordinate2) + compare(emptyQuery.waypoints[2], coordinate1) + compare(emptyQuery.waypoints[3], coordinate2) + emptyQuery.removeWaypoint(coordinate1) // remove one from the middle, check that one added last is removed + compare(emptyQuery.waypoints[0], coordinate1) + compare(emptyQuery.waypoints[1], coordinate2) + compare(emptyQuery.waypoints[2], coordinate2) + waypointsSpy.clear() + emptyQuery.clearWaypoints() + compare(emptyQuery.waypoints.length, 0) + compare(waypointsSpy.count, 1) + + // Altering the waypoint contents should trigger signal + emptyQuery.clearWaypoints() + queryDetailsChangedSpy.clear(); + emptyQuery.addWaypoint(coordinate1) + compare(queryDetailsChangedSpy.count, 1); + + // verify coordinate is disconnected + emptyQuery.removeWaypoint(coordinate1) + compare (queryDetailsChangedSpy.count, 2) + + // verify that the same coordinate can be added to the waypoints + emptyQuery.addWaypoint(coordinate1) + compare(queryDetailsChangedSpy.count, 3); + emptyQuery.addWaypoint(coordinate1) + compare(queryDetailsChangedSpy.count, 4); + compare (emptyQuery.waypoints.length, 2) + queryDetailsChangedSpy.clear() + + // verify that removing duplicate coordinate leaves remaining ones + emptyQuery.removeWaypoint(coordinate1) + compare (queryDetailsChangedSpy.count, 1) + compare (emptyQuery.waypoints.length, 1) + + // verify that clearing works + emptyQuery.clearWaypoints() + compare(queryDetailsChangedSpy.count, 2); + compare (emptyQuery.waypoints.length, 0) + + // Excluded areas + queryDetailsChangedSpy.clear() + compare(exclusionSpy.count, 0) + emptyQuery.addExcludedArea(boundingBox1) + compare(exclusionSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + emptyQuery.addExcludedArea(boundingBox1) + // doesn't make sense to put same area twice + compare(exclusionSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + compare(emptyQuery.excludedAreas.length, 1) + emptyQuery.removeExcludedArea(boundingBox1) + compare(exclusionSpy.count, 2) + compare(queryDetailsChangedSpy.count, 2) + compare(emptyQuery.excludedAreas.length, 0) + emptyQuery.removeExcludedArea(boundingBox2) // boundingBox2 isn't in the list, must not impact + compare(exclusionSpy.count, 2) + compare(queryDetailsChangedSpy.count, 2) + emptyQuery.removeExcludedArea(boundingBox1) // doesn't exist anymore, must not impact + compare(exclusionSpy.count, 2) + compare(queryDetailsChangedSpy.count, 2) + // Check correct ordering of exclusion + exclusionSpy.clear() + emptyQuery.addExcludedArea(boundingBox1) + emptyQuery.addExcludedArea(boundingBox2) + emptyQuery.addExcludedArea(boundingBox1) + emptyQuery.addExcludedArea(boundingBox2) + compare(exclusionSpy.count, 2) + compare(emptyQuery.excludedAreas[0], boundingBox1) + compare(emptyQuery.excludedAreas[1], boundingBox2) + emptyQuery.removeExcludedArea(boundingBox1) // remove first and check all geos ok + compare(emptyQuery.excludedAreas[0], boundingBox2) + exclusionSpy.clear() + emptyQuery.clearExcludedAreas() + compare(emptyQuery.excludedAreas.length, 0) + compare(exclusionSpy.count, 1) + + // verify that clearing works + emptyQuery.addExcludedArea(unitBox); + compare(emptyQuery.excludedAreas.length, 1); + queryDetailsChangedSpy.clear(); + emptyQuery.clearExcludedAreas(); + compare(queryDetailsChangedSpy.count, 1); + compare(emptyQuery.excludedAreas.length, 0) + + // Feature types and weights + queryDetailsChangedSpy.clear() + // Bug in QtQml. Todo, enable when QList support is done + //compare(emptyQuery.featureTypes.length, 0) + compare(featureTypesSpy.count, 0) + emptyQuery.setFeatureWeight(RouteQuery.TollFeature, RouteQuery.AvoidFeatureWeight); + compare(featureTypesSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + emptyQuery.setFeatureWeight(RouteQuery.HighwayFeature, RouteQuery.PreferFeatureWeight); + compare(featureTypesSpy.count, 2) + compare(queryDetailsChangedSpy.count, 2) + // Bug in QtQml. Todo, enable when QList support is done + //compare(emptyQuery.featureTypes.length, 2) + //compare(emptyQuery.featureTypes[0], RouteQuery.TollFeature) + //compare(emptyQuery.featureTypes[1], RouteQuery.HighwayFeature) + // Verify feature weights are as set + compare(emptyQuery.featureWeight(RouteQuery.TollFeature), RouteQuery.AvoidFeatureWeight); + compare(emptyQuery.featureWeight(RouteQuery.HighwayFeature), RouteQuery.PreferFeatureWeight); + // Neutralize a weight, feature should disappear + emptyQuery.setFeatureWeight(RouteQuery.TollFeature, RouteQuery.NeutralFeatureWeight); + compare(featureTypesSpy.count, 3) + compare(queryDetailsChangedSpy.count, 3) + // Bug in QtQml. Todo, enable when QList support is done + //compare(emptyQuery.featureTypes.length, 1) + compare(emptyQuery.featureWeight(RouteQuery.TollFeature), RouteQuery.NeutralFeatureWeight); + compare(emptyQuery.featureWeight(RouteQuery.HighwayFeature), RouteQuery.PreferFeatureWeight); + // Bug in QtQml. Todo, enable when QList support is done + //compare(emptyQuery.featureTypes[0], RouteQuery.HighwayFeature) + //compare(emptyQuery.featureWeight(emptyQuery.featureTypes[0]), RouteQuery.PreferFeatureWeight) + compare(featureTypesSpy.count, 3) + compare(queryDetailsChangedSpy.count, 3) + // Bug in QtQml. Todo, enable when QList support is done + //compare(emptyQuery.featureTypes.length, 1) + + // Put some feature weights and then reset them with NoFeature + emptyQuery.setFeatureWeight(RouteQuery.FerryFeature, RouteQuery.RequireFeatureWeight); + emptyQuery.setFeatureWeight(RouteQuery.MotorPoolLaneFeature, RouteQuery.DisallowFeatureWeight); + compare(featureTypesSpy.count, 5) + compare(queryDetailsChangedSpy.count, 5) + // Bug in QtQml. Todo, enable when QList support is done + //compare(emptyQuery.featureTypes.length, 3) + emptyQuery.setFeatureWeight(RouteQuery.NoFeature, RouteQuery.NeutralFeatureWeight) + compare(featureTypesSpy.count, 6) + compare(queryDetailsChangedSpy.count, 6) + // Bug in QtQml. Todo, enable when QList support is done + //compare(emptyQuery.featureTypes.length, 0) + + // Segment details + queryDetailsChangedSpy.clear() + compare(segmentDetailSpy.count, 0) + compare(emptyQuery.segmentDetail, RouteQuery.BasicSegmentData) + emptyQuery.segmentDetail = RouteQuery.NoSegmentData + compare(segmentDetailSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + compare(emptyQuery.segmentDetail, RouteQuery.NoSegmentData) + emptyQuery.segmentDetail = RouteQuery.NoSegmentData + compare(segmentDetailSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + compare(emptyQuery.segmentDetail, RouteQuery.NoSegmentData) + + // Maneuver details + queryDetailsChangedSpy.clear() + compare(maneuverDetailSpy.count, 0) + compare(emptyQuery.maneuverDetail, RouteQuery.BasicManeuvers) + emptyQuery.maneuverDetail = RouteQuery.NoManeuvers + compare(maneuverDetailSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + compare(emptyQuery.maneuverDetail, RouteQuery.NoManeuvers) + emptyQuery.maneuverDetail = RouteQuery.NoManeuvers + compare(maneuverDetailSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + compare(emptyQuery.maneuverDetail, RouteQuery.NoManeuvers) + + // NumberAlternativeRoutes + queryDetailsChangedSpy.clear() + compare(numberAlterNativeRoutesSpy.count, 0) + compare(emptyQuery.numberAlternativeRoutes, 0) + emptyQuery.numberAlternativeRoutes = 2 + compare(numberAlterNativeRoutesSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + compare(emptyQuery.numberAlternativeRoutes, 2) + emptyQuery.numberAlternativeRoutes = 2 + compare(numberAlterNativeRoutesSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + compare(emptyQuery.numberAlternativeRoutes, 2) + + // Route optimization + queryDetailsChangedSpy.clear() + compare(routeOptimizationsSpy.count, 0) + compare(emptyQuery.routeOptimizations, RouteQuery.FastestRoute) + emptyQuery.routeOptimizations = RouteQuery.ShortestRoute + compare(routeOptimizationsSpy.count, 1) + compare(queryDetailsChangedSpy.count, 1) + compare(emptyQuery.routeOptimizations, RouteQuery.ShortestRoute) + emptyQuery.routeOptimizations = RouteQuery.ShortestRoute | RouteQuery.MostScenicRoute + compare(routeOptimizationsSpy.count, 2) + compare(queryDetailsChangedSpy.count, 2) + compare(emptyQuery.routeOptimizations, RouteQuery.ShortestRoute | RouteQuery.MostScenicRoute) + + // Must act gracefully + emptyModel.reset() + emptyModel.update() + + // Plugin + compare(pluginSpy.count, 0) + emptyModel.plugin = testPlugin + compare(pluginSpy.count, 1) + compare(emptyModel.plugin, testPlugin) + emptyModel.plugin = testPlugin + compare(pluginSpy.count, 1) + emptyModel.plugin = errorPlugin + compare(pluginSpy.count, 2) + + // Must act gracefully + emptyModel.reset() + emptyModel.update() + } + // Test that model acts gracefully when plugin is not set or is invalid + // (does not support routing) + RouteModel {id: errorModel; plugin: errorPlugin} + RouteModel {id: errorModelNoPlugin} + SignalSpy {id: countInvalidSpy; target: errorModel; signalName: "countChanged"} + SignalSpy {id: errorSpy; target: errorModel; signalName: "errorChanged"} + function test_error_plugin() { + // test plugin not set + compare(errorModelNoPlugin.error,RouteModel.NoError) + errorModelNoPlugin.update() + compare(errorModelNoPlugin.error,RouteModel.EngineNotSetError) + console.log(errorModelNoPlugin.errorString) + + //plugin set but otherwise not offering anything + compare(errorModel.error,RouteModel.EngineNotSetError) + compare(errorModel.errorString,"This error was expected. No worries !") + errorSpy.clear() + errorModel.update() + compare(errorModel.error,RouteModel.EngineNotSetError) + compare(errorModel.errorString,qsTr("Cannot route, route manager not set.")) + compare(errorSpy.count, 1) + errorSpy.clear() + errorModel.cancel() + compare(errorModel.error,RouteModel.NoError) + compare(errorModel.errorString,"") + compare(errorSpy.count, 1) + errorSpy.clear() + errorModel.reset() + compare(errorModel.error,RouteModel.NoError) + compare(errorModel.errorString,"") + compare(errorSpy.count, 0) + errorSpy.clear() + errorModel.update() + compare(errorModel.error,RouteModel.EngineNotSetError) + compare(errorModel.errorString,qsTr("Cannot route, route manager not set.")) + compare(errorSpy.count, 1) + errorSpy.clear() + var data = errorModel.get(-1) + compare(data, null) + } + } + + Plugin { + id: testPlugin_immediate; + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "gc_supported"; value: true}, + PluginParameter { name: "gc_finishRequestImmediately"; value: true}, + PluginParameter { name: "gc_validateWellKnownValues"; value: true} + ] + } + + Plugin { + id: testPlugin_slacker; + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "gc_finishRequestImmediately"; value: false} + ] + } + + Plugin { + id: bacicRoutingPlugin_slacker; + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "gc_finishRequestImmediately"; value: false} + ] + } + + property variant rcoordinate1: QtPositioning.coordinate(50, 50) + property variant rcoordinate2: QtPositioning.coordinate(51, 52) + property variant rcoordinate3: QtPositioning.coordinate(53, 54) + property variant rcoordinate4: QtPositioning.coordinate(55, 56) + property variant rcoordinate5: QtPositioning.coordinate(57, 58) + + property variant fcoordinate1: QtPositioning.coordinate(60, 60) + property variant fcoordinate2: QtPositioning.coordinate(61, 62) + property variant fcoordinate3: QtPositioning.coordinate(63, 64) + property variant fcoordinate4: QtPositioning.coordinate(65, 66) + property variant fcoordinate5: QtPositioning.coordinate(67, 68) + + property variant f2coordinate1: QtPositioning.coordinate(60, 60) + property variant f2coordinate2: QtPositioning.coordinate(61, 62) + property variant f2coordinate3: QtPositioning.coordinate(63, 64) + + RouteQuery {id: routeQuery} + RouteQuery { + id: filledRouteQuery + numberAlternativeRoutes: 0 + waypoints: [ + { latitude: 60, longitude: 60 }, + { latitude: 61, longitude: 62 }, + { latitude: 63, longitude: 64 }, + { latitude: 65, longitude: 66 }, + { latitude: 67, longitude: 68 } + ] + } + RouteQuery { + id: filledRouteQuery2 + waypoints: [ + f2coordinate1, + f2coordinate2, + f2coordinate3 + ] + } + RouteModel { + id: routeModelAutomatic; + plugin: testPlugin_slacker; + query: filledRouteQuery; + autoUpdate: true + } + + SignalSpy {id: automaticRoutesSpy; target: routeModelAutomatic; signalName: "routesChanged" } + + RouteModel {id: routeModel; plugin: testPlugin_immediate; query: routeQuery } + SignalSpy {id: testRoutesSpy; target: routeModel; signalName: "routesChanged"} + SignalSpy {id: testCountSpy; target: routeModel; signalName: "countChanged" } + SignalSpy {id: testStatusSpy; target: routeModel; signalName: "statusChanged"} + SignalSpy {id: testErrorStringSpy; target: routeModel; signalName: "errorChanged"} + SignalSpy {id: testErrorSpy; target: routeModel; signalName: "errorChanged"} + SignalSpy {id: testWaypointsSpy; target: routeQuery; signalName: "waypointsChanged"} + + RouteModel {id: routeModelSlack; plugin: bacicRoutingPlugin_slacker; query: routeQuery } + SignalSpy {id: testRoutesSlackSpy; target: routeModelSlack; signalName: "routesChanged"} + SignalSpy {id: testCountSlackSpy; target: routeModelSlack; signalName: "countChanged" } + SignalSpy {id: testStatusSlackSpy; target: routeModelSlack; signalName: "statusChanged"} + SignalSpy {id: testErrorStringSlackSpy; target: routeModelSlack; signalName: "errorChanged"} + SignalSpy {id: testErrorSlackSpy; target: routeModelSlack; signalName: "errorChanged"} + SignalSpy {id: testPluginSlackSpy; target: routeModelSlack; signalName: "pluginChanged"} + + TestCase { + name: "Routing" + function clear_immediate_model() { + routeModel.reset() + testRoutesSpy.clear() + testCountSpy.clear() + testStatusSpy.clear() + testErrorStringSpy.clear() + testErrorSpy.clear() + } + function clear_slacker_model() { + routeModelSlack.reset() + testRoutesSlackSpy.clear() + testCountSlackSpy.clear() + testStatusSlackSpy.clear() + testErrorStringSlackSpy.clear() + testErrorSlackSpy.clear() + } + + function test_reset() { + clear_immediate_model(); + routeQuery.numberAlternativeRoutes = 72 // 'altroutes - 70' is the echoed errorcode + routeModel.update() + verify (testErrorStringSpy.count > 0) + verify (testErrorSpy.count > 0) + compare (routeModel.errorString, "error") + compare (routeModel.error, RouteModel.CommunicationError) + compare (routeModel.count, 0) + compare (testStatusSpy.count, 2) + compare (routeModel.status, RouteModel.Error) + routeModel.reset() + compare (routeModel.status, RouteModel.Null) + compare (routeModel.errorString, "") + compare (routeModel.error, RouteModel.NoError) + // Check that ongoing req is aborted + clear_slacker_model() + routeQuery.numberAlternativeRoutes = 3 + routeModelSlack.update() + wait (100) + routeModelSlack.reset() + wait (200) + compare (routeModelSlack.count, 0) + // Check that results are cleared + routeModelSlack.update() + tryCompare(routeModelSlack, "count", 3) // numberALternativeRoutes + routeModelSlack.reset() + compare (routeModelSlack.count, 0) + // Check that changing plugin resets any ongoing requests + clear_slacker_model() + routeQuery.numberAlternativeRoutes = 3 + compare (testPluginSlackSpy.count, 0) + routeModelSlack.update() + wait (100) + routeModelSlack.plugin = testPlugin_immediate + wait (200) + compare (routeModelSlack.count, 0) // should be no updates + compare (testPluginSlackSpy.count, 1) + // test that works + routeModelSlack.update() + compare (routeModelSlack.count, 3) + // return back + routeModelSlack.plugin = testPlugin_slacker + } + + function test_error_routing() { + // Basic immediate error + clear_immediate_model(); + routeQuery.numberAlternativeRoutes = 72 // 'altroutes - 70' is the echoed errorcode + routeModel.update() + compare (testErrorStringSpy.count, 1) + compare (testErrorSpy.count, 1) + compare (routeModel.errorString, "error") + compare (routeModel.error, RouteModel.CommunicationError) + compare (routeModel.count, 0) + compare (testStatusSpy.count, 2) + compare (routeModel.status, RouteModel.Error) + // Basic delayed error + clear_slacker_model() + routeQuery.numberAlternativeRoutes = 72 + routeModelSlack.update() + compare (testErrorStringSlackSpy.count, 0) + compare (testErrorSlackSpy.count, 0) + if (routeModelSlack.errorString == "") + tryCompare(testErrorStringSlackSpy, "count", 1) + else + tryCompare(testErrorStringSlackSpy, "count", 2) + compare (routeModelSlack.errorString, "error") + compare (routeModelSlack.error, RouteModel.CommunicationError) + compare (routeModelSlack.count, 0) + // check that we recover + routeQuery.numberAlternativeRoutes = 1 + routeModelSlack.update() + tryCompare(routeModelSlack, "count", 1) + compare (testCountSlackSpy.count, 1) + compare (routeModelSlack.errorString, "") + compare (routeModelSlack.error, RouteModel.NoError) + } + function test_basic_routing() { + compare (testRoutesSpy.count, 0) + compare (routeModel.errorString, "") + compare (routeModel.error, RouteModel.NoError) + compare (testCountSpy.count, 0) + compare (routeModel.count, 0) + compare (routeQuery.waypoints.length, 0) + compare (testWaypointsSpy.count, 0) + routeQuery.addWaypoint(rcoordinate1) + routeQuery.addWaypoint(rcoordinate2) + routeQuery.addWaypoint(rcoordinate3) + routeQuery.addWaypoint(rcoordinate4) + routeQuery.addWaypoint(rcoordinate5) + compare (testWaypointsSpy.count, 5) + compare (routeQuery.waypoints.length, 5) + routeQuery.numberAlternativeRoutes = 1 // how many routes to get back, > 70 indicates error + routeModel.update() + tryCompare (testRoutesSpy, "count", 1) // 5 sec + tryCompare (testCountSpy, "count", 1) + compare (routeModel.count, 1) + // the test plugin echoes waypoints back as the path of the route: + compare (routeQuery.waypoints.length, 5) + compare (routeModel.get(0).path.length, 5) + compare (routeModel.get(0).path[0].latitude, routeQuery.waypoints[0].latitude) + // check reset() functionality + routeModel.reset() + tryCompare (testRoutesSpy, "count", 2) // 5 sec + tryCompare (testCountSpy, "count", 2) + compare (routeModel.count, 0) + + // delayed responses + compare (testRoutesSlackSpy.count, 0) + compare (routeModelSlack.errorString, "") + compare (routeModel.error, RouteModel.NoError) + compare (testCountSlackSpy.count, 0) + compare (routeModelSlack.count, 0) + routeModelSlack.update() + wait (100) + compare (testRoutesSlackSpy.count, 0) + compare (testCountSlackSpy.count, 0) + tryCompare(testRoutesSlackSpy, "count", 1) + compare (testCountSlackSpy.count, 1) + compare(routeModelSlack.count, 1) + compare (routeModelSlack.get(0).path.length, 5) + compare (routeModelSlack.get(0).path[0].latitude, routeQuery.waypoints[0].latitude) + + // Frequent updates, previous requests are aborted + routeModelSlack.reset() + testRoutesSlackSpy.clear() + testCountSlackSpy.clear() + routeModelSlack.update() + wait (100) + compare(testRoutesSlackSpy.count, 0) + compare(testCountSlackSpy.count, 0) + routeModelSlack.update() + wait (100) + compare(testRoutesSlackSpy.count, 0) + compare(testCountSlackSpy.count, 0) + routeModelSlack.update() + wait (100) + compare(testRoutesSlackSpy.count, 0) + compare(testCountSlackSpy.count, 0) + routeModelSlack.update() + wait (100) + compare(testRoutesSlackSpy.count, 0) + compare(testCountSlackSpy.count, 0) + tryCompare(testRoutesSlackSpy, "count", 1) + compare(testCountSlackSpy.count, 1) + compare(routeModelSlack.count, 1) + + // Autoupdate + automaticRoutesSpy.clear(); + filledRouteQuery.numberAlternativeRoutes = 1 // 'altroutes - 70' is the echoed errorcode + tryCompare (automaticRoutesSpy, "count", 1) // 5 sec + compare(routeModelAutomatic.count, 1) // There should be a route already + compare (routeModelAutomatic.get(0).path.length, 5) + compare (routeModelAutomatic.get(0).path[0].latitude, filledRouteQuery.waypoints[0].latitude) + + // Remove a waypoint and check that autoupdate works + filledRouteQuery.removeWaypoint(fcoordinate2) + tryCompare (automaticRoutesSpy, "count", 2) + compare (routeModelAutomatic.get(0).path.length, 4) + compare (routeModelAutomatic.get(0).path[0].latitude, fcoordinate1.latitude) + + // Add a waypoint and check that autoupdate works + filledRouteQuery.addWaypoint(fcoordinate2); + tryCompare (automaticRoutesSpy, "count", 3) + compare(routeModelAutomatic.count, 1); + compare(routeModelAutomatic.get(0).path.length, 5); + compare(routeModelAutomatic.get(0).path[0].latitude, filledRouteQuery.waypoints[0].latitude); + + // Change contents of a coordinate and check that autoupdate works + filledRouteQuery.waypoints = [ + { latitude: fcoordinate1.latitude + 1, longitude: fcoordinate1.longitude }, + { latitude: 61, longitude: 62 }, + { latitude: 63, longitude: 64 }, + { latitude: 65, longitude: 66 }, + { latitude: 67, longitude: 68 } + ]; + tryCompare (automaticRoutesSpy, "count", 4) + compare(routeModelAutomatic.get(0).path[0].latitude, fcoordinate1.latitude + 1) // new value should be echoed + + // Change query + routeModelAutomatic.query = filledRouteQuery2 + filledRouteQuery2.numberAlternativeRoutes = 3 + tryCompare (automaticRoutesSpy, "count", 5) + compare (routeModelAutomatic.get(0).path.length, 3) + + // Verify that the old query is disconnected internally ie. does not trigger update + filledRouteQuery.waypoints = [ + { latitude: fcoordinate1.latitude + 2, longitude: fcoordinate1.longitude }, + { latitude: 61, longitude: 62 }, + { latitude: 63, longitude: 64 }, + { latitude: 65, longitude: 66 }, + { latitude: 67, longitude: 68 } + ]; + wait(800) // wait to hope no further updates comes through + compare (automaticRoutesSpy.count, 5) + compare(routeModelAutomatic.get(0).path.length, 3); + } + + function test_route_query_handles_destroyed_qml_objects() { + var coordinate = QtPositioning.coordinate(11, 52); + routeQuery.addWaypoint(coordinate); + wait(300); + routeQuery.clearWaypoints(); + } + } +} + + + + diff --git a/tests/auto/declarative_core/tst_supplier.qml b/tests/auto/declarative_core/tst_supplier.qml new file mode 100644 index 0000000..3fcb0d1 --- /dev/null +++ b/tests/auto/declarative_core/tst_supplier.qml @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "Supplier" + + Supplier { id: emptySupplier } + + function test_empty() { + compare(emptySupplier.supplierId, ""); + compare(emptySupplier.name, ""); + compare(emptySupplier.url, ""); + verify(emptySupplier.icon); + } + + Supplier { + id: qmlSupplier + + supplierId: "test-supplier-id" + name: "Test Supplier" + url: "http://example.com/test-supplier-id" + + icon: Icon { + Component.onCompleted: { + parameters.singleUrl = "http://example.com/icons/test-supplier.png" + } + } + } + + function test_qmlConstructedSupplier() { + compare(qmlSupplier.supplierId, "test-supplier-id"); + compare(qmlSupplier.name, "Test Supplier"); + compare(qmlSupplier.url, "http://example.com/test-supplier-id"); + verify(qmlSupplier.icon); + compare(qmlSupplier.icon.parameters.singleUrl, "http://example.com/icons/test-supplier.png"); + } + + Supplier { + id: testSupplier + } + + Plugin { + id: testPlugin + name: "qmlgeo.test.plugin" + allowExperimental: true + } + + Plugin { + id: invalidPlugin + } + + Icon { + id: testIcon + } + + function test_setAndGet_data() { + return [ + { tag: "name", property: "name", signal: "nameChanged", value: "Test Supplier", reset: "" }, + { tag: "supplierId", property: "supplierId", signal: "supplierIdChanged", value: "test-supplier-id-1", reset: "" }, + { tag: "url", property: "url", signal: "urlChanged", value: "http://example.com/test-supplier-id-1", reset: "" }, + { tag: "icon", property: "icon", signal: "iconChanged", value: testIcon } + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testSupplier, data); + } +} diff --git a/tests/auto/declarative_core/tst_user.qml b/tests/auto/declarative_core/tst_user.qml new file mode 100644 index 0000000..1453c41 --- /dev/null +++ b/tests/auto/declarative_core/tst_user.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtTest 1.0 +import QtLocation 5.3 +import "utils.js" as Utils + +TestCase { + id: testCase + + name: "User" + + User { id: emptyUser } + + function test_empty() { + compare(emptyUser.userId, ""); + compare(emptyUser.name, ""); + } + + User { + id: qmlUser + + userId: "testuser" + name: "Test User" + } + + function test_qmlConstructedUser() { + compare(qmlUser.userId, "testuser"); + compare(qmlUser.name, "Test User"); + } + + User { + id: testUser + } + + function test_setAndGet_data() { + return [ + { tag: "userId", property: "userId", signal: "userIdChanged", value: "testuser", reset: "" }, + { tag: "name", property: "name", signal: "nameChanged", value: "Test User", reset: "" }, + ]; + } + + function test_setAndGet(data) { + Utils.testObjectProperties(testCase, testUser, data); + } +} diff --git a/tests/auto/declarative_core/utils.js b/tests/auto/declarative_core/utils.js new file mode 100644 index 0000000..5370bab --- /dev/null +++ b/tests/auto/declarative_core/utils.js @@ -0,0 +1,182 @@ +.pragma library + +function compareArray(a, b) { + if (a.length !== b.length) + return false; + + for (var i = 0; i < a.length; ++i) { + var aMatched = false; + var bMatched = false; + + for (var j = 0; j < b.length; ++j) { + if (a[i] === b[j]) + aMatched = true; + if (b[i] === a[j]) + bMatched = true; + if (aMatched && bMatched) + break; + } + + if (!aMatched || !bMatched) + return false; + } + + return true; +} + +function testObjectProperties(testCase, testObject, data) { + var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = testObject; + signalSpy.signalName = data.signal; + + // set property to something new + testObject[data.property] = data.value; + if (data.array) { + if (data.expectedValue) { + testCase.verify(compareArray(testObject[data.property], data.expectedValue)); + testCase.compare(signalSpy.count, 1 + data.expectedValue.length); + } else { + testCase.verify(compareArray(testObject[data.property], data.value)); + testCase.compare(signalSpy.count, 1 + data.value.length); + } + + } else { + testCase.compare(testObject[data.property], data.value); + testCase.compare(signalSpy.count, 1); + } + + signalSpy.clear(); + + // set property to same value + testObject[data.property] = data.value; + if (data.array) { + if (data.expectedValue) { + testCase.verify(compareArray(testObject[data.property], data.expectedValue)); + testCase.compare(signalSpy.count, 1 + data.expectedValue.length); + } else { + testCase.verify(compareArray(testObject[data.property], data.value)); + testCase.compare(signalSpy.count, 1 + data.value.length); + } + + } else { + testCase.compare(testObject[data.property], data.value); + testCase.compare(signalSpy.count, 0); + } + + signalSpy.clear(); + + // reset property + if (data.reset === undefined) { + testObject[data.property] = null; + testCase.compare(testObject[data.property], null); + } else { + testObject[data.property] = data.reset; + if (data.array) + testCase.verify(compareArray(testObject[data.property], data.reset)); + else + testCase.compare(testObject[data.property], data.reset); + } + testCase.compare(signalSpy.count, 1); + signalSpy.destroy(); +} + +function compareObj(testCase, obj1, obj2) { + for (var propertyName in obj2) { + if (obj1[propertyName] !== undefined) { + if (propertyName === "dateTime" && isNaN(obj2["dateTime"].getTime())) + testCase.verify(isNaN(obj1["dateTime"].getTime())); + else + testCase.compare(obj1[propertyName], obj2[propertyName]) + } + } +} + +function testConsecutiveFetch(testCase, model, place, expectedValues, data) +{ + var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); + signalSpy.target = model; + signalSpy.signalName ="totalCountChanged"; + + var visDataModel = Qt.createQmlObject('import QtQuick 2.0; ' + + 'VisualDataModel{ delegate: Text{} }', + testCase, "dataModel"); + visDataModel.model = model; + + //check that initial values are as expected + testCase.compare(model.totalCount, -1); + testCase.compare(model.place, null); + testCase.compare(visDataModel.items.count, 0); + + //perform an initial fetch with the default batch size + model.batchSize = data.batchSize + model.place = place; + testCase.tryCompare(signalSpy, "count", 1); + signalSpy.clear(); + + var totalCount = model.totalCount; + testCase.compare(totalCount, 5); + testCase.compare(visDataModel.items.count, Math.min(data.batchSize, totalCount)); + + compareObj(testCase, visDataModel.items.get(0).model, expectedValues[0]); + + //fetch remaining items, in batchSize batches + while (visDataModel.items.count < totalCount) { + var startIndex = visDataModel.items.count + + //'creating' the last item will trigger a fetch + visDataModel.items.create(visDataModel.items.count - 1); + + testCase.tryCompare(visDataModel.items, "count", Math.min(totalCount, startIndex + data.batchSize)); + testCase.compare(signalSpy.count, 0); + testCase.compare(model.totalCount, totalCount); + + for (var i = startIndex; i < Math.min(totalCount, startIndex + data.batchSize); ++i) + compareObj(testCase, visDataModel.items.get(i).model, expectedValues[i]); + } + + visDataModel.destroy(); + signalSpy.destroy(); +} + +function testReset(testCase, model, place) +{ + var dataModel = Qt.createQmlObject('import QtQuick 2.0; ' + + 'VisualDataModel{ delegate: Text{} }', + testCase, "dataModel"); + + dataModel.model = model; + model.place = place; + testCase.wait(1); + testCase.verify(model.totalCount > 0); + testCase.verify(dataModel.items.count > 0); + + model.place = null; + testCase.tryCompare(model, "totalCount", -1); + testCase.compare(dataModel.items.count, 0); + + dataModel.destroy(); +} + +function testFetch(testCase, data) +{ + var model = data.model; + var visDataModel = Qt.createQmlObject('import QtQuick 2.0; ' + + 'VisualDataModel{ delegate: Text{} }', + testCase, "dataModel"); + visDataModel.model = model + + var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', + testCase, "SignalSpy"); + signalSpy.target = model; + signalSpy.signalName ="totalCountChanged"; + + model.batchSize = data.batchSize; + model.place = data.place; + testCase.tryCompare(signalSpy, "count", 1); + signalSpy.clear(); + testCase.compare(model.totalCount, data.expectedTotalCount); + testCase.compare(visDataModel.items.count, data.expectedCount); + + visDataModel.destroy(); + signalSpy.destroy(); +} diff --git a/tests/auto/declarative_geoshape/declarative_geoshape.pro b/tests/auto/declarative_geoshape/declarative_geoshape.pro new file mode 100644 index 0000000..aa6647f --- /dev/null +++ b/tests/auto/declarative_geoshape/declarative_geoshape.pro @@ -0,0 +1,11 @@ +# QML tests in this directory must not depend on an OpenGL context. + +TEMPLATE = app +TARGET = tst_declarative_geoshape +CONFIG += qmltestcase +SOURCES += main.cpp + +QT += positioning quick + +OTHER_FILES = *.qml +TESTDATA = $$OTHER_FILES diff --git a/tests/auto/declarative_geoshape/main.cpp b/tests/auto/declarative_geoshape/main.cpp new file mode 100644 index 0000000..ffc9445 --- /dev/null +++ b/tests/auto/declarative_geoshape/main.cpp @@ -0,0 +1,30 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +QUICK_TEST_MAIN(declarative_geoshape) diff --git a/tests/auto/declarative_geoshape/tst_locationsingleton.qml b/tests/auto/declarative_geoshape/tst_locationsingleton.qml new file mode 100644 index 0000000..e38e4ec --- /dev/null +++ b/tests/auto/declarative_geoshape/tst_locationsingleton.qml @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtPositioning 5.2 +import QtLocation 5.5 + +Item { + id: testCase + + property variant coordinate1: QtPositioning.coordinate(1, 1) + property variant coordinate2: QtPositioning.coordinate(2, 2) + property variant coordinate3: QtPositioning.coordinate(80, 80) + + property variant emptyCircle: QtPositioning.circle() + property variant circle1: QtPositioning.circle(coordinate1, 200000) + + SignalSpy { id: circleChangedSpy; target: testCase; signalName: "emptyCircleChanged" } + + TestCase { + name: "Bounding circle" + function test_circle_defaults_and_setters() { + circleChangedSpy.clear(); + compare (emptyCircle.radius, -1) + compare (circle1.radius, 200000) + + emptyCircle.radius = 200 + compare(circleChangedSpy.count, 1); + emptyCircle.radius = 200; + compare(circleChangedSpy.count, 1); + + emptyCircle.center = coordinate1; + compare(circleChangedSpy.count, 2); + emptyCircle.center = coordinate1 + compare(circleChangedSpy.count, 2); + emptyCircle.center = coordinate2 + compare(circleChangedSpy.count, 3); + + emptyCircle.center = coordinate1 + emptyCircle.radius = 200000 + + compare(emptyCircle.contains(coordinate1), true); + compare(emptyCircle.contains(coordinate2), true); + compare(emptyCircle.contains(coordinate3), false); + } + } + + // coordinate unit square + property variant bl: QtPositioning.coordinate(0, 0) + property variant tl: QtPositioning.coordinate(1, 0) + property variant tr: QtPositioning.coordinate(1, 1) + property variant br: QtPositioning.coordinate(0, 1) + property variant ntr: QtPositioning.coordinate(3, 3) + + property variant invalid: QtPositioning.coordinate(100, 190) + property variant inside: QtPositioning.coordinate(0.5, 0.5) + property variant outside: QtPositioning.coordinate(2, 2) + + property variant box: QtPositioning.rectangle(tl, br) + + property variant coordinates: [bl, tl, tr, br] + property variant coordinates2: [bl, tl, tr, br, ntr] + property variant coordinates3: [tr] + property variant coordinates4: [invalid] + property variant coordinates5: [] + + property variant listBox: QtPositioning.rectangle(coordinates) + property variant listBox2: QtPositioning.rectangle(coordinates2) + property variant listBox3: QtPositioning.rectangle(coordinates3) + property variant listBox4: QtPositioning.rectangle(coordinates4) + property variant listBox5: QtPositioning.rectangle(coordinates5) + + property variant widthBox: QtPositioning.rectangle(inside, 1, 1); + + // C++ auto test exists for basics of bounding box, testing here + // only added functionality + TestCase { + name: "Bounding box" + function test_box_defaults_and_setters() { + compare (box.bottomRight.longitude, br.longitude) // sanity + compare (box.contains(bl), true) + compare (box.contains(inside), true) + compare (box.contains(outside), false) + box.topRight = ntr + compare (box.contains(outside), true) + + compare (listBox.isValid, true) + compare (listBox.contains(outside), false) + compare (listBox2.contains(outside), true) + compare (listBox3.isValid, true) + compare (listBox3.isEmpty, true) + compare (listBox4.isValid, false) + compare (listBox5.isValid, false) + + compare (widthBox.contains(inside), true) + compare (widthBox.contains(outside), false) + } + } + + TestCase { + name: "Shape" + + function test_shape_comparison_data() { + return [ + { tag: "invalid shape", shape1: QtPositioning.shape(), shape2: QtPositioning.shape(), result: true }, + { tag: "box equal", shape1: box, shape2: QtPositioning.rectangle(tl, br), result: true }, + { tag: "box not equal", shape1: box, shape2: QtPositioning.rectangle([inside, outside]), result: false }, + { tag: "box invalid shape", rect1: box, shape2: QtPositioning.shape(), result: false }, + { tag: "invalid rectangle", shape1: QtPositioning.rectangle(), shape2: QtPositioning.rectangle(), result: true }, + { tag: "invalid rectangle2", shape1: QtPositioning.rectangle(), shape2: QtPositioning.shape(), result: false }, + { tag: "circle1 equal", shape1: circle1, shape2: QtPositioning.circle(coordinate1, 200000), result: true }, + { tag: "circle1 not equal", shape1: circle1, shape2: QtPositioning.circle(coordinate2, 2000), result: false }, + { tag: "circle1 invalid shape", shape1: circle1, shape2: QtPositioning.shape(), result: false }, + { tag: "invalid circle", shape1: QtPositioning.circle(), shape2: QtPositioning.circle(), result: true }, + { tag: "invalid circle2", shape1: QtPositioning.circle(), shape2: QtPositioning.shape(), result: false } + ] + } + + function test_shape_comparison(data) { + compare(data.shape1 === data.shape2, data.result) + compare(data.shape1 !== data.shape2, !data.result) + compare(data.shape1 == data.shape2, data.result) + compare(data.shape1 != data.shape2, !data.result) + } + } + + TestCase { + name: "Conversions" + + function test_shape_circle_conversions() { + var circle = QtPositioning.shapeToCircle(QtPositioning.shape()) + verify(!circle.isValid) + circle = QtPositioning.shapeToCircle(QtPositioning.circle()) + verify(!circle.isValid) + circle = QtPositioning.shapeToCircle(QtPositioning.circle(tl, 10000)) + verify(circle.isValid) + compare(circle.center, tl) + compare(circle.radius, 10000) + circle = QtPositioning.shapeToCircle(QtPositioning.rectangle()) + verify(!circle.isValid) + circle = QtPositioning.shapeToCircle(QtPositioning.rectangle(tl, br)) + verify(!circle.isValid) + circle = QtPositioning.shapeToCircle(listBox) + verify(!circle.isValid) + } + + function test_shape_rectangle_conversions() { + var rectangle = QtPositioning.shapeToRectangle(QtPositioning.shape()) + verify(!rectangle.isValid) + rectangle = QtPositioning.shapeToRectangle(QtPositioning.circle()) + verify(!rectangle.isValid) + rectangle = QtPositioning.shapeToRectangle(QtPositioning.circle(tl, 10000)) + verify(!rectangle.isValid) + rectangle = QtPositioning.shapeToRectangle(QtPositioning.rectangle()) + verify(!rectangle.isValid) + rectangle = QtPositioning.shapeToRectangle(QtPositioning.rectangle(tl, br)) + verify(rectangle.isValid) + compare(rectangle.topLeft, tl) + compare(rectangle.bottomRight, br) + rectangle = QtPositioning.shapeToRectangle(listBox) + verify(rectangle.isValid) + } + } + + + MapPolyline { + id: mapPolyline + path: [ + { latitude: -27, longitude: 153.0 }, + { latitude: -27, longitude: 154.1 }, + { latitude: -28, longitude: 153.5 }, + { latitude: -29, longitude: 153.5 } + ] + } + + TestCase { + name: "MapPolyline path" + function test_path_operations() { + compare(mapPolyline.path[1].latitude, -27) + compare(mapPolyline.path[1].longitude, 154.1) + compare(mapPolyline.coordinateAt(1), QtPositioning.coordinate(-27, 154.1)) + compare(mapPolyline.path.length, mapPolyline.pathLength()) + + mapPolyline.removeCoordinate(1); + compare(mapPolyline.path[1].latitude, -28) + compare(mapPolyline.path[1].longitude, 153.5) + compare(mapPolyline.coordinateAt(1), QtPositioning.coordinate(-28, 153.5)) + compare(mapPolyline.path.length, mapPolyline.pathLength()) + + mapPolyline.addCoordinate(QtPositioning.coordinate(30, 153.1)) + compare(mapPolyline.path[mapPolyline.path.length-1].latitude, 30) + compare(mapPolyline.path[mapPolyline.path.length-1].longitude, 153.1) + compare(mapPolyline.containsCoordinate(QtPositioning.coordinate(30, 153.1)), true) + compare(mapPolyline.path.length, mapPolyline.pathLength()) + + mapPolyline.removeCoordinate(QtPositioning.coordinate(30, 153.1)) + compare(mapPolyline.path[mapPolyline.path.length-1].latitude, -29) + compare(mapPolyline.path[mapPolyline.path.length-1].longitude, 153.5) + compare(mapPolyline.containsCoordinate(QtPositioning.coordinate(30, 153.1)), false) + compare(mapPolyline.path.length, mapPolyline.pathLength()) + + mapPolyline.insertCoordinate(2, QtPositioning.coordinate(35, 153.1)) + compare(mapPolyline.path[2].latitude, 35) + compare(mapPolyline.path[2].longitude, 153.1) + compare(mapPolyline.containsCoordinate(QtPositioning.coordinate(35, 153.1)), true) + compare(mapPolyline.path.length, mapPolyline.pathLength()) + + mapPolyline.replaceCoordinate(2, QtPositioning.coordinate(45, 150.1)) + compare(mapPolyline.path[2].latitude, 45) + compare(mapPolyline.path[2].longitude, 150.1) + compare(mapPolyline.containsCoordinate(QtPositioning.coordinate(35, 153.1)), false) + compare(mapPolyline.containsCoordinate(QtPositioning.coordinate(45, 150.1)), true) + compare(mapPolyline.path.length, mapPolyline.pathLength()) + + mapPolyline.insertCoordinate(2, QtPositioning.coordinate(35, 153.1)) + compare(mapPolyline.coordinateAt(2).latitude, 35) + compare(mapPolyline.coordinateAt(2).longitude, 153.1) + compare(mapPolyline.containsCoordinate(QtPositioning.coordinate(35, 153.1)), true) + compare(mapPolyline.path.length, mapPolyline.pathLength()) + } + } +} diff --git a/tests/auto/declarative_ui/declarative_ui.pro b/tests/auto/declarative_ui/declarative_ui.pro new file mode 100644 index 0000000..d3a2f08 --- /dev/null +++ b/tests/auto/declarative_ui/declarative_ui.pro @@ -0,0 +1,18 @@ +# QML tests in this directory depend on a Qt platform plugin that supports OpenGL. +# QML tests that do not require an OpenGL context should go in ../declarative_core. + +TEMPLATE = app +TARGET = tst_declarative_ui +!no_ui_tests:CONFIG += qmltestcase +SOURCES += main.cpp + +CONFIG -= app_bundle + +QT += location quick + +OTHER_FILES = *.qml +TESTDATA = $$OTHER_FILES + + +# Import path used by 'make check' since CI doesn't install test imports +IMPORTPATH = $$OUT_PWD/../../../qml diff --git a/tests/auto/declarative_ui/main.cpp b/tests/auto/declarative_ui/main.cpp new file mode 100644 index 0000000..8a12f41 --- /dev/null +++ b/tests/auto/declarative_ui/main.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +static void initializeLibraryPath() +{ + // Set custom path since CI doesn't install test plugins +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif +} + +Q_COREAPP_STARTUP_FUNCTION(initializeLibraryPath) + +QUICK_TEST_MAIN(declarative_ui) diff --git a/tests/auto/declarative_ui/tst_map.qml b/tests/auto/declarative_ui/tst_map.qml new file mode 100644 index 0000000..5f02962 --- /dev/null +++ b/tests/auto/declarative_ui/tst_map.qml @@ -0,0 +1,343 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.6 +import QtPositioning 5.5 + +Item { + width:100 + height:100 + // General-purpose elements for the test: + Plugin { id: testPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true } + Plugin { id: testPlugin2; name: "gmlgeo.test.plugin"; allowExperimental: true } + Plugin { id: herePlugin; name: "here"; + parameters: [ + PluginParameter { + name: "here.app_id" + value: "stub" + }, + PluginParameter { + name: "here.token" + value: "stub" + } + ] + } + + property variant coordinate1: QtPositioning.coordinate(10, 11) + property variant coordinate2: QtPositioning.coordinate(12, 13) + property variant coordinate3: QtPositioning.coordinate(50, 50, 0) + property variant coordinate4: QtPositioning.coordinate(80, 80, 0) + property variant coordinate5: QtPositioning.coordinate(20, 180) + property variant invalidCoordinate: QtPositioning.coordinate() + property variant altitudelessCoordinate: QtPositioning.coordinate(50, 50) + + Map { id: mapZoomOnCompleted; width: 200; height: 200; + zoomLevel: 3; center: coordinate1; plugin: testPlugin; + Component.onCompleted: { + zoomLevel = 7 + } + } + SignalSpy {id: mapZoomSpy; target: mapZoomOnCompleted; signalName: 'zoomLevelChanged'} + + Map { id: mapZoomDefault; width: 200; height: 200; + center: coordinate1; plugin: testPlugin; } + + Map { id: mapZoomUserInit; width: 210; height: 210; + zoomLevel: 4; center: coordinate1; plugin: testPlugin; + Component.onCompleted: { + console.log("mapZoomUserInit completed") + } + } + + Map {id: map; plugin: testPlugin; center: coordinate1; width: 100; height: 100} + SignalSpy {id: mapCenterSpy; target: map; signalName: 'centerChanged'} + + Map {id: coordinateMap; plugin: herePlugin; center: coordinate3; + width: 1000; height: 1000; zoomLevel: 15 } + + + + + TestCase { + when: windowShown + name: "MapProperties" + + function fuzzy_compare(val, ref) { + var tolerance = 0.01; + if ((val > ref - tolerance) && (val < ref + tolerance)) + return true; + console.log('map fuzzy cmp returns false for value, ref: ' + val + ', ' + ref) + return false; + } + + function init() { + mapCenterSpy.clear(); + } + + function test_map_center() { + // coordinate is set at map element declaration + compare(map.center.latitude, 10) + compare(map.center.longitude, 11) + + // change center and its values + mapCenterSpy.clear(); + compare(mapCenterSpy.count, 0) + map.center = coordinate2 + compare(mapCenterSpy.count, 1) + map.center = coordinate2 + compare(mapCenterSpy.count, 1) + + // change center to dateline + mapCenterSpy.clear() + compare(mapCenterSpy.count, 0) + map.center = coordinate5 + compare(mapCenterSpy.count, 1) + compare(map.center, coordinate5) + + map.center = coordinate2 + + verify(isNaN(map.center.altitude)); + compare(map.center.longitude, 13) + compare(map.center.latitude, 12) + } + + function test_map_clamp() + { + //valid + map.center = QtPositioning.coordinate(10.0, 20.5, 30.8) + map.zoomLevel = 2.0 + + compare(map.center.latitude, 10) + compare(map.center.longitude, 20.5) + compare(map.center.altitude, 30.8) + + //negative values + map.center = QtPositioning.coordinate(-50, -20, 100) + map.zoomLevel = 1.0 + + compare(map.center.latitude, -50) + compare(map.center.longitude, -20) + compare(map.center.altitude, 100) + + //clamped center negative + map.center = QtPositioning.coordinate(-89, -45, 0) + map.zoomLevel = 1.0 + + fuzzyCompare(map.center.latitude, -80.8728, 0.001) + compare(map.center.longitude, -45) + compare(map.center.altitude, 0) + + //clamped center positive + map.center = QtPositioning.coordinate(86, 38, 0) + map.zoomLevel = 1.0 + + fuzzyCompare(map.center.latitude, 80.8728, 0.001) + compare(map.center.longitude, 38) + compare(map.center.altitude, 0) + } + + function test_zoom_limits() + { + map.center.latitude = 30 + map.center.longitude = 60 + map.zoomLevel = 4 + + //initial plugin values + compare(map.minimumZoomLevel, 0) + compare(map.maximumZoomLevel, 20) + + //Higher min level than curr zoom, should change curr zoom + map.minimumZoomLevel = 5 + map.maximumZoomLevel = 18 + compare(map.zoomLevel, 5) + compare(map.minimumZoomLevel, 5) + compare(map.maximumZoomLevel, 18) + + //Trying to set higher than max, max should be set. + map.maximumZoomLevel = 21 + compare(map.minimumZoomLevel, 5) + compare(map.maximumZoomLevel, 20) + + //Negative values should be ignored + map.minimumZoomLevel = -1 + map.maximumZoomLevel = -2 + compare(map.minimumZoomLevel, 5) + compare(map.maximumZoomLevel, 20) + + //Max limit lower than curr zoom, should change curr zoom + map.zoomLevel = 18 + map.maximumZoomLevel = 16 + compare(map.zoomLevel, 16) + + //reseting default + map.minimumZoomLevel = 0 + map.maximumZoomLevel = 20 + compare(map.minimumZoomLevel, 0) + compare(map.maximumZoomLevel, 20) + } + + function test_zoom() + { + wait(1000) + compare(mapZoomOnCompleted.zoomLevel, 7) + compare(mapZoomDefault.zoomLevel, 8) + compare(mapZoomUserInit.zoomLevel, 4) + + mapZoomSpy.clear() + mapZoomOnCompleted.zoomLevel = 6 + tryCompare(mapZoomSpy, "count", 1) + } + + function test_pan() + { + map.center.latitude = 30 + map.center.longitude = 60 + map.zoomLevel = 4 + mapCenterSpy.clear(); + + // up left + tryCompare(mapCenterSpy, "count", 0) + map.pan(-20,-20) + tryCompare(mapCenterSpy, "count", 1) + verify(map.center.latitude > 30) + verify(map.center.longitude < 60) + map.center.latitude = 30 + map.center.longitude = 60 + mapCenterSpy.clear() + // up + map.pan(0,-20) + tryCompare(mapCenterSpy, "count", 1) + verify(map.center.latitude > 30) + compare(map.center.longitude, 60) + map.center.latitude = 30 + map.center.longitude = 60 + mapCenterSpy.clear() + // up right + tryCompare(mapCenterSpy, "count", 0) + map.pan(20,-20) + tryCompare(mapCenterSpy, "count", 1) + verify(map.center.latitude > 30) + verify(map.center.longitude > 60) + map.center.latitude = 30 + map.center.longitude = 60 + mapCenterSpy.clear() + // left + map.pan(-20,0) + tryCompare(mapCenterSpy, "count", 1) + verify (fuzzy_compare(map.center.latitude, 30)) + verify(map.center.longitude < 60) + map.center.latitude = 30 + map.center.longitude = 60 + mapCenterSpy.clear() + // center + map.pan(0,0) + tryCompare(mapCenterSpy, "count", 0) + compare(map.center.latitude, 30) + compare(map.center.longitude, 60) + map.center.latitude = 30 + map.center.longitude = 60 + mapCenterSpy.clear() + // right + map.pan(20,0) + tryCompare(mapCenterSpy, "count", 1) + verify (fuzzy_compare(map.center.latitude, 30)) + verify(map.center.longitude > 60) + map.center.latitude = 30 + map.center.longitude = 60 + mapCenterSpy.clear() + // down left + map.pan(-20,20) + tryCompare(mapCenterSpy, "count", 1) + verify (map.center.latitude < 30 ) + verify (map.center.longitude < 60 ) + map.center.latitude = 30 + map.center.longitude = 60 + mapCenterSpy.clear() + // down + map.pan(0,20) + tryCompare(mapCenterSpy, "count", 1) + verify (map.center.latitude < 30 ) + verify (fuzzy_compare(map.center.longitude, 60)) + map.center.latitude = 30 + map.center.longitude = 60 + mapCenterSpy.clear() + // down right + map.pan(20,20) + tryCompare(mapCenterSpy, "count", 1) + verify (map.center.latitude < 30 ) + verify (map.center.longitude > 60 ) + map.center.latitude = 30 + map.center.longitude = 60 + mapCenterSpy.clear() + } + + function test_coordinate_conversion() + { + wait(1000) + mapCenterSpy.clear(); + compare(coordinateMap.center.latitude, 50) + compare(coordinateMap.center.longitude, 50) + // valid to screen position + var point = coordinateMap.fromCoordinate(coordinateMap.center) + verify (point.x > 495 && point.x < 505) + verify (point.y > 495 && point.y < 505) + // valid coordinate without altitude + point = coordinateMap.fromCoordinate(altitudelessCoordinate) + verify (point.x > 495 && point.x < 505) + verify (point.y > 495 && point.y < 505) + // out of map area in view + //var oldZoomLevel = coordinateMap.zoomLevel + //coordinateMap.zoomLevel = 8 + point = coordinateMap.fromCoordinate(coordinate4) + verify(isNaN(point.x)) + verify(isNaN(point.y)) + //coordinateMap.zoomLevel = oldZoomLevel + // invalid coordinates + point = coordinateMap.fromCoordinate(invalidCoordinate) + verify(isNaN(point.x)) + verify(isNaN(point.y)) + point = coordinateMap.fromCoordinate(null) + verify(isNaN(point.x)) + verify(isNaN(point.y)) + // valid point to coordinate + var coord = coordinateMap.toCoordinate(Qt.point(500,500)) + verify(coord.latitude > 49 && coord.latitude < 51) + verify(coord.longitude > 49 && coord.longitude < 51) + // beyond + coord = coordinateMap.toCoordinate(Qt.point(2000, 2000)) + verify(isNaN(coord.latitude)) + verify(isNaN(coord.longitde)) + // invalid + coord = coordinateMap.toCoordinate(Qt.point(-5, -6)) + verify(isNaN(coord.latitude)) + verify(isNaN(coord.longitde)) + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_coordinateanimation.qml b/tests/auto/declarative_ui/tst_map_coordinateanimation.qml new file mode 100644 index 0000000..d9b71ed --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_coordinateanimation.qml @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.6 +import QtPositioning 5.5 + +Item { + width:100 + height:100 + // General-purpose elements for the test: + Plugin { id: testPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true } + + + property var coordinateList: [] + property int coordinateCount: 0 + property int animationDuration: 100 + + Map {id: map + plugin: testPlugin + width: 100 + height: 100 + + Behavior on center { + id: centerBehavior + enabled: false + CoordinateAnimation { + id: coordinateAnimation + duration: animationDuration + } + } + + onCenterChanged: { + if (!coordinateList) { + coordinateList = [] + } + + coordinateList[coordinateCount] = {'latitude': center.latitude, 'longitude': center.longitude} + coordinateCount++ + } + } + + function toMercator(coord) { + var pi = Math.PI + var lon = coord.longitude / 360.0 + 0.5; + + var lat = coord.latitude; + lat = 0.5 - (Math.log(Math.tan((pi / 4.0) + (pi / 2.0) * lat / 180.0)) / pi) / 2.0; + lat = Math.max(0.0, lat); + lat = Math.min(1.0, lat); + + return {'latitude': lat, 'longitude': lon}; + } + + TestCase { + when: windowShown + name: "CoordinateAnimation" + + function test_coordinate_animation() { + + coordinateList = [] + coordinateCount = 0 + + var from = {'latitude': 58.0, 'longitude': 12.0} + var to = {'latitude': 62.0, 'longitude': 24.0} + + + var fromMerc = toMercator(from) + var toMerc = toMercator(to) + + var delta = (toMerc.latitude - fromMerc.latitude) / (toMerc.longitude - fromMerc.longitude) + + // Set from coordinate with animation disabled. + map.center = QtPositioning.coordinate(from.latitude, from.longitude) + + // Expect only one update + compare(coordinateList.length, 1) + + // Set to coordinate with animation enabled + centerBehavior.enabled = true + map.center = QtPositioning.coordinate(to.latitude, to.longitude) + wait(animationDuration) + tryCompare(coordinateAnimation,"running",false) + + //check correct start position + compare(coordinateList[0].latitude, from.latitude) + compare(coordinateList[0].longitude, from.longitude) + + //check correct end position + compare(coordinateList[coordinateList.length - 1].latitude, to.latitude) + compare(coordinateList[coordinateList.length - 1].longitude, to.longitude) + + var i + var lastLatitude + for (i in coordinateList) { + var coordinate = coordinateList[i] + var mercCoordinate = toMercator(coordinate) + + //check that coordinates from the animation is along a straight line between from and to + var estimatedLatitude = fromMerc.latitude + (mercCoordinate.longitude - fromMerc.longitude) * delta + verify(mercCoordinate.latitude - estimatedLatitude < 0.00000000001); + + //check that each step has moved in the right direction + if (lastLatitude) { + verify(coordinate.latitude > lastLatitude) + } + lastLatitude = coordinate.latitude + } + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_error.qml b/tests/auto/declarative_ui/tst_map_error.qml new file mode 100644 index 0000000..c978e0c --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_error.qml @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.6 +import QtPositioning 5.5 + +Item { + id: page + x: 0; y: 0; + width: 200 + height: 100 + property variant coordinate: QtPositioning.coordinate(20, 20) + + Plugin { + id: errorPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true + parameters: [ + PluginParameter { name: "error"; value: "1"}, + PluginParameter { name: "errorString"; value: "This error was expected. No worries !"} + ] + } + + Map { + id: map_error_plugin; + property alias mouseClickedSpy: mouseClickedSpy1 + x: 0; y: 0; width: 100; height: 100; plugin: errorPlugin; + + MouseArea { + id: mouseArea1 + objectName: "mouseArea" + x: 25; y: 25; width: 50; height: 50; + preventStealing: true + } + + SignalSpy {id: mouseClickedSpy1; target: mouseArea1; signalName: "clicked"} + } + + Map { + id: map_no_plugin; + property alias mouseClickedSpy: mouseClickedSpy2 + x: 100; y: 0; width: 100; height: 100; + + MouseArea { + id: mouseArea2 + objectName: "mouseArea" + x: 25; y: 25; width: 50; height: 50; + preventStealing: true + } + + SignalSpy {id: mouseClickedSpy2; target: mouseArea2; signalName: "clicked"} + } + + TestCase { + name: "MapErrorHandling" + when: windowShown + + function init() { + map_error_plugin.zoomLevel = 0 + map_no_plugin.zoomLevel = 0 + map_error_plugin.center = QtPositioning.coordinate(0, 0) + map_no_plugin.center = QtPositioning.coordinate(0, 0) + map_error_plugin.mouseClickedSpy.clear() + map_no_plugin.mouseClickedSpy.clear() + } + + function map_clicked(map) + { + mouseClick(map, 5, 5) + mouseClick(map, 50, 50) + mouseClick(map, 50, 50) + mouseClick(map, 50, 50) + tryCompare(map.mouseClickedSpy, "count", 3) + } + + function test_map_clicked_wiht_no_plugin() + { + map_clicked(map_no_plugin) + } + + function test_map_clicked_with_error_plugin() + { + map_clicked(map_error_plugin) + } + + function test_map_no_supportedMapTypes() + { + compare(map_no_plugin.supportedMapTypes.length , 0) + compare(map_error_plugin.supportedMapTypes.length , 0) + } + + function test_map_set_zoom_level() + { + map_no_plugin.zoomLevel = 9 + compare(map_no_plugin.zoomLevel,9) + map_error_plugin.zoomLevel = 9 + compare(map_error_plugin.zoomLevel,9) + } + + function test_map_set_center() + { + map_no_plugin.center = coordinate + verify(map_no_plugin.center === coordinate) + map_error_plugin.center = coordinate + verify(map_error_plugin.center === coordinate) + } + + function test_map_no_mapItems() + { + compare(map_no_plugin.mapItems.length , 0) + compare(map_error_plugin.mapItems.length , 0) + } + + function test_map_error() + { + compare(map_no_plugin.error , 0) + compare(map_no_plugin.errorString , "") + compare(map_error_plugin.error , 1) + compare(map_error_plugin.errorString ,"This error was expected. No worries !") + } + + function test_map_toCoordinate() + { + map_no_plugin.center = coordinate + compare(map_no_plugin.toCoordinate(50,50).isValid,false) + map_error_plugin.center = coordinate + compare(map_error_plugin.toCoordinate(50,50).isValid,false) + } + + function test_map_fromCoordinate() + { + verify(isNaN(map_error_plugin.fromCoordinate(coordinate).x)) + verify(isNaN(map_error_plugin.fromCoordinate(coordinate).y)) + verify(isNaN(map_no_plugin.fromCoordinate(coordinate).x)) + verify(isNaN(map_no_plugin.fromCoordinate(coordinate).y)) + } + + function test_map_gesture_enabled() + { + verify(map_error_plugin.gesture.enabled) + verify(map_no_plugin.gesture.enabled) + } + + function test_map_pan() + { + map_no_plugin.center = coordinate + map_no_plugin.pan(20,20) + verify(map_no_plugin.center === coordinate) + map_error_plugin.center = coordinate + map_error_plugin.pan(20,20) + verify(map_error_plugin.center === coordinate) + } + + function test_map_prefetchData() + { + map_error_plugin.prefetchData() + map_no_plugin.prefetchData() + } + + function test_map_fitViewportToMapItems() + { + map_error_plugin.fitViewportToMapItems() + map_no_plugin.fitViewportToMapItems() + } + + function test_map_setVisibleRegion() + { + map_no_plugin.visibleRegion = QtPositioning.circle(coordinate,1000) + verify(map_no_plugin.center != coordinate) + verify(map_no_plugin.visibleRegion == QtPositioning.circle(coordinate,1000)) + map_error_plugin.visibleRegion = QtPositioning.circle(coordinate,1000) + verify(map_error_plugin.center != coordinate) + verify(map_no_plugin.visibleRegion == QtPositioning.circle(coordinate,1000)) + } + + function test_map_activeMapType() + { + compare(map_no_plugin.supportedMapTypes.length, 0) + compare(map_no_plugin.activeMapType.style, MapType.NoMap) + compare(map_error_plugin.supportedMapTypes.length, 0) + compare(map_error_plugin.activeMapType.style, MapType.NoMap) + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_flick.qml b/tests/auto/declarative_ui/tst_map_flick.qml new file mode 100644 index 0000000..15f13b5 --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_flick.qml @@ -0,0 +1,347 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtTest 1.0 +import QtLocation 5.6 +import QtPositioning 5.5 + +Item { + // General-purpose elements for the test: + id: page + width: 100 + height: 100 + Plugin { id: testPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true } + + property variant coordinate: QtPositioning.coordinate(10, 11) + + MouseArea { + id: mouseAreaBottom + anchors.fill: parent + visible: false + } + + Map { + id: map + plugin: testPlugin + center: coordinate; + zoomLevel: 9; + anchors.fill: page + x:0; y:0 + + property real flickStartedLatitude + property real flickStartedLongitude + property bool disableOnPanStartedWithNoGesture: false + property bool disableOnFlickStartedWithNoGesture: false + property bool disableOnPanStartedWithDisabled: false + property bool disableOnFlickStartedWithDisabled: false + + gesture.onPanStarted: { + if (disableOnPanStartedWithNoGesture) + map.gesture.acceptedGestures = MapGestureArea.NoGesture + if (disableOnPanStartedWithDisabled) + map.gesture.enabled = false + } + gesture.onFlickStarted: { + flickStartedLatitude = map.center.latitude + flickStartedLatitude = map.center.longitude + if (disableOnFlickStartedWithNoGesture) + map.gesture.acceptedGestures = MapGestureArea.NoGesture + if (disableOnFlickStartedWithDisabled) + map.gesture.enabled = false + } + MouseArea { + id: mouseAreaTop + anchors.fill: parent + visible: false + } + } + + SignalSpy {id: centerSpy; target: map; signalName: 'centerChanged'} + SignalSpy {id: panStartedSpy; target: map.gesture; signalName: 'panStarted'} + SignalSpy {id: panFinishedSpy; target: map.gesture; signalName: 'panFinished'} + SignalSpy {id: gestureEnabledSpy; target: map.gesture; signalName: 'enabledChanged'} + SignalSpy {id: flickDecelerationSpy; target: map.gesture; signalName: 'flickDecelerationChanged'} + SignalSpy {id: flickStartedSpy; target: map.gesture; signalName: 'flickStarted'} + SignalSpy {id: flickFinishedSpy; target: map.gesture; signalName: 'flickFinished'} + SignalSpy {id: mouseAreaTopSpy; target: mouseAreaTop; signalName: 'onPressed'} + SignalSpy {id: mouseAreaBottomSpy; target: mouseAreaBottom; signalName: 'onPressed'} + + TestCase { + when: windowShown + name: "MapFlick" + + function init() + { + map.gesture.acceptedGestures = MapGestureArea.PanGesture | MapGestureArea.FlickGesture; + map.gesture.enabled = true + map.gesture.panEnabled = true + map.gesture.flickDeceleration = 500 + map.zoomLevel = 0 + map.disableOnPanStartedWithNoGesture = false + map.disableOnFlickStartedWithNoGesture = false + map.disableOnPanStartedWithDisabled = false + map.disableOnFlickStartedWithDisabled = false + centerSpy.clear() + gestureEnabledSpy.clear() + flickDecelerationSpy.clear() + panStartedSpy.clear() + panFinishedSpy.clear() + flickStartedSpy.clear() + flickFinishedSpy.clear() + mouseAreaTopSpy.clear() + mouseAreaBottomSpy.clear() + mouseAreaBottom.visible = false + mouseAreaTop.visible = false + compare(map.gesture.pinchActive, false) + compare(map.gesture.panActive, false) + } + + function initTestCase() + { + //check default values + compare(map.gesture.enabled, true) + map.gesture.enabled = false + compare(gestureEnabledSpy.count, 1) + compare(map.gesture.enabled, false) + map.gesture.enabled = false + compare(gestureEnabledSpy.count, 1) + compare(map.gesture.enabled, false) + map.gesture.enabled = true + compare(gestureEnabledSpy.count, 2) + compare(map.gesture.enabled, true) + compare(map.gesture.pinchActive, false) + compare(map.gesture.panActive, false) + verify(map.gesture.acceptedGestures & MapGestureArea.PinchGesture) + map.gesture.acceptedGestures = MapGestureArea.NoGesture + compare(map.gesture.acceptedGestures, MapGestureArea.NoGesture) + map.gesture.acceptedGestures = MapGestureArea.NoGesture + compare(map.gesture.acceptedGestures, MapGestureArea.NoGesture) + map.gesture.acceptedGestures = MapGestureArea.PinchGesture | MapGestureArea.PanGesture + compare(map.gesture.acceptedGestures, MapGestureArea.PinchGesture | MapGestureArea.PanGesture) + map.gesture.acceptedGestures = MapGestureArea.PanGesture + compare(map.gesture.acceptedGestures, MapGestureArea.PanGesture) + compare(map.gesture.flickDeceleration, 2500) + map.gesture.flickDeceleration = 2600 + compare(flickDecelerationSpy.count, 1) + compare(map.gesture.flickDeceleration, 2600) + map.gesture.flickDeceleration = 2600 + compare(flickDecelerationSpy.count, 1) + compare(map.gesture.flickDeceleration, 2600) + map.gesture.flickDeceleration = 400 // too small + compare(flickDecelerationSpy.count, 2) + compare(map.gesture.flickDeceleration, 500) // clipped to min + map.gesture.flickDeceleration = 11000 // too big + compare(flickDecelerationSpy.count, 3) + compare(map.gesture.flickDeceleration, 10000) // clipped to max + } + + function flick_down() + { + map.center.latitude = 10 + map.center.longitude = 11 + mousePress(page, 0, 50) + for (var i = 0; i < 50; i += 5) { + wait(20) + mouseMove(page, 0, (50 + i), 0, Qt.LeftButton); + } + mouseRelease(page, 0, 100) + + // order of signals is: flickStarted, either order: (flickEnded, movementEnded) + verify(map.center.latitude > 10) // latitude increases we are going 'up/north' (moving mouse down) + var moveLatitude = map.center.latitude // store lat and check that flick continues + + tryCompare(flickStartedSpy, "count", 1) + tryCompare(panFinishedSpy, "count", 1) + tryCompare(flickFinishedSpy, "count", 1) + + verify(map.center.latitude > moveLatitude) + compare(map.center.longitude, 11) // should remain the same + } + + function test_flick_down() + { + flick_down() + } + + function test_flick_down_with_filtetring() + { + mouseAreaTop.visible = true + mouseAreaBottom.visible = true + flick_down() + tryCompare(mouseAreaTopSpy, "count", 1) + tryCompare(mouseAreaBottomSpy, "count",0) + } + + function flick_up() + { + map.center.latitude = 70 + map.center.longitude = 11 + mousePress(page, 10, 95) + for (var i = 45; i > 0; i -= 5) { + wait(20) + mouseMove(page, 10, (50 + i), 0, Qt.LeftButton); + } + mouseRelease(page, 10, 50) + verify(map.center.latitude < 70) + var moveLatitude = map.center.latitude // store lat and check that flick continues + tryCompare(flickStartedSpy, "count", 1) + tryCompare(panFinishedSpy, "count", 1) + tryCompare(flickFinishedSpy, "count", 1) + verify(map.center.latitude < moveLatitude) + compare(map.center.longitude, 11) // should remain the same + } + + function test_flick_up() + { + flick_up() + } + + function test_flick_up_with_filtering() + { + mouseAreaTop.visible = true + mouseAreaBottom.visible = true + flick_up() + tryCompare(mouseAreaTopSpy, "count", 1) + tryCompare(mouseAreaBottomSpy, "count",0) + } + + function test_flick_diagonal() + { + map.center.latitude = 50 + map.center.longitude = 50 + mousePress(page, 0, 0) + for (var i = 0; i < 50; i += 5) { + wait(20) + mouseMove(page, i, i, 0, Qt.LeftButton); + } + mouseRelease(page, 50, 50) + verify(map.center.latitude > 50) + verify(map.center.longitude < 50) + var moveLatitude = map.center.latitude + var moveLongitude = map.center.longitude + tryCompare(flickStartedSpy, "count", 1) + tryCompare(panFinishedSpy, "count", 1) + tryCompare(flickFinishedSpy, "count", 1) + verify(map.center.latitude > moveLatitude) + verify(map.center.longitude < moveLongitude) + } + + function disabled_flicking() + { + map.center.latitude = 50 + map.center.longitude = 50 + mousePress(page, 0, 0) + for (var i = 0; i < 50; i += 5) { + wait(20) + mouseMove(page, i, i, 0, Qt.LeftButton); + } + mouseRelease(page, 50, 50) + compare(panStartedSpy.count, 0) + compare(panFinishedSpy.count, 0) + compare(flickStartedSpy.count, 0) + compare(flickFinishedSpy.count, 0) + } + + function test_disabled_flicking_with_nogesture() + { + map.gesture.acceptedGestures = MapGestureArea.NoGesture + } + + function test_disabled_flicking_with_disabled() + { + map.gesture.enabled = false + disabled_flicking() + } + + function disable_onFlickStarted() + { + map.center.latitude = 50 + map.center.longitude = 50 + mousePress(page, 0, 0) + for (var i = 0; i < 50; i += 5) { + wait(20) + mouseMove(page, i, i, 0, Qt.LeftButton); + } + mouseRelease(page, 50, 50) + var latitude = map.center.latitude; + var longitude = map.center.longitude + tryCompare(panStartedSpy, "count", 1) + tryCompare(flickStartedSpy, "count", 1) + verify(map.center.latitude > 50) + tryCompare(panFinishedSpy, "count", 1) + tryCompare(flickFinishedSpy, "count", 1) + // compare that flick was interrupted (less movement than without interrupting) + compare(latitude, map.center.latitude) + compare(longitude, map.center.longitude) + } + + function test_disable_onFlickStarted_with_disabled() + { + map.disableOnFlickStartedWithDisabled = true + disable_onFlickStarted() + } + + function test_disable_onFlickStarted_with_nogesture() + { + map.disableOnFlickStartedWithNoGesture = true + disable_onFlickStarted() + } + + function disable_onPanStarted() + { + map.center.latitude = 50 + map.center.longitude = 50 + mousePress(page, 0, 0) + for (var i = 0; i < 50; i += 5) { + wait(20) + mouseMove(page, i, i, 0, Qt.LeftButton); + } + mouseRelease(page, 50, 50) + compare(map.center.latitude,50) + compare(map.center.longitude,50) + tryCompare(panFinishedSpy, "count", 1) + // compare that flick was interrupted (less movement than without interrupting) + compare(map.center.latitude,50) + compare(map.center.longitude,50) + compare(map.gesture.panActive, false) + } + + function test_disable_onPanStarted_with_disabled() + { + map.disableOnPanStartedWithDisabled = true + disable_onPanStarted() + } + + function test_disable_onPanStarted_with_nogesture() + { + map.disableOnPanStartedWithNoGesture = true + disable_onPanStarted() + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_item.qml b/tests/auto/declarative_ui/tst_map_item.qml new file mode 100644 index 0000000..8ede357 --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_item.qml @@ -0,0 +1,615 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.6 +import QtPositioning 5.5 +import QtLocation.Test 5.6 + + /* + + (0,0) ---------------------------------------------------- (240,0) + | no map | + | (20,20) | + (0,20) | ------------------------------------------ | (240,20) + | | | | + | | map | | + | | | | + | | | | + | | | | + | | (lat 20, lon 20) | | + | | x | | + | | | | + | | | | + | | | | + | | | | + | | | | + | ------------------------------------------ | + | | + (0,240) ---------------------------------------------------- (240,240) + + */ + +Item { + id: page + x: 0; y: 0; + width: 240 + height: 240 + Plugin { id: testPlugin; name : "qmlgeo.test.plugin"; allowExperimental: true } + + property variant someCoordinate1: QtPositioning.coordinate(15, 15) + property variant someCoordinate2: QtPositioning.coordinate(16, 16) + + Route { id: someRoute; + path: [ + { latitude: 22, longitude: 15 }, + { latitude: 21, longitude: 16 }, + { latitude: 23, longitude: 17 } + ] + } + Item { id: someItem } + + MapCircle { + id: extMapCircle + center { + latitude: 35 + longitude: 15 + } + color: 'firebrick' + radius: 600000 + MouseArea { + anchors.fill: parent + SignalSpy { id: extMapCircleClicked; target: parent; signalName: "clicked" } + } + } + + MapQuickItem { + id: extMapQuickItem + MouseArea { + anchors.fill: parent + SignalSpy { id: extMapQuickItemClicked; target: parent; signalName: "clicked" } + } + coordinate { + latitude: 35 + longitude: 33 + } + sourceItem: Rectangle { + color: 'darkblue' + width: 40 + height: 20 + } + } + + Map { + id: map; + x: 20; y: 20; width: 200; height: 200 + zoomLevel: 9 + plugin: testPlugin; + + MapRectangle { + id: preMapRect + MouseArea { + id: preMapRectMa + anchors.fill: parent + drag.target: parent + preventStealing: true + SignalSpy { id: preMapRectClicked; target: parent; signalName: "clicked" } + SignalSpy { id: preMapRectActiveChanged; target: parent.drag; signalName: "activeChanged" } + } + SignalSpy {id: preMapRectTopLeftChanged; target: parent; signalName: "topLeftChanged" } + SignalSpy {id: preMapRectBottomRightChanged; target: parent; signalName: "bottomRightChanged" } + SignalSpy {id: preMapRectColorChanged; target: parent; signalName: "colorChanged"} + } + MapCircle { + id: preMapCircle + MouseArea { + id: preMapCircleMa + anchors.fill: parent + drag.target: parent + preventStealing: true + SignalSpy { id: preMapCircleClicked; target: parent; signalName: "clicked" } + SignalSpy { id: preMapCircleActiveChanged; target: parent.drag; signalName: "activeChanged" } + } + SignalSpy {id: preMapCircleCenterChanged; target: parent; signalName: "centerChanged"} + SignalSpy {id: preMapCircleColorChanged; target: parent; signalName: "colorChanged"} + SignalSpy {id: preMapCircleRadiusChanged; target: parent; signalName: "radiusChanged"} + SignalSpy {id: preMapCircleBorderColorChanged; target: parent.border; signalName: "colorChanged"} + SignalSpy {id: preMapCircleBorderWidthChanged; target: parent.border; signalName: "widthChanged"} + } + MapQuickItem { + id: preMapQuickItem + MouseArea { + id: preMapQuickItemMa + anchors.fill: parent + drag.target: parent + preventStealing: true + SignalSpy { id: preMapQuickItemClicked; target: parent; signalName: "clicked" } + SignalSpy { id: preMapQuickItemActiveChanged; target: parent.drag; signalName: "activeChanged" } + } + sourceItem: Rectangle { + id: preMapQuickItemSource + color: 'darkgreen' + width: 20 + height: 20 + } + SignalSpy { id: preMapQuickItemCoordinateChanged; target: parent; signalName: "coordinateChanged"} + SignalSpy { id: preMapQuickItemAnchorPointChanged; target: parent; signalName: "anchorPointChanged"} + SignalSpy { id: preMapQuickItemZoomLevelChanged; target: parent; signalName: "zoomLevelChanged"} + SignalSpy { id: preMapQuickItemSourceItemChanged; target: parent; signalName: "sourceItemChanged"} + } + MapPolygon { + id: preMapPolygon + color: 'darkgrey' + border.width: 0 + path: [ + { latitude: 25, longitude: 5 }, + { latitude: 20, longitude: 10 }, + { latitude: 15, longitude: 6 } + ] + MouseArea { + anchors.fill: parent + drag.target: parent + SignalSpy { id: preMapPolygonClicked; target: parent; signalName: "clicked" } + } + SignalSpy {id: preMapPolygonPathChanged; target: parent; signalName: "pathChanged"} + SignalSpy {id: preMapPolygonColorChanged; target: parent; signalName: "colorChanged"} + SignalSpy {id: preMapPolygonBorderWidthChanged; target: parent.border; signalName: "widthChanged"} + SignalSpy {id: preMapPolygonBorderColorChanged; target: parent.border; signalName: "colorChanged"} + } + MapPolyline { + id: preMapPolyline + line.color: 'darkred' + path: [ + { latitude: 25, longitude: 15 }, + { latitude: 20, longitude: 19 }, + { latitude: 15, longitude: 16 } + ] + SignalSpy {id: preMapPolylineColorChanged; target: parent.line; signalName: "colorChanged"} + SignalSpy {id: preMapPolylineWidthChanged; target: parent.line; signalName: "widthChanged"} + SignalSpy {id: preMapPolylinePathChanged; target: parent; signalName: "pathChanged"} + } + MapRoute { + id: preMapRoute + line.color: 'yellow' + // don't try this at home - route is not user instantiable + route: Route { + path: [ + { latitude: 25, longitude: 14 }, + { latitude: 20, longitude: 18 }, + { latitude: 15, longitude: 15 } + ] + } + SignalSpy {id: preMapRouteRouteChanged; target: parent; signalName: "routeChanged"} + SignalSpy {id: preMapRouteLineWidthChanged; target: parent.line; signalName: "widthChanged"} + SignalSpy {id: preMapRouteLineColorChanged; target: parent.line; signalName: "colorChanged"} + } + } + TestCase { + name: "MapItems" + when: windowShown + + function initTestCase() + { + // sanity check that the coordinate conversion works, as + // rest of the case relies on it. for robustness cut + // a little slack with fuzzy compare + var mapcenter = map.fromCoordinate(map.center) + verify (fuzzy_compare(mapcenter.x, 100, 2)) + verify (fuzzy_compare(mapcenter.y, 100, 2)) + } + + function init() + { + map.center = QtPositioning.coordinate(20, 20) + preMapCircle.center = QtPositioning.coordinate(10,30) + preMapCircle.border.width = 0 + preMapCircle.color = 'red' + preMapCircle.radius = 10000 + preMapCircleClicked.clear() + preMapCircleCenterChanged.clear() + preMapCircleColorChanged.clear() + preMapCircleRadiusChanged.clear() + preMapCircleBorderColorChanged.clear() + preMapCircleBorderWidthChanged.clear() + + preMapRect.color = 'red' + preMapRect.border.width = 0 + preMapRect.topLeft = QtPositioning.coordinate(20, 20) + preMapRect.bottomRight = QtPositioning.coordinate(10, 30) + preMapRectTopLeftChanged.clear() + preMapRectBottomRightChanged.clear() + preMapRectColorChanged.clear() + preMapRectClicked.clear() + preMapRectActiveChanged.clear() + + preMapQuickItem.sourceItem = preMapQuickItemSource + preMapQuickItem.zoomLevel = 0 + preMapQuickItem.coordinate = QtPositioning.coordinate(35, 3) + preMapQuickItemClicked.clear() + preMapQuickItem.anchorPoint = Qt.point(0,0) + preMapQuickItemCoordinateChanged.clear() + preMapQuickItemAnchorPointChanged.clear() + preMapQuickItemZoomLevelChanged.clear() + preMapQuickItemSourceItemChanged.clear() + + preMapPolygonClicked.clear() + preMapPolylineColorChanged.clear() + preMapPolylineWidthChanged.clear() + preMapPolylinePathChanged.clear() + preMapPolygonPathChanged.clear() + preMapPolygonColorChanged.clear() + preMapPolygonBorderColorChanged.clear() + preMapPolygonBorderWidthChanged.clear() + preMapRouteRouteChanged.clear() + preMapRouteLineColorChanged.clear() + preMapRouteLineWidthChanged.clear() + verify(LocationTestHelper.waitForPolished(map)) + } + + function test_items_on_map() + { + // click rect + map.center = preMapRect.topLeft + verify(LocationTestHelper.waitForPolished(map)) + var point = map.fromCoordinate(preMapRect.topLeft) + mouseClick(map, point.x + 5, point.y + 5) + tryCompare(preMapRectClicked, "count", 1) + mouseClick(map, 1, 1) // no item hit + tryCompare(preMapRectClicked, "count", 1) + compare(preMapCircleClicked.count, 0) + + // click circle, overlaps and is above rect + map.center = preMapCircle.center + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(preMapCircle.center) + mouseClick(map, point.x - 5, point.y - 5) + tryCompare(preMapCircleClicked, "count", 1) + compare(preMapRectClicked.count, 1) + + // click within circle bounding rect but not inside the circle geometry + map.center = preMapCircle.center.atDistanceAndAzimuth(preMapCircle.radius, -45) + mouseClick(map, preMapCircle.x + 4, preMapCircle.y + 4) + tryCompare(preMapRectClicked, "count", 2) + compare(preMapCircleClicked.count, 1) + + // click quick item + compare(preMapQuickItemClicked.count, 0) + map.center = preMapQuickItem.coordinate + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(preMapQuickItem.coordinate) + mouseClick(map, point.x + 5, point.y + 5) + tryCompare(preMapQuickItemClicked, "count", 1) + + // click polygon + compare (preMapPolygonClicked.count, 0) + map.center = preMapPolygon.path[1] + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(preMapPolygon.path[1]) + mouseClick(map, point.x - 5, point.y) + tryCompare(preMapPolygonClicked, "count", 1) + } + + function test_no_items_on_map() + { + // remove items and repeat clicks to verify they are gone + map.clearMapItems() + compare (map.mapItems.length, 0) + map.center = preMapRect.topLeft + var point = map.fromCoordinate(preMapRect.topLeft) + mouseClick(map, point.x + 5, point.y + 5) + compare(preMapRectClicked.count, 0) + verify(LocationTestHelper.waitForPolished(map)) + map.center = preMapCircle.center + point = map.fromCoordinate(preMapCircle.center) + mouseClick(map, point.x - 5, point.y - 5) + compare(preMapRectClicked.count, 0) + compare(preMapCircleClicked.count, 0) + map.center = preMapCircle.center.atDistanceAndAzimuth(preMapCircle.radius, -45) + mouseClick(map, preMapCircle.x + 4, preMapCircle.y + 4) + compare(preMapRectClicked.count, 0) + compare(preMapCircleClicked.count, 0) + compare(preMapQuickItemClicked.count, 0) + map.center = preMapQuickItem.coordinate + point = map.fromCoordinate(preMapQuickItem.coordinate) + mouseClick(map, point.x + 5, point.y + 5) + compare(preMapQuickItemClicked.count, 0) + map.center = preMapPolygon.path[1] + point = map.fromCoordinate(preMapPolygon.path[1]) + mouseClick(map, point.x - 5, point.y) + compare(preMapPolygonClicked.count, 0) + + // re-add items and verify they are back + // note: addition order is significant + map.addMapItem(preMapRect) + map.addMapItem(preMapCircle) + map.addMapItem(preMapQuickItem) + map.addMapItem(preMapPolygon) + map.addMapItem(preMapPolyline) + map.addMapItem(preMapRoute) + compare (map.mapItems.length, 6) + + map.center = preMapRect.topLeft + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(preMapRect.topLeft) + mouseClick(map, point.x + 5, point.y + 5) + tryCompare(preMapRectClicked, "count", 1) + map.center = preMapCircle.center + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(preMapCircle.center) + mouseClick(map, point.x - 5, point.y - 5) + tryCompare(preMapRectClicked, "count", 1) + compare(preMapCircleClicked.count, 1) + map.center = preMapCircle.center.atDistanceAndAzimuth(preMapCircle.radius, -45) + verify(LocationTestHelper.waitForPolished(map)) + mouseClick(map, preMapCircle.x + 4, preMapCircle.y + 4) + tryCompare(preMapRectClicked, "count", 2) + compare(preMapCircleClicked.count, 1) + compare(preMapQuickItemClicked.count, 0) + map.center = preMapQuickItem.coordinate + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(preMapQuickItem.coordinate) + mouseClick(map, point.x + 5, point.y + 5) + tryCompare(preMapQuickItemClicked, "count", 1) + map.center = preMapPolygon.path[1] + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(preMapPolygon.path[1]) + mouseClick(map, point.x - 5, point.y) + tryCompare(preMapPolygonClicked, "count", 1) + + + // item clips to map. not sure if this is sensible test + map.addMapItem(extMapCircle) + map.center = extMapCircle.center + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(extMapCircle.center) + mouseClick(map, point.x, point.y) + tryCompare(extMapCircleClicked, "count", 1) + mouseClick(map, point.x, -5) + tryCompare(extMapCircleClicked, "count", 1) + map.removeMapItem(extMapCircle) + + map.addMapItem(extMapQuickItem) + map.center = extMapQuickItem.coordinate + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(extMapQuickItem.coordinate) + mouseClick(map, point.x + 5, point.y + 5) + tryCompare(extMapQuickItemClicked, "count", 1) + mouseClick(map, map.width + 5, point.y + 5) + tryCompare(extMapQuickItemClicked, "count", 1) + map.removeMapItem(extMapQuickItem) + } + + function test_drag() + { + // basic drags, drag rectangle + compare (preMapRectActiveChanged.count, 0) + map.center = preMapRect.topLeft + verify(LocationTestHelper.waitForPolished(map)) + var i + var point = map.fromCoordinate(preMapRect.topLeft) + var targetCoordinate = map.toCoordinate(51, 51) + mousePress(map, point.x + 5, point.y + 5) + for (i = 0; i < 50; i += 1) { + wait(1) + mouseMove(map, point.x + 5 - i, point.y + 5 - i) + } + mouseRelease(map, point.x + 5 - i, point.y + 5 - i) + compare (preMapRectActiveChanged.count, 2) + verify(preMapRectTopLeftChanged.count > 1) + verify(preMapRectBottomRightChanged.count === preMapRectTopLeftChanged.count) + verify(fuzzy_compare(preMapRect.topLeft.latitude, targetCoordinate.latitude, 0.2)) + verify(fuzzy_compare(preMapRect.topLeft.longitude, targetCoordinate.longitude, 0.2)) + var latH = preMapRect.bottomRight.latitude - preMapRect.topLeft.latitude + var lonW = preMapRect.bottomRight.longitude - preMapRect.topLeft.longitude + verify(fuzzy_compare(preMapRect.bottomRight.latitude, preMapRect.topLeft.latitude + latH, 0.1)) + verify(fuzzy_compare(preMapRect.bottomRight.longitude, preMapRect.topLeft.longitude + lonW, 0.1)) + + // drag circle + compare (preMapCircleActiveChanged.count, 0) + map.center = preMapCircle.center + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(preMapCircle.center) + targetCoordinate = map.toCoordinate(51, 51) + mousePress(map, point.x, point.y) + for (i = 0; i < 50; i += 1) { + wait(1) + mouseMove(map, point.x - i, point.y - i) + } + mouseRelease(map, point.x - i, point.y - i) + verify(LocationTestHelper.waitForPolished(map)) + compare(preMapRectActiveChanged.count, 2) + compare(preMapCircleActiveChanged.count, 2) + verify(preMapCircleCenterChanged.count > 1) + verify(fuzzy_compare(preMapCircle.center.latitude, targetCoordinate.latitude, 0.2)) + verify(fuzzy_compare(preMapCircle.center.longitude, targetCoordinate.longitude, 0.2)) + + // drag quick item + compare (preMapQuickItemActiveChanged.count, 0) + map.center = preMapQuickItem.coordinate + verify(LocationTestHelper.waitForPolished(map)) + point = map.fromCoordinate(preMapQuickItem.coordinate) + targetCoordinate = map.toCoordinate(51, 51) + mousePress(map, point.x + 5, point.y + 5) + for (i = 0; i < 50; i += 1) { + wait(1) + mouseMove(map, point.x - i, point.y - i) + } + mouseRelease(map, point.x - i, point.y - i) + verify(LocationTestHelper.waitForPolished(map)) + compare(preMapQuickItemActiveChanged.count, 2) + verify(preMapQuickItemCoordinateChanged.count > 1) + verify(fuzzy_compare(preMapQuickItem.coordinate.latitude, targetCoordinate.latitude, 0.2)) + verify(fuzzy_compare(preMapQuickItem.coordinate.longitude, targetCoordinate.longitude, 0.2)) + } + + function test_basic_items_properties() + { + // circle + preMapCircle.center = someCoordinate1 + compare (preMapCircleCenterChanged.count, 1) + preMapCircle.center = someCoordinate1 + compare (preMapCircleCenterChanged.count, 1) + preMapCircle.color = 'blue' + compare (preMapCircleColorChanged.count, 1) + preMapCircle.color = 'blue' + compare (preMapCircleColorChanged.count, 1) + preMapCircle.radius = 50 + compare (preMapCircleRadiusChanged.count, 1) + preMapCircle.radius = 50 + compare (preMapCircleRadiusChanged.count, 1) + preMapCircle.border.color = 'blue' + compare(preMapCircleBorderColorChanged.count, 1) + preMapCircle.border.color = 'blue' + compare(preMapCircleBorderColorChanged.count, 1) + preMapCircle.border.width = 5 + compare(preMapCircleBorderWidthChanged.count, 1) + preMapCircle.border.width = 5 + compare(preMapCircleBorderWidthChanged.count, 1) + + // rectangle + preMapRect.topLeft = someCoordinate1 + compare (preMapRectTopLeftChanged.count, 1) + compare (preMapRectBottomRightChanged.count, 0) + preMapRect.bottomRight = someCoordinate2 + compare (preMapRectTopLeftChanged.count, 1) + compare (preMapRectBottomRightChanged.count, 1) + preMapRect.bottomRight = someCoordinate2 + preMapRect.topLeft = someCoordinate1 + compare (preMapRectTopLeftChanged.count, 1) + compare (preMapRectBottomRightChanged.count, 1) + preMapRect.color = 'blue' + compare (preMapRectColorChanged.count, 1) + preMapRect.color = 'blue' + compare (preMapRectColorChanged.count, 1) + + // polyline + preMapPolyline.line.width = 5 + compare (preMapPolylineWidthChanged.count, 1) + preMapPolyline.line.width = 5 + compare (preMapPolylineWidthChanged.count, 1) + preMapPolyline.line.color = 'blue' + compare(preMapPolylineColorChanged.count, 1) + preMapPolyline.line.color = 'blue' + compare(preMapPolylineColorChanged.count, 1) + preMapPolyline.addCoordinate(someCoordinate1) + compare (preMapPolylinePathChanged.count, 1) + preMapPolyline.addCoordinate(someCoordinate1) + compare (preMapPolylinePathChanged.count, 2) + preMapPolyline.removeCoordinate(someCoordinate1) + compare (preMapPolylinePathChanged.count, 3) + preMapPolyline.removeCoordinate(someCoordinate1) + compare (preMapPolylinePathChanged.count, 4) + preMapPolyline.removeCoordinate(someCoordinate1) + compare (preMapPolylinePathChanged.count, 4) + + // polygon + preMapPolygon.border.width = 5 + compare (preMapPolylineWidthChanged.count, 1) + preMapPolygon.border.width = 5 + compare (preMapPolylineWidthChanged.count, 1) + preMapPolygon.border.color = 'blue' + compare(preMapPolylineColorChanged.count, 1) + preMapPolygon.border.color = 'blue' + preMapPolygon.color = 'blue' + compare (preMapPolygonColorChanged.count, 1) + preMapPolygon.color = 'blue' + compare (preMapPolygonColorChanged.count, 1) + preMapPolygon.addCoordinate(someCoordinate1) + compare (preMapPolygonPathChanged.count, 1) + preMapPolygon.addCoordinate(someCoordinate1) + compare (preMapPolygonPathChanged.count, 2) + preMapPolygon.removeCoordinate(someCoordinate1) + compare (preMapPolygonPathChanged.count, 3) + preMapPolygon.removeCoordinate(someCoordinate1) + compare (preMapPolygonPathChanged.count, 4) + preMapPolygon.removeCoordinate(someCoordinate1) + compare (preMapPolygonPathChanged.count, 4) + + // route + preMapRoute.line.width = 5 + compare (preMapRouteLineWidthChanged.count, 1) + preMapRoute.line.width = 5 + compare (preMapRouteLineWidthChanged.count, 1) + preMapRoute.line.color = 'blue' + compare (preMapRouteLineColorChanged.count, 1) + preMapRoute.line.color = 'blue' + compare (preMapRouteLineColorChanged.count, 1) + preMapRoute.route = someRoute + compare (preMapRouteRouteChanged.count, 1) + preMapRoute.route = someRoute + compare (preMapRouteRouteChanged.count, 1) + + // quick + compare (preMapQuickItemCoordinateChanged.count, 0) + preMapQuickItem.coordinate = someCoordinate1 + compare (preMapQuickItemCoordinateChanged.count, 1) + preMapQuickItem.coordinate = someCoordinate1 + compare (preMapQuickItemCoordinateChanged.count, 1) + preMapQuickItem.anchorPoint = Qt.point(39, 3) + compare (preMapQuickItemAnchorPointChanged.count, 1) + preMapQuickItem.anchorPoint = Qt.point(39, 3) + compare (preMapQuickItemAnchorPointChanged.count, 1) + preMapQuickItem.zoomLevel = 6 + compare (preMapQuickItemZoomLevelChanged.count, 1) + preMapQuickItem.zoomLevel = 6 + compare (preMapQuickItemZoomLevelChanged.count, 1) + preMapQuickItem.sourceItem = someItem + compare (preMapQuickItemSourceItemChanged.count, 1) + preMapQuickItem.sourceItem = someItem + compare (preMapQuickItemSourceItemChanged.count, 1) + } + + function fuzzy_compare(val, ref, tol) { + var tolerance = 2 + if (tol !== undefined) + tolerance = tol + if ((val >= ref - tolerance) && (val <= ref + tolerance)) + return true; + console.log('map fuzzy cmp returns false for value, ref, tolerance: ' + val + ', ' + ref + ', ' + tolerance) + return false; + } + + // these 'real_' prefixed functions do sequences as + // it would occur on real app (e.g. doubleclick is in fact + // a sequence of press, release, doubleclick, release). + // (they were recorded as seen on test app). mouseClick() works ok + // because testlib internally converts it to mousePress + mouseRelease events + function real_double_click (target, x, y) { + mousePress(target, x,y) + mouseRelease(target, x, y) + mouseDoubleClick(target, x, y) + mouseRelease(target, x, y) + } + function real_press_and_hold(target, x,y) { + mousePress(target,x,y) + wait(850) // threshold is 800 ms + mouseRelease(target,x, y) + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_item_details.qml b/tests/auto/declarative_ui/tst_map_item_details.qml new file mode 100644 index 0000000..ebaf1ea --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_item_details.qml @@ -0,0 +1,613 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtPositioning 5.5 +import QtLocation 5.6 +import QtLocation.Test 5.6 + +Item { + id: page + x: 0; y: 0; + width: 240 + height: 240 + Plugin { id: testPlugin + name : "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ PluginParameter { name: "finishRequestImmediately"; value: true}] + } + + property variant mapDefaultCenter: QtPositioning.coordinate(20, 20) + + property variant datelineCoordinate: QtPositioning.coordinate(20, 180) + property variant datelineCoordinateLeft: QtPositioning.coordinate(20, 170) + property variant datelineCoordinateRight: QtPositioning.coordinate(20, -170) + + MapPolygon { + id: extMapPolygon + color: 'darkgrey' + path: [ + { latitude: 25, longitude: 5 }, + { latitude: 20, longitude: 10 } + ] + MouseArea { + anchors.fill: parent + drag.target: parent + SignalSpy { id: extMapPolygonClicked; target: parent; signalName: "clicked" } + } + SignalSpy {id: extMapPolygonPathChanged; target: parent; signalName: "pathChanged"} + SignalSpy {id: extMapPolygonColorChanged; target: parent; signalName: "colorChanged"} + SignalSpy {id: extMapPolygonBorderWidthChanged; target: parent.border; signalName: "widthChanged"} + SignalSpy {id: extMapPolygonBorderColorChanged; target: parent.border; signalName: "colorChanged"} + } + + property variant polyCoordinate: QtPositioning.coordinate(15, 6) + + MapPolygon { + id: extMapPolygon0 + color: 'darkgrey' + } + + MapPolyline { + id: extMapPolyline0 + } + + MapPolyline { + id: extMapPolyline + path: [ + { latitude: 25, longitude: 5 }, + { latitude: 20, longitude: 10 } + ] + SignalSpy {id: extMapPolylineColorChanged; target: parent.line; signalName: "colorChanged"} + SignalSpy {id: extMapPolylineWidthChanged; target: parent.line; signalName: "widthChanged"} + SignalSpy {id: extMapPolylinePathChanged; target: parent; signalName: "pathChanged"} + } + + MapRectangle { + id: extMapRectDateline + color: 'darkcyan' + topLeft { + latitude: 20 + longitude: 175 + } + bottomRight { + latitude: 10 + longitude: -175 + } + MouseArea { + anchors.fill: parent + drag.target: parent + preventStealing: true + } + } + + MapCircle { + id: extMapCircleDateline + color: 'darkmagenta' + center { + latitude: 20 + longitude: 180 + } + radius: 400000 + MouseArea { + anchors.fill: parent + drag.target: parent + preventStealing: true + } + } + + MapQuickItem { + id: extMapQuickItemDateline + MouseArea { + anchors.fill: parent + drag.target: parent + preventStealing: true + } + coordinate { + latitude: 20 + longitude: 175 + } + sourceItem: Rectangle { + color: 'darkgreen' + width: 20 + height: 20 + } + } + + MapPolygon { + id: extMapPolygonDateline + color: 'darkmagenta' + path: [ + { latitude: 20, longitude: 175 }, + { latitude: 20, longitude: -175 }, + { latitude: 10, longitude: -175 }, + { latitude: 10, longitude: 175 } + ] + MouseArea { + anchors.fill: parent + drag.target: parent + preventStealing: true + } + } + + MapPolyline { + id: extMapPolylineDateline + line.width : 3 + path: [ + { latitude: 20, longitude: 175 }, + { latitude: 25, longitude: -175 } + ] + MouseArea { + anchors.fill: parent + drag.target: parent + } + } + + MapRoute { + id: extMapRouteDateline + line.color: 'yellow' + route: Route { + path: [ + { latitude: 25, longitude: 175 }, + { latitude: 20, longitude: -175 } + ] + } + } + + MapRectangle { + id: extMapRectEdge + color: 'darkcyan' + topLeft { + latitude: 20 + longitude: -15 + } + bottomRight { + latitude: 10 + longitude: -5 + } + MouseArea { + anchors.fill: parent + drag.target: parent + } + } + + MapCircle { + id: extMapCircleEdge + color: 'darkmagenta' + center { + latitude: 20 + longitude: -15 + } + radius: 400000 + MouseArea { + anchors.fill: parent + drag.target: parent + } + } + + MapQuickItem { + id: extMapQuickItemEdge + MouseArea { + anchors.fill: parent + drag.target: parent + } + coordinate { + latitude: 20 + longitude: -15 + } + sourceItem: Rectangle { + color: 'darkgreen' + width: 20 + height: 20 + } + } + + MapPolygon { + id: extMapPolygonEdge + color: 'darkmagenta' + path: [ + { latitude: 20, longitude: -15 }, + { latitude: 20, longitude: -5 }, + { latitude: 10, longitude: -5 }, + { latitude: 10, longitude: -15 } + ] + MouseArea { + anchors.fill: parent + drag.target: parent + } + } + + MapPolyline { + id: extMapPolylineEdge + line.width : 3 + path: [ + { latitude: 20, longitude: -15 }, + { latitude: 25, longitude: -5 } + ] + MouseArea { + anchors.fill: parent + drag.target: parent + } + } + + MapRoute { + id: extMapRouteEdge + line.color: 'yellow' + route: Route { + path: [ + { latitude: 25, longitude: -15 }, + { latitude: 20, longitude: -5 } + ] + } + } + + Map { + id: map; + x: 20; y: 20; width: 200; height: 200 + center: mapDefaultCenter + plugin: testPlugin; + } + + Text {id: progressText} + + TestCase { + name: "MapItemDetails" + when: windowShown + + /* + + (0,0) ---------------------------------------------------- (240,0) + | no map | + | (20,20) | + (0,20) | ------------------------------------------ | (240,20) + | | | | + | | map | | + | | | | + | | | | + | | | | + | | (lat 20, lon 20) | | + | | x | | + | | | | + | | | | + | | | | + | | | | + | | | | + | ------------------------------------------ | + | | + (0,240) ---------------------------------------------------- (240,240) + + */ + function initTestCase() + { + // sanity check that the coordinate conversion works + var mapcenter = map.fromCoordinate(map.center) + verify (fuzzy_compare(mapcenter.x, 100, 2)) + verify (fuzzy_compare(mapcenter.y, 100, 2)) + } + + function init() + { + map.clearMapItems() + map.zoomLevel = 3 + extMapPolygon.border.width = 1.0 + extMapPolygonClicked.clear() + extMapPolylineColorChanged.clear() + extMapPolylineWidthChanged.clear() + extMapPolylinePathChanged.clear() + extMapPolygonPathChanged.clear() + extMapPolygonColorChanged.clear() + extMapPolygonBorderColorChanged.clear() + extMapPolygonBorderWidthChanged.clear() + } + + function test_polygon() + { + map.center = extMapPolygon.path[1] + var point = map.fromCoordinate(extMapPolygon.path[1]) + map.addMapItem(extMapPolygon) + verify(LocationTestHelper.waitForPolished(map)) + verify(extMapPolygon.path.length == 2) + mouseClick(map, point.x - 5, point.y) + compare(extMapPolygonClicked.count, 0) + map.addMapItem(extMapPolygon0) // mustn't crash or ill-behave + verify(extMapPolygon0.path.length == 0) + extMapPolygon.addCoordinate(polyCoordinate) + verify(extMapPolygon.path.length == 3) + verify(LocationTestHelper.waitForPolished(map)) + mouseClick(map, point.x - 5, point.y) + tryCompare(extMapPolygonClicked, "count", 1) + + extMapPolygon.path[0].latitude = 10 + verify(extMapPolygon.path[0].latitude, 10) + extMapPolygon.path[0].latitude = polyCoordinate.latitude + verify(extMapPolygon.path[0].latitude, 15) + extMapPolygon.path[0].longitude = 2 + verify(extMapPolygon.path[0].longitude, 2) + extMapPolygon.path[0].longitude = polyCoordinate.longitude + verify(extMapPolygon.path[0].longitude, 6) + + extMapPolygon.removeCoordinate(polyCoordinate) + verify(extMapPolygon.path.length == 2) + extMapPolygon.removeCoordinate(extMapPolygon.path[1]) + verify(extMapPolygon.path.length == 1) + extMapPolygon.removeCoordinate(extMapPolygon.path[0]) + verify(extMapPolygon.path.length == 0) + } + + function test_polyline() + { + compare (extMapPolyline.line.width, 1.0) + var point = map.fromCoordinate(extMapPolyline.path[1]) + map.addMapItem(extMapPolyline0) // mustn't crash or ill-behave + verify(extMapPolyline0.path.length == 0) + map.addMapItem(extMapPolyline) + verify(extMapPolyline.path.length == 2) + extMapPolyline.addCoordinate(polyCoordinate) + verify(extMapPolyline.path.length == 3) + extMapPolyline.addCoordinate(extMapPolyline.path[0]) + verify(extMapPolyline.path.length == 4) + + extMapPolyline.path[0].latitude = 10 + verify(extMapPolyline.path[0].latitude, 10) + extMapPolyline.path[0].latitude = polyCoordinate.latitude + verify(extMapPolyline.path[0].latitude, 15) + extMapPolyline.path[0].longitude = 2 + verify(extMapPolyline.path[0].longitude, 2) + extMapPolyline.path[0].longitude = polyCoordinate.longitude + verify(extMapPolyline.path[0].longitude, 6) + + // TODO when line rendering is ready + //mouseClick(map, point.x - 5, point.y) + //compare(extMapPolylineClicked.count, 1) + extMapPolyline.removeCoordinate(extMapPolyline.path[0]) + verify(extMapPolyline.path.length == 3) + extMapPolyline.removeCoordinate(polyCoordinate) + verify(extMapPolyline.path.length == 2) + extMapPolyline.removeCoordinate(extMapPolyline.path[1]) + verify(extMapPolyline.path.length == 1) + extMapPolyline.removeCoordinate(extMapPolyline.path[0]) + verify(extMapPolyline.path.length == 0) + } + + /* + + (0,0) ---------------------------------------------------- (600,0) + | no map | + | (20,20) | + (0,20) | ------------------------------------------ | (600,20) + | | | | + | | map | | + | | | | + | | | | + | | | | + | | (lat 20, lon 180) | | + | | x | | + | | | | + | | | | + | | | | + | | | | + | | | | + | ------------------------------------------ | + | | + (0,240) ---------------------------------------------------- (600,240) + + */ + function test_dateline() { + map.center = datelineCoordinate + map.zoomLevel = 2.2 + var inspectionTime = 0 // change this to inspect the behavior. + + // rectangle + // item spanning across dateline + map.addMapItem(extMapRectDateline) + verify(extMapRectDateline.topLeft.longitude == 175) + verify(extMapRectDateline.bottomRight.longitude == -175) + var point = map.fromCoordinate(extMapRectDateline.topLeft) + verify(point.x < map.width / 2.0) + point = map.fromCoordinate(extMapRectDateline.bottomRight) + verify(point.x > map.width / 2.0) + // move item away from dataline by directly setting its coords + extMapRectDateline.bottomRight.longitude = datelineCoordinateRight.longitude + point = map.fromCoordinate(extMapRectDateline.bottomRight) + verify(point.x > map.width / 2.0) + // move item edge onto dateline + extMapRectDateline.topLeft.longitude = datelineCoordinate.longitude + point = map.fromCoordinate(extMapRectDateline.topLeft) + verify(point.x == map.width / 2.0) + // drag item back onto dateline + verify(LocationTestHelper.waitForPolished(map)) + visualInspectionPoint(inspectionTime) + mousePress(map, point.x + 5, point.y + 5) + var i + for (i=0; i < 20; i += 2) { + wait(1) + mouseMove(map, point.x + 5 - i, point.y + 5 ) + } + mouseRelease(map, point.x + 5 - i, point.y + 5) + verify(LocationTestHelper.waitForPolished(map)) + visualInspectionPoint(inspectionTime) + point = map.fromCoordinate(extMapRectDateline.topLeft) + verify(point.x < map.width / 2.0) + point = map.fromCoordinate(extMapRectDateline.bottomRight) + verify(point.x > map.width / 2.0) + map.removeMapItem(extMapRectDateline) + + // circle + map.addMapItem(extMapCircleDateline) + verify(extMapCircleDateline.center.longitude === 180) + map.center = datelineCoordinate + point = map.fromCoordinate(extMapCircleDateline.center) + verify(point.x == map.width / 2.0) // center of the screen + visualInspectionPoint() + extMapCircleDateline.center.longitude = datelineCoordinateRight.longitude // -170, moving the circle to the right + point = map.fromCoordinate(extMapCircleDateline.center) + verify(LocationTestHelper.waitForPolished(map)) + verify(point.x > map.width / 2.0) + visualInspectionPoint(inspectionTime) + mousePress(map, point.x, point.y) + for (i=0; i < 50; i += 4) { + wait(1) + mouseMove(map, point.x - i, point.y) + } + mouseRelease(map, point.x - i, point.y) + verify(LocationTestHelper.waitForPolished(map)) + visualInspectionPoint(inspectionTime) + point = map.fromCoordinate(extMapCircleDateline.center) + visualInspectionPoint() + verify(point.x < map.width / 2.0) + map.removeMapItem(extMapCircleDateline) + + // quickitem + map.addMapItem(extMapQuickItemDateline) + map.center = datelineCoordinate + verify(extMapQuickItemDateline.coordinate.longitude === 175) + point = map.fromCoordinate(extMapQuickItemDateline.coordinate) + verify(point.x < map.width / 2.0) + visualInspectionPoint() + extMapQuickItemDateline.coordinate.longitude = datelineCoordinateRight.longitude + point = map.fromCoordinate(extMapQuickItemDateline.coordinate) + verify(point.x > map.width / 2.0) + verify(LocationTestHelper.waitForPolished(map)) + visualInspectionPoint(inspectionTime) + mousePress(map, point.x + 5, point.y + 5) + for (i=0; i < 64; i += 5) { + wait(1) + mouseMove(map, point.x + 5 - i, point.y + 5 ) + } + mouseRelease(map, point.x + 5 - i, point.y + 5) + verify(LocationTestHelper.waitForPolished(map)) + visualInspectionPoint(inspectionTime) + point = map.fromCoordinate(extMapQuickItemDateline.coordinate) + visualInspectionPoint() + verify(point.x < map.width / 2.0) + map.removeMapItem(extMapQuickItemDateline) + + // polygon + map.addMapItem(extMapPolygonDateline) + map.center = datelineCoordinate + verify(extMapPolygonDateline.path[0].longitude == 175) + verify(extMapPolygonDateline.path[1].longitude == -175) + verify(extMapPolygonDateline.path[2].longitude == -175) + verify(extMapPolygonDateline.path[3].longitude == 175) + point = map.fromCoordinate(extMapPolygonDateline.path[0]) + verify(point.x < map.width / 2.0) + point = map.fromCoordinate(extMapPolygonDateline.path[1]) + verify(point.x > map.width / 2.0) + point = map.fromCoordinate(extMapPolygonDateline.path[2]) + verify(point.x > map.width / 2.0) + point = map.fromCoordinate(extMapPolygonDateline.path[3]) + verify(point.x < map.width / 2.0) + extMapPolygonDateline.path[1].longitude = datelineCoordinateRight.longitude + point = map.fromCoordinate(extMapPolygonDateline.path[1]) + verify(point.x > map.width / 2.0) + extMapPolygonDateline.path[2].longitude = datelineCoordinateRight.longitude + point = map.fromCoordinate(extMapPolygonDateline.path[2]) + verify(point.x > map.width / 2.0) + var path = extMapPolygonDateline.path; + path[0].longitude = datelineCoordinate.longitude; + extMapPolygonDateline.path = path; + point = map.fromCoordinate(extMapPolygonDateline.path[0]) + verify(point.x == map.width / 2.0) + path = extMapPolygonDateline.path; + path[3].longitude = datelineCoordinate.longitude; + extMapPolygonDateline.path = path; + point = map.fromCoordinate(extMapPolygonDateline.path[3]) + verify(point.x == map.width / 2.0) + verify(LocationTestHelper.waitForPolished(map)) + visualInspectionPoint(inspectionTime) + mousePress(map, point.x + 5, point.y - 5) + for (i=0; i < 16; i += 2) { + wait(1) + mouseMove(map, point.x + 5 - i, point.y - 5 ) + } + mouseRelease(map, point.x + 5 - i, point.y - 5) + verify(LocationTestHelper.waitForPolished(map)) + visualInspectionPoint(inspectionTime) + point = map.fromCoordinate(extMapPolygonDateline.path[0]) + verify(point.x < map.width / 2.0) + point = map.fromCoordinate(extMapPolygonDateline.path[1]) + verify(point.x > map.width / 2.0) + point = map.fromCoordinate(extMapPolygonDateline.path[2]) + verify(point.x > map.width / 2.0) + point = map.fromCoordinate(extMapPolygonDateline.path[3]) + verify(point.x < map.width / 2.0) + map.removeMapItem(extMapPolygonDateline) + + // polyline + map.addMapItem(extMapPolylineDateline) + map.center = datelineCoordinate + verify(extMapPolylineDateline.path[0].longitude == 175) + verify(extMapPolylineDateline.path[1].longitude == -175) + point = map.fromCoordinate(extMapPolylineDateline.path[0]) + verify(point.x < map.width / 2.0) + point = map.fromCoordinate(extMapPolylineDateline.path[1]) + verify(point.x > map.width / 2.0) + extMapPolylineDateline.path[1].longitude = datelineCoordinateRight.longitude + point = map.fromCoordinate(extMapPolylineDateline.path[1]) + verify(point.x > map.width / 2.0) + var path = extMapPolygonDateline.path; + path[0].longitude = datelineCoordinate.longitude; + extMapPolylineDateline.path = path; + point = map.fromCoordinate(extMapPolylineDateline.path[0]) + verify(point.x == map.width / 2.0) + map.removeMapItem(extMapPolylineDateline) + + // map route + // (does not support setting of path coords) + map.addMapItem(extMapRouteDateline) + verify(extMapRouteDateline.route.path[0].longitude == 175) + verify(extMapRouteDateline.route.path[1].longitude == -175) + point = map.fromCoordinate(extMapRouteDateline.route.path[0]) + verify(point.x < map.width / 2.0) + point = map.fromCoordinate(extMapRouteDateline.route.path[1]) + verify(point.x > map.width / 2.0) + map.removeMapItem(extMapRouteDateline) + } + + function fuzzy_compare(val, ref, tol) { + var tolerance = 2 + if (tol !== undefined) + tolerance = tol + if ((val >= ref - tolerance) && (val <= ref + tolerance)) + return true; + console.log('map fuzzy cmp returns false for value, ref, tolerance: ' + val + ', ' + ref + ', ' + tolerance) + return false; + } + // call to visualInspectionPoint testcase (for dev time visual inspection) + function visualInspectionPoint(time) { + var waitTime = 0 // 300 + if (time !== undefined) + waitTime = time + if (waitTime > 0) { + console.log('halting for ' + waitTime + ' milliseconds') + wait (waitTime) + } + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_item_fit_viewport.qml b/tests/auto/declarative_ui/tst_map_item_fit_viewport.qml new file mode 100644 index 0000000..fe4d9e4 --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_item_fit_viewport.qml @@ -0,0 +1,690 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.6 +import QtPositioning 5.5 +import QtLocation.Test 5.5 + + /* + + (0,0) ---------------------------------------------------- (296,0) + | no map | + | (20,20) | + (0,20) | ------------------------------------------ | (296,20) + | | | | + | | map | | + | | | | + | | | | + | | | | + | | (lat 20, lon 20) | | + | | x | | + | | | | + | | | | + | | | | + | | | | + | | | | + | ------------------------------------------ | + | | + (0,296) ---------------------------------------------------- (296,296) + + */ + +Item { + id: page + x: 0; y: 0; + width: 296 + height: 296 + Plugin { id: testPlugin; name : "qmlgeo.test.plugin"; allowExperimental: true } + + property variant mapDefaultCenter: QtPositioning.coordinate(20, 20) + property variant preMapRectangleDefaultTopLeft: QtPositioning.coordinate(20, 20) + property variant preMapRectangleDefaultBottomRight: QtPositioning.coordinate(10, 30) + property variant preMapCircleDefaultCenter: QtPositioning.coordinate(10, 30) + property variant preMapQuickItemDefaultCoordinate: QtPositioning.coordinate(35, 3) + + property variant preMapPolygonDefaultPath: [ + { latitude: 25, longitude: 5 }, + { latitude: 20, longitude: 10 }, + { latitude: 15, longitude: 6 } + ] + + property variant preMapPolylineDefaultPath: [ + { latitude: 25, longitude: 15 }, + { latitude: 20, longitude: 19 }, + { latitude: 15, longitude: 16 } + ] + + property variant preMapRouteDefaultPath: [ + { latitude: 25, longitude: 14 }, + { latitude: 20, longitude: 18 }, + { latitude: 15, longitude: 15 } + ] + + property variant mapCircleTopLeft: QtPositioning.coordinate(0, 0) + property variant mapCircleBottomRight: QtPositioning.coordinate(0, 0) + property variant mapQuickItemTopLeft: QtPositioning.coordinate(0, 0) + property variant mapQuickItemBottomRight: QtPositioning.coordinate(0, 0) + property variant mapPolygonTopLeft: QtPositioning.coordinate(0, 0) + property variant mapPolygonBottomRight: QtPositioning.coordinate(0, 0) + property variant mapPolylineTopLeft: QtPositioning.coordinate(0, 0) + property variant mapPolylineBottomRight: QtPositioning.coordinate(0, 0) + property variant mapRouteTopLeft: QtPositioning.coordinate(0, 0) + property variant mapRouteBottomRight: QtPositioning.coordinate(0, 0) + property variant fitRect: QtPositioning.rectangle(QtPositioning.coordinate(80, 80), + QtPositioning.coordinate(78, 82)) + property variant fitEmptyRect: QtPositioning.rectangle(QtPositioning.coordinate(79, 79),-1, -1) + property variant fitCircle: QtPositioning.circle(QtPositioning.coordinate(-50, -100), 1500) + property variant fitInvalidShape: QtPositioning.shape() + + property variant fitCircleTopLeft: QtPositioning.coordinate(0, 0) + property variant fitCircleBottomRight: QtPositioning.coordinate(0, 0) + + Map { + id: map; + x: 20; y: 20; width: 256; height: 256 + zoomLevel: 3 + center: mapDefaultCenter + plugin: testPlugin; + + MapRectangle { + id: preMapRect + color: 'darkcyan' + border.width: 0 + topLeft: preMapRectangleDefaultTopLeft + bottomRight: preMapRectangleDefaultBottomRight + MouseArea { + id: preMapRectMa + anchors.fill: parent + drag.target: parent + SignalSpy { id: preMapRectClicked; target: parent; signalName: "clicked" } + SignalSpy { id: preMapRectActiveChanged; target: parent.drag; signalName: "activeChanged" } + } + SignalSpy {id: preMapRectTopLeftChanged; target: parent; signalName: "topLeftChanged" } + SignalSpy {id: preMapRectBottomRightChanged; target: parent; signalName: "bottomRightChanged" } + SignalSpy {id: preMapRectColorChanged; target: parent; signalName: "colorChanged"} + } + MapCircle { + id: preMapCircle + color: 'darkmagenta' + border.width: 0 + center: preMapCircleDefaultCenter + radius: 400000 + MouseArea { + anchors.fill: parent + drag.target: parent + SignalSpy { id: preMapCircleClicked; target: parent; signalName: "clicked" } + SignalSpy { id: preMapCircleActiveChanged; target: parent.drag; signalName: "activeChanged" } + } + SignalSpy {id: preMapCircleCenterChanged; target: parent; signalName: "centerChanged"} + SignalSpy {id: preMapCircleColorChanged; target: parent; signalName: "colorChanged"} + SignalSpy {id: preMapCircleRadiusChanged; target: parent; signalName: "radiusChanged"} + SignalSpy {id: preMapCircleBorderColorChanged; target: parent.border; signalName: "colorChanged"} + SignalSpy {id: preMapCircleBorderWidthChanged; target: parent.border; signalName: "widthChanged"} + } + MapQuickItem { + id: preMapQuickItem + MouseArea { + anchors.fill: parent + drag.target: parent + SignalSpy { id: preMapQuickItemClicked; target: parent; signalName: "clicked" } + SignalSpy { id: preMapQuickItemActiveChanged; target: parent.drag; signalName: "activeChanged" } + } + coordinate: preMapQuickItemDefaultCoordinate + sourceItem: Rectangle { + color: 'darkgreen' + width: 20 + height: 20 + } + SignalSpy { id: preMapQuickItemCoordinateChanged; target: parent; signalName: "coordinateChanged"} + SignalSpy { id: preMapQuickItemAnchorPointChanged; target: parent; signalName: "anchorPointChanged"} + SignalSpy { id: preMapQuickItemZoomLevelChanged; target: parent; signalName: "zoomLevelChanged"} + SignalSpy { id: preMapQuickItemSourceItemChanged; target: parent; signalName: "sourceItemChanged"} + } + MapPolygon { + id: preMapPolygon + color: 'darkgrey' + border.width: 0 + path: [ + { latitude: 25, longitude: 5 }, + { latitude: 20, longitude: 10 }, + { latitude: 15, longitude: 6 } + ] + MouseArea { + anchors.fill: parent + drag.target: parent + SignalSpy { id: preMapPolygonClicked; target: parent; signalName: "clicked" } + } + SignalSpy {id: preMapPolygonPathChanged; target: parent; signalName: "pathChanged"} + SignalSpy {id: preMapPolygonColorChanged; target: parent; signalName: "colorChanged"} + SignalSpy {id: preMapPolygonBorderWidthChanged; target: parent.border; signalName: "widthChanged"} + SignalSpy {id: preMapPolygonBorderColorChanged; target: parent.border; signalName: "colorChanged"} + } + MapPolyline { + id: preMapPolyline + line.color: 'darkred' + path: [ + { latitude: 25, longitude: 15 }, + { latitude: 20, longitude: 19 }, + { latitude: 15, longitude: 16 } + ] + SignalSpy {id: preMapPolylineColorChanged; target: parent.line; signalName: "colorChanged"} + SignalSpy {id: preMapPolylineWidthChanged; target: parent.line; signalName: "widthChanged"} + SignalSpy {id: preMapPolylinePathChanged; target: parent; signalName: "pathChanged"} + } + MapRoute { + id: preMapRoute + line.color: 'yellow' + // don't try this at home - route is not user instantiable + route: Route { + path: [ + { latitude: 25, longitude: 14 }, + { latitude: 20, longitude: 18 }, + { latitude: 15, longitude: 15 } + ] + } + SignalSpy {id: preMapRouteRouteChanged; target: parent; signalName: "routeChanged"} + SignalSpy {id: preMapRouteLineWidthChanged; target: parent.line; signalName: "widthChanged"} + SignalSpy {id: preMapRouteLineColorChanged; target: parent.line; signalName: "colorChanged"} + } + } + + TestCase { + name: "MapItemsFitViewport" + when: windowShown + + function initTestCase() + { + // sanity check that the coordinate conversion works + var mapcenter = map.fromCoordinate(map.center) + verify (fuzzy_compare(mapcenter.x, 128, 2)) + verify (fuzzy_compare(mapcenter.y, 128, 2)) + } + + function init() + { + preMapRect.topLeft.latitude = 20 + preMapRect.topLeft.longitude = 20 + preMapRect.bottomRight.latitude = 10 + preMapRect.bottomRight.longitude = 30 + preMapCircle.center.latitude = 10 + preMapCircle.center.longitude = 30 + preMapQuickItem.coordinate.latitude = 35 + preMapQuickItem.coordinate.longitude = 3 + var i + for (i = 0; i < preMapPolygon.path.length; ++i) { + preMapPolygon.path[i].latitude = preMapPolygonDefaultPath[i].latitude + preMapPolygon.path[i].longitude = preMapPolygonDefaultPath[i].longitude + } + for (i = 0; i < preMapPolyline.path.length; ++i) { + preMapPolyline.path[i].latitude = preMapPolylineDefaultPath[i].latitude + preMapPolyline.path[i].longitude = preMapPolylineDefaultPath[i].longitude + } + for (i = 0; i < preMapRoute.route.path.length; ++i) { + preMapRoute.route.path[i].latitude = preMapRouteDefaultPath[i].latitude + preMapRoute.route.path[i].longitude = preMapRouteDefaultPath[i].longitude + } + // remove items + map.clearMapItems() + //clear_data() + compare (map.mapItems.length, 0) + // reset map + map.center.latitude = 20 + map.center.longitude = 20 + map.zoomLevel = 3 + // re-add items and verify they are back (without needing to pan map etc.) + map.addMapItem(preMapRect) + map.addMapItem(preMapCircle) + map.addMapItem(preMapQuickItem) + map.addMapItem(preMapPolygon) + map.addMapItem(preMapPolyline) + map.addMapItem(preMapRoute) + compare (map.mapItems.length, 6) + calculate_bounds() + } + + function test_visible_itmes() + { + // normal case - fit viewport to items which are all already visible + verify_visibility_all_items() + map.fitViewportToMapItems() + visualInspectionPoint() + verify_visibility_all_items() + } + + function test_visible_zoom_in() + { + // zoom in (clipping also occurs) + var z = map.zoomLevel + for (var i = (z + 1); i < map.maximumZoomLevel; ++i ) { + map.zoomLevel = i + visualInspectionPoint() + map.fitViewportToMapItems() + visualInspectionPoint() + verify_visibility_all_items() + } + } + + function test_visible_zoom_out() + { + // zoom out + for (var i = (z - 1); i >= 0; --i ) { + map.zoomLevel = i + visualInspectionPoint() + verify_visibility_all_items() + map.fitViewportToMapItems() + visualInspectionPoint() + verify_visibility_all_items() + } + } + + function test_visible_map_move() { + // move map so all items are out of screen + // then fit viewport + var xDir = 1 + var yDir = 0 + var xDirChange = -1 + var yDirChange = 1 + var dir = 0 + for (dir = 0; dir < 4; dir++) { + verify_visibility_all_items() + var i = 0 + var panX = map.width * xDir * 0.5 + var panY = map.height * yDir * 0.5 + map.pan(panX, panY) + map.pan(panX, panY) + visualInspectionPoint() + // check all items are indeed not within screen bounds + calculate_bounds() + verify(!is_coord_on_screen(preMapRect.topLeft)) + verify(!is_coord_on_screen(preMapRect.bottomRight)) + verify(!is_coord_on_screen(mapCircleTopLeft)) + verify(!is_coord_on_screen(mapCircleBottomRight)) + verify(!is_coord_on_screen(mapPolygonTopLeft)) + verify(!is_coord_on_screen(mapPolygonBottomRight)) + verify(!is_coord_on_screen(mapQuickItemTopLeft)) + verify(!is_coord_on_screen(mapQuickItemBottomRight)) + verify(!is_coord_on_screen(mapPolylineTopLeft)) + verify(!is_coord_on_screen(mapPolylineBottomRight)) + verify(!is_coord_on_screen(mapRouteTopLeft)) + verify(!is_coord_on_screen(mapRouteBottomRight)) + // fit viewport and verify that all items are visible again + map.fitViewportToMapItems() + visualInspectionPoint() + verify_visibility_all_items() + if (dir == 2) + xDirChange *= -1 + if (dir == 1) + yDirChange *= -1 + xDir += xDirChange + yDir += yDirChange + } + } + + function test_fit_to_geoshape() { + visualInspectionPoint() + calculate_fit_circle_bounds() + //None should be visible + verify(!is_coord_on_screen(fitCircleTopLeft)) + verify(!is_coord_on_screen(fitCircleBottomRight)) + verify(!is_coord_on_screen(fitRect.topLeft)) + verify(!is_coord_on_screen(fitRect.bottomRight)) + + map.visibleRegion = fitRect + visualInspectionPoint() + calculate_fit_circle_bounds() + //Rectangle should be visible, not circle + verify(!is_coord_on_screen(fitCircleTopLeft)) + verify(!is_coord_on_screen(fitCircleBottomRight)) + verify(is_coord_on_screen(fitRect.topLeft)) + verify(is_coord_on_screen(fitRect.bottomRight)) + + map.visibleRegion = fitCircle + visualInspectionPoint() + calculate_fit_circle_bounds() + //Circle should be visible, not rectangle + verify(is_coord_on_screen(fitCircleTopLeft)) + verify(is_coord_on_screen(fitCircleBottomRight)) + verify(!is_coord_on_screen(fitRect.topLeft)) + verify(!is_coord_on_screen(fitRect.bottomRight)) + + map.visibleRegion = fitInvalidShape + visualInspectionPoint() + calculate_fit_circle_bounds() + //Invalid shape, map should be in the same position as before + verify(is_coord_on_screen(fitCircleTopLeft)) + verify(is_coord_on_screen(fitCircleBottomRight)) + verify(!is_coord_on_screen(fitRect.topLeft)) + verify(!is_coord_on_screen(fitRect.bottomRight)) + + map.visibleRegion = fitEmptyRect + visualInspectionPoint() + calculate_fit_circle_bounds() + //Empty shape, map should change centerlocation, empty rect visible + verify(!is_coord_on_screen(fitCircleTopLeft)) + verify(!is_coord_on_screen(fitCircleBottomRight)) + verify(is_coord_on_screen(fitEmptyRect.topLeft)) + verify(is_coord_on_screen(fitEmptyRect.bottomRight)) + + // Test if this can be reset + map.visibleRegion = fitRect + verify(is_coord_on_screen(fitRect.topLeft)) + verify(is_coord_on_screen(fitRect.bottomRight)) + // move map + map.center = QtPositioning.coordinate(0,0) + verify(!is_coord_on_screen(fitRect.topLeft)) + verify(!is_coord_on_screen(fitRect.bottomRight)) + // recheck + map.visibleRegion = fitRect + verify(is_coord_on_screen(fitRect.topLeft)) + verify(is_coord_on_screen(fitRect.bottomRight)) + //zoom map + map.zoomLevel++ + verify(!is_coord_on_screen(fitRect.topLeft)) + verify(!is_coord_on_screen(fitRect.bottomRight)) + // recheck + map.visibleRegion = fitRect + verify(is_coord_on_screen(fitRect.topLeft)) + verify(is_coord_on_screen(fitRect.bottomRight)) + } + + // checks that circles belongs to the view port + function circle_in_viewport(center, radius, visible) + { + for (var i = 0; i < 128; ++i) { + var azimuth = 360.0 * i / 128.0; + var coord = center.atDistanceAndAzimuth(radius,azimuth) + if (coord.isValid) + verify(is_coord_on_screen(coord) === visible, visible ? + "circle not visible" : "circle visible") + } + } + + function test_fit_circle_to_viewport(data) + { + verify(!is_coord_on_screen(data.center)) + circle_in_viewport(data.center, data.radius, false) + map.visibleRegion = QtPositioning.circle(data.center, data.radius) + circle_in_viewport(data.center, data.radius, true) + } + + function test_fit_circle_to_viewport_data() + { + return [ + { tag: "circle 1", center: + QtPositioning.coordinate(70,70), radius: 10 }, + { tag: "circle 2", center: + QtPositioning.coordinate(80,30), radius: 2000000 }, + { tag: "circle 3", center: + QtPositioning.coordinate(-82,30), radius: 2000000 }, + { tag: "circle 4", center: + QtPositioning.coordinate(60,179), radius: 20000 }, + { tag: "circle 5", center: + QtPositioning.coordinate(60,-179), radius: 20000 }, + ] + } + + function test_fit_rectangle_to_viewport(data) + { + verify(!is_coord_on_screen(data.topLeft),"rectangle visible") + verify(!is_coord_on_screen(data.bottomRight),"rectangle visible") + map.visibleRegion = QtPositioning.rectangle(data.topLeft,data.bottomRight) + verify(is_coord_on_screen(data.topLeft),"rectangle not visible") + verify(is_coord_on_screen(data.bottomRight),"rectangle not visible") + } + + function test_fit_rectangle_to_viewport_data() + { + return [ + { tag: "rectangle 1", + topLeft: QtPositioning.coordinate(80, 80), + bottomRight: QtPositioning.coordinate(78, 82) }, + { tag: "rectangle 2", + topLeft: QtPositioning.coordinate(30,-130), + bottomRight: QtPositioning.coordinate(0,-100)} + ] + } + + /*function test_ad_visible_items_move() { + // move different individual items out of screen + // then fit viewport + var xDir = 1 + var yDir = 0 + var xDirChange = -1 + var yDirChange = 1 + var dir = 0 + var move = 50 + for (dir = 0; dir < 4; dir++) { + // move rect out of screen + reset() + verify_visibility_all_items() + preMapRect.topLeft.longitude += move * xDir + preMapRect.topLeft.latitude += move * yDir + preMapRect.bottomRight.longitude += move * xDir + preMapRect.bottomRight.latitude += move * yDir + calculate_bounds() + verify(!is_coord_on_screen(preMapRect.topLeft)) + verify(!is_coord_on_screen(preMapRect.bottomRight)) + map.fitViewportToMapItems() + visualInspectionPoint() + verify_visibility_all_items() + + // move circle out of screen + reset() + verify_visibility_all_items() + preMapCircle.center.longitude += move * xDir + preMapCircle.center.latitude += move * yDir + calculate_bounds() + verify(!is_coord_on_screen(mapCircleTopLeft)) + verify(!is_coord_on_screen(mapCircleBottomRight)) + map.fitViewportToMapItems() + visualInspectionPoint() + verify_visibility_all_items() + + // move quick item out of screen + reset() + verify_visibility_all_items() + preMapQuickItem.coordinate.longitude += move * xDir + preMapQuickItem.coordinate.latitude += move * yDir + calculate_bounds() + verify(!is_coord_on_screen(mapQuickItemTopLeft)) + verify(!is_coord_on_screen(mapQuickItemBottomRight)) + map.fitViewportToMapItems() + visualInspectionPoint() + verify_visibility_all_items() + + // move map polygon out of screen + reset() + verify_visibility_all_items() + var i + for (i = 0; i < preMapPolygonDefaultPath.length; ++i) { + preMapPolygon.path[i].longitude += move * xDir + preMapPolygon.path[i].latitude += move * yDir + } + calculate_bounds() + verify(!is_coord_on_screen(mapPolygonTopLeft)) + verify(!is_coord_on_screen(mapPolygonBottomRight)) + map.fitViewportToMapItems() + visualInspectionPoint() + verify_visibility_all_items() + if (dir == 2) + xDirChange *= -1 + if (dir == 1) + yDirChange *= -1 + xDir += xDirChange + yDir += yDirChange + } + }*/ + + function clear_data() { + preMapRectClicked.clear() + preMapCircleClicked.clear() + preMapQuickItemClicked.clear() + preMapPolygonClicked.clear() + preMapCircleCenterChanged.clear() + preMapCircleColorChanged.clear() + preMapCircleRadiusChanged.clear() + preMapCircleBorderColorChanged.clear() + preMapCircleBorderWidthChanged.clear() + preMapRectTopLeftChanged.clear() + preMapRectBottomRightChanged.clear() + preMapRectColorChanged.clear() + preMapPolylineColorChanged.clear() + preMapPolylineWidthChanged.clear() + preMapPolylinePathChanged.clear() + preMapPolygonPathChanged.clear() + preMapPolygonColorChanged.clear() + preMapPolygonBorderColorChanged.clear() + preMapPolygonBorderWidthChanged.clear() + preMapRouteRouteChanged.clear() + preMapRouteLineColorChanged.clear() + preMapRouteLineWidthChanged.clear() + preMapQuickItemCoordinateChanged.clear() + preMapQuickItemAnchorPointChanged.clear() + preMapQuickItemZoomLevelChanged.clear() + preMapQuickItemSourceItemChanged.clear() + } + + function calculate_fit_circle_bounds() { + var circleDiagonal = Math.sqrt(2 * fitCircle.radius * fitCircle.radius) + fitCircleTopLeft = fitCircle.center.atDistanceAndAzimuth(circleDiagonal,-45) + fitCircleBottomRight = fitCircle.center.atDistanceAndAzimuth(circleDiagonal,135) + } + + function calculate_bounds(){ + var circleDiagonal = Math.sqrt(2 * preMapCircle.radius * preMapCircle.radius) + var itemTopLeft = preMapCircle.center.atDistanceAndAzimuth(circleDiagonal,-45) + var itemBottomRight = preMapCircle.center.atDistanceAndAzimuth(circleDiagonal,135) + + mapCircleTopLeft = itemTopLeft; + mapCircleBottomRight = itemBottomRight; + + itemTopLeft = preMapQuickItem.coordinate + var preMapQuickItemScreenPosition = map.fromCoordinate(preMapQuickItem.coordinate) + preMapQuickItemScreenPosition.x += preMapQuickItem.sourceItem.width + preMapQuickItemScreenPosition.y += preMapQuickItem.sourceItem.height + itemBottomRight = map.toCoordinate(preMapQuickItemScreenPosition) + + mapQuickItemTopLeft = itemTopLeft; + mapQuickItemBottomRight = itemBottomRight; + + var bounds = min_max_bounds_from_list(preMapPolygon.path) + mapPolygonTopLeft = bounds.topLeft; + mapPolygonBottomRight = bounds.bottomRight; + + bounds = min_max_bounds_from_list(preMapPolyline.path) + mapPolylineTopLeft = bounds.topLeft; + mapPolylineBottomRight = bounds.bottomRight; + + bounds = min_max_bounds_from_list(preMapRoute.route.path) + mapRouteTopLeft = bounds.topLeft; + mapRouteBottomRight = bounds.bottomRight; + } + + function min_max_bounds_from_list(coorindates){ + var i = 0 + var point = map.fromCoordinate(coorindates[0]) + var minX = point.x + var minY = point.y + var maxX = point.x + var maxY = point.y + + for (i=1; i < coorindates.length; ++i) { + point = map.fromCoordinate(coorindates[i]) + if (point.x < minX) + minX = point.x + if (point.x > maxX) + maxX = point.x + if (point.y < minY) + minY = point.y + if (point.y > maxY) + maxY = point.y + } + point.x = minX + point.y = minY + var itemTopLeft = map.toCoordinate(point) + point.x = maxX + point.y = maxY + var itemBottomRight = map.toCoordinate(point) + + return QtPositioning.rectangle(itemTopLeft, itemBottomRight); + } + + function verify_visibility_all_items(){ + calculate_bounds() + verify(is_coord_on_screen(preMapRect.topLeft)) + verify(is_coord_on_screen(preMapRect.bottomRight)) + verify(is_coord_on_screen(mapCircleTopLeft)) + verify(is_coord_on_screen(mapCircleBottomRight)) + verify(is_coord_on_screen(mapPolygonTopLeft)) + verify(is_coord_on_screen(mapPolygonBottomRight)) + verify(is_coord_on_screen(mapQuickItemTopLeft)) + verify(is_coord_on_screen(mapQuickItemBottomRight)) + verify(is_coord_on_screen(mapPolylineTopLeft)) + verify(is_coord_on_screen(mapPolylineBottomRight)) + verify(is_coord_on_screen(mapRouteTopLeft)) + verify(is_coord_on_screen(mapRouteBottomRight)) + } + + + function is_coord_on_screen(coord) { + return is_point_on_screen(map.fromCoordinate(coord)) + } + + function is_point_on_screen(point) { + if (point.x >= 0 && point.x <= (map.x + map.width) + && point.y >=0 && point.y <= (map.y + map.height) ) + return true; + else + return false; + } + + function fuzzy_compare(val, ref, tol) { + var tolerance = 2 + if (tol !== undefined) + tolerance = tol + if ((val >= ref - tolerance) && (val <= ref + tolerance)) + return true; + console.log('map fuzzy cmp returns false for value, ref, tolerance: ' + val + ', ' + ref + ', ' + tolerance) + return false; + } + + // call to visualInspectionPoint testcase (for dev time visual inspection) + function visualInspectionPoint(time) { + var waitTime = 0 // 300 + if (time !== undefined) + waitTime = time + if (waitTime > 0) { + console.log('halting for ' + waitTime + ' milliseconds') + wait (waitTime) + } + } + } +} + diff --git a/tests/auto/declarative_ui/tst_map_itemview.qml b/tests/auto/declarative_ui/tst_map_itemview.qml new file mode 100644 index 0000000..db788ac --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_itemview.qml @@ -0,0 +1,490 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.6 +import QtPositioning 5.5 +import QtLocation.Test 5.5 + +Item { + id: masterItem + width: 200 + height: 350 + // General-purpose elements for the test: + Plugin { id: testPlugin; name : "qmlgeo.test.plugin"; allowExperimental: true } + + property variant mapDefaultCenter: QtPositioning.coordinate(10, 30) + + Map { + id: map + objectName: 'staticallyDeclaredMap' + center: mapDefaultCenter; + plugin: testPlugin; + width: 100 + height: 100 + zoomLevel: 2 + MapCircle { + id: prepopulatedCircle + objectName: 'prepopulatedCircle' + center: mapDefaultCenter; + radius: 100 + } + } + + Map { + id: map3 + objectName: 'staticallyDeclaredMapWithView' + center: mapDefaultCenter; + plugin: testPlugin; + width: 100 + height: 100 + zoomLevel: 2 + MapItemView { + id: theItemView3 + model: testModel3 + delegate: Component { + MapCircle { + radius: 1500000 + center { + latitude: modeldata.coordinate.latitude + longitude: modeldata.coordinate.longitude + } + } + } + } + } + + MapCircle { + id: externalCircle + objectName: 'externalCircle' + radius: 200 + center: mapDefaultCenter + } + + SignalSpy {id: mapItemSpy; target: map; signalName: 'mapItemsChanged'} + + + MapCircle { + objectName: "externalCircle2" + id: externalCircle2 + radius: 2000000 + center: mapDefaultCenter + } + + MapCircle { + objectName: "externalCircle3" + id: externalCircle3 + radius: 2000000 + center: mapDefaultCenter + } + + MapRectangle { + objectName: "externalRectangle" + id: externalRectangle + } + + MapPolygon { + objectName: "externalPolygon" + id: externalPolygon + } + + MapPolyline { + objectName: 'externalPolyline' + id: externalPolyline + } + + MapQuickItem { + objectName: 'externalQuickItem' + id: externalQuickItem + sourceItem: Rectangle {} + } + + TestModel { + id: testModel + datatype: 'coordinate' + datacount: 7 + delay: 0 + } + + TestModel { + id: testModel2 + datatype: 'coordinate' + datacount: 3 + delay: 0 + } + + TestModel { + id: testModel3 + datatype: 'coordinate' + datacount: 0 + delay: 0 + } + + Plugin { + id: testPlugin_immediate; + name: "qmlgeo.test.plugin" + allowExperimental: true + parameters: [ + // Parms to guide the test plugin + PluginParameter { name: "gc_supported"; value: true}, + PluginParameter { name: "gc_finishRequestImmediately"; value: true}, + PluginParameter { name: "gc_validateWellKnownValues"; value: true} + ] + } + RouteQuery {id: routeQuery; + waypoints: [ + { latitude: 60, longitude: 60 }, + { latitude: 61, longitude: 62 }, + { latitude: 63, longitude: 64 }, + { latitude: 65, longitude: 66 }, + { latitude: 67, longitude: 68 } + ] + } + + RouteModel {id: routeModel; plugin: testPlugin_immediate; query: routeQuery } + SignalSpy {id: mapItemsChangedSpy; target: mapForTestingRouteModel; signalName: "mapItemsChanged"} + + Map { + id: mapForView + + property int mapItemsLength: mapItems.length + + center: mapDefaultCenter + plugin: testPlugin + anchors.fill: parent + zoomLevel: 2 + + MapCircle { + id: internalCircle + radius: 2000000 + center: mapDefaultCenter + } + MapItemView { + id: theItemView + model: testModel + delegate: Component { + id: theItemViewsComponent + MapCircle { + radius: 1500000 + center { + latitude: modeldata.coordinate.latitude + longitude: modeldata.coordinate.longitude + } + } + } + } + } + + Map { + id: mapForTestingListModel + + center: mapDefaultCenter + plugin: testPlugin + anchors.fill: parent + zoomLevel: 2 + + property int mapItemsLength: mapItems.length + property variant itemCoordinates: [ + QtPositioning.coordinate(11, 31), + QtPositioning.coordinate(12, 32), + QtPositioning.coordinate(13, 33) + ] + + MapItemView { + id: listModelItemView + model: ListModel { + id: testingListModel + ListElement { lat: 11; lon: 31 } + ListElement { lat: 12; lon: 32 } + ListElement { lat: 13; lon: 33 } + } + delegate: Component { + MapCircle { + radius: 1500000 + center { + latitude: lat + longitude: lon + } + } + } + } + } + + Map { + id: mapForTestingRouteModel + + property int mapItemsLength: mapItems.length + + plugin: testPlugin + center: mapDefaultCenter + anchors.fill: parent + zoomLevel: 2 + + MapItemView { + id: routeItemView + model: routeModel + delegate: Component { + MapRoute { + route: routeData + } + } + } + } + + TestCase { + name: "MapItem" + when: windowShown + function clear_data() { + mapItemSpy.clear() + } + + function test_basics() { + compare(theItemView.delegate, theItemViewsComponent); + compare(theItemView.model, testModel); + } + + function test_aaa_basic_add_remove() { // aaa to ensure execution first + clear_data() + compare(map.mapItems.length, 1) + compare(map.mapItems[0], prepopulatedCircle) + compare(mapItemSpy.count, 0) + // nonexistent + map.removeMapItem(externalCircle) + compare(mapItemSpy.count, 0) + compare(map.mapItems.length, 1) + compare(map.mapItems[0], prepopulatedCircle) + // real + map.removeMapItem(prepopulatedCircle) + compare(mapItemSpy.count, 1) + compare(map.mapItems.length, 0) + map.addMapItem(externalCircle) + map.addMapItem(prepopulatedCircle) + compare(mapItemSpy.count, 3) + compare(map.mapItems.length, 2) + // same again + map.addMapItem(prepopulatedCircle) + compare(mapItemSpy.count, 3) + compare(map.mapItems.length, 2) + compare(map.mapItems[0], externalCircle) + compare(map.mapItems[1], prepopulatedCircle) + map.removeMapItem(externalCircle) + compare(map.mapItems[0], prepopulatedCircle) + compare(mapItemSpy.count, 4) + compare(map.mapItems.length, 1) + map.clearMapItems() + compare(mapItemSpy.count, 5) + compare(map.mapItems.length, 0) + // empty map, do not crash + map.clearMapItems() + compare(mapItemSpy.count, 5) + compare(map.mapItems.length, 0) + } + + function test_dynamic_map_and_items() { + clear_data(); + /* + // basic create-destroy without items, mustn't crash + var dynamicMap = Qt.createQmlObject('import QtQuick 2.0; import QtLocation 5.3; Map { x:0; y:0; objectName: \'dynomik map\'; width: masterItem.width; height: masterItem.height; plugin: testPlugin} ', masterItem, "dynamicCreationErrors" ); + verify(dynamicMap !== null) + dynamicMap.destroy(1) + //wait(5) + + // add rm add, destroy with item on it + dynamicMap = Qt.createQmlObject('import QtQuick 2.0; import QtLocation 5.3; Map { x:0; y:0; objectName: \'dynomik map\'; width: masterItem.width; height: masterItem.height; plugin: testPlugin} ', masterItem, "dynamicCreationErrors" ); + verify(dynamicMap !== null) + dynamicMap.addMapItem(externalCircle); + compare(dynamicMap.mapItems.length, 1) + dynamicMap.removeMapItem(externalCircle); + compare(dynamicMap.mapItems.length, 0) + dynamicMap.addMapItem(externalCircle); + compare(dynamicMap.mapItems.length, 1) + dynamicMap.destroy(1) + //wait(5) + + // try adding same item to two maps, will not be allowed + var dynamicMap2 = Qt.createQmlObject('import QtQuick 2.0; import QtLocation 5.3; Map { x:0; y:0; objectName: \'dynomik map2\'; width: masterItem.width; height: masterItem.height; plugin: testPlugin} ', masterItem, "dynamicCreationErrors" ); + dynamicMap = Qt.createQmlObject('import QtQuick 2.0; import QtLocation 5.3; Map { x:0; y:0; objectName: \'dynomik map\'; width: masterItem.width; height: masterItem.height; plugin: testPlugin} ', masterItem, "dynamicCreationErrors" ); + verify(dynamicMap !== null) + verify(dynamicMap2 !== null) + compare(dynamicMap.mapItems.length, 0) + dynamicMap.addMapItem(externalCircle3); + compare(dynamicMap.mapItems.length, 1) + dynamicMap2.addMapItem(externalCircle3); + compare(dynamicMap2.mapItems.length, 0) + + // create and destroy a dynamic item that is in the map + var dynamicCircle = Qt.createQmlObject('import QtQuick 2.0; import QtLocation 5.3; MapCircle { objectName: \'dynamic circle 1\'; center { latitude: 5; longitude: 5 } radius: 15 } ', masterItem, "dynamicCreationErrors" ); + verify (dynamicCircle !== null) + compare(map.mapItems.length, 0) + map.addMapItem(dynamicCircle) + compare(mapItemSpy.count, 1) + compare(map.mapItems.length, 1) + dynamicCircle.destroy(1) + tryCompare(mapItemSpy, "count", 2) + compare(map.mapItems.length, 0) + + // leave one map item, will be destroyed at the end of the case + dynamicMap.addMapItem(externalCircle); + compare(dynamicMap.mapItems.length, 2) + + // leave a handful of item from model to the map and let it destroy + compare(map3.mapItems.length, 0) + testModel3.datacount = 4 + testModel3.update() + compare(map3.mapItems.length, 4) + */ + } + + function test_add_and_remove_with_view() { + // Basic adding and removing of static object + tryCompare(mapForView, "mapItemsLength", 8) // 1 declared and 7 from model + mapForView.addMapItem(internalCircle) + compare(mapForView.mapItems.length, 8) + mapForView.removeMapItem(internalCircle) + compare(mapForView.mapItems.length, 7) + mapForView.removeMapItem(internalCircle) + compare(mapForView.mapItems.length, 7) + // Basic adding and removing of dynamic object + var dynamicCircle = Qt.createQmlObject( "import QtQuick 2.0; import QtLocation 5.3; MapCircle {radius: 4000; center: mapDefaultCenter}", map, ""); + mapForView.addMapItem(dynamicCircle) + compare(mapForView.mapItems.length, 8) + mapForView.removeMapItem(dynamicCircle) + compare(mapForView.mapItems.length, 7) + mapForView.removeMapItem(dynamicCircle) + compare(mapForView.mapItems.length, 7) + } + SignalSpy {id: model1Spy; target: testModel; signalName: "modelChanged"} + SignalSpy {id: model2Spy; target: testModel2; signalName: "modelChanged"} + function test_model_change() { + // Ensure that internalCircle is removed + mapForView.removeMapItem(internalCircle) + + // Change the model of an MapItemView on the fly + // and verify that object counts change accordingly. + testModel.datacount = 7 + testModel.update() + + tryCompare(mapForView, "mapItemsLength", 7) + testModel.datacount += 2 + testModel2.datacount += 1 + // delegate spawning is async. wait a bit. + wait(1) + tryCompare(mapForView, "mapItemsLength", 9) + + theItemView.model = testModel + compare(mapForView.mapItems.length, 9) + theItemView.model = testModel2 + tryCompare(mapForView, "mapItemsLength", 4) + } + + function test_listmodel() { + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + + for (var i = 0; i < 3; ++i) { + var itemCoord = mapForTestingListModel.mapItems[i].center + var index = mapForTestingListModel.itemCoordinates.indexOf(itemCoord) + verify(0 <= index && index < 3) + } + + testingListModel.remove(0) + compare(mapForTestingListModel.mapItems.length, 2) + + for (var i = 0; i < 2; ++i) { + itemCoord = mapForTestingListModel.mapItems[i].center + index = mapForTestingListModel.itemCoordinates.indexOf(itemCoord) + verify(1 <= index && index < 3) + } + + testingListModel.append({ lat: 1, lon: 1 }) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + compare(mapForTestingListModel.mapItems[2].center, QtPositioning.coordinate(1, 1)) + + testingListModel.clear() + compare(mapForTestingListModel.mapItems.length, 0) + } + + function test_routemodel() { + testModel.reset(); + mapItemsChangedSpy.clear() + compare(mapForTestingRouteModel.mapItems.length, 0) // precondition + compare(mapItemsChangedSpy.count, 0) + routeQuery.numberAlternativeRoutes = 4 + routeModel.update(); + tryCompare(mapForTestingRouteModel, "mapItemsLength", 4) + routeQuery.numberAlternativeRoutes = 3 + routeModel.update(); + tryCompare(mapForTestingRouteModel, "mapItemsLength", 3) + routeModel.reset(); + compare(mapForTestingRouteModel.mapItems.length, 0) + routeModel.reset(); // clear empty model + routeQuery.numberAlternativeRoutes = 3 + routeModel.update(); + tryCompare(mapForTestingRouteModel, "mapItemsLength", 3) + mapForTestingRouteModel.addMapItem(externalCircle2) + compare(mapForTestingRouteModel.mapItems.length, 4) + compare(mapForTestingRouteModel.mapItems[3], externalCircle2) + routeModel.reset(); + compare(mapForTestingRouteModel.mapItems.length, 1) + mapForTestingRouteModel.clearMapItems() + compare(mapForTestingRouteModel.mapItems.length, 0) + + // Test the mapItems list + mapForTestingRouteModel.addMapItem(externalCircle2) + compare(mapForTestingRouteModel.mapItems.length, 1) + compare(mapForTestingRouteModel.mapItems[0], externalCircle2) + + mapForTestingRouteModel.addMapItem(externalRectangle) + compare(mapForTestingRouteModel.mapItems.length, 2) + compare(mapForTestingRouteModel.mapItems[1], externalRectangle) + + mapForTestingRouteModel.addMapItem(externalRectangle) + compare(mapForTestingRouteModel.mapItems.length, 2) + compare(mapForTestingRouteModel.mapItems[1], externalRectangle) + + mapForTestingRouteModel.addMapItem(externalPolygon) + compare(mapForTestingRouteModel.mapItems.length, 3) + compare(mapForTestingRouteModel.mapItems[2], externalPolygon) + + mapForTestingRouteModel.addMapItem(externalQuickItem) + compare(mapForTestingRouteModel.mapItems.length, 4) + compare(mapForTestingRouteModel.mapItems[3], externalQuickItem) + + mapForTestingRouteModel.removeMapItem(externalCircle2) + compare(mapForTestingRouteModel.mapItems.length, 3) + compare(mapForTestingRouteModel.mapItems[0], externalRectangle) + + mapForTestingRouteModel.removeMapItem(externalRectangle) + compare(mapForTestingRouteModel.mapItems.length, 2) + compare(mapForTestingRouteModel.mapItems[0], externalPolygon) + + mapForTestingRouteModel.clearMapItems() + compare(mapForTestingRouteModel.mapItems.length, 0) + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_keepgrab.qml b/tests/auto/declarative_ui/tst_map_keepgrab.qml new file mode 100644 index 0000000..fa47eec --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_keepgrab.qml @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtTest 1.0 +import QtLocation 5.6 +import QtPositioning 5.5 + +Item { + // General-purpose elements for the test: + id: page + width: 200 + height: 200 + Plugin { id: testPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true } + + + Flickable { + id: flickable + anchors.fill: parent + contentWidth: flickable.width * 4; contentHeight: flickable.height + + Map { + id: map + x: flickable.width + height: flickable.height + width:flickable.width + plugin: testPlugin + } + } + + SignalSpy { id: mapPanStartedSpy; target: map.gesture; signalName: 'panStarted' } + SignalSpy { id: mapPanFinishedSpy; target: map.gesture; signalName: 'panFinished' } + SignalSpy { id: flickStartedSpy; target: flickable; signalName: 'flickStarted' } + SignalSpy { id: flickEndedSpy; target: flickable; signalName: 'flickEnded' } + SignalSpy { id: preventStealingChangedSpy; target: map.gesture; signalName: 'preventStealingChanged' } + + + TestCase { + when: windowShown + name: "MapKeepGrabAndPreventSteal" + + function initTestCase() + { + compare(map.gesture.preventStealing, false) + } + + function init() + { + map.gesture.acceptedGestures = MapGestureArea.PanGesture | MapGestureArea.FlickGesture; + map.gesture.flickDeceleration = 500 + map.zoomLevel = 1 + map.center = QtPositioning.coordinate(50,50) + map.gesture.preventStealing = false + flickable.contentX = 0 + flickable.contentY = 0 + mapPanStartedSpy.clear() + mapPanFinishedSpy.clear() + flickStartedSpy.clear() + flickEndedSpy.clear() + preventStealingChangedSpy.clear() + } + + function flick() + { + var i = 0 + mousePress(flickable, flickable.width - 1, 0) + for (i = flickable.width; i > 0; i -= 5) { + wait(5) + mouseMove(flickable, i, 0, 0, Qt.LeftButton); + } + mouseRelease(flickable, i, 0) + } + + function pan() + { + var i = 0 + mousePress(map, 0, 0) + for (i = 0; i < flickable.width; i += 5) { + wait(5) + mouseMove(map, i, 0, 0, Qt.LeftButton); + } + mouseRelease(map, i, 0) + } + + function test_flick() + { + var center = QtPositioning.coordinate(map.center.latitude,map.center.longitude) + flick() //flick flickable + tryCompare(flickStartedSpy,"count",1) + pan() //pan map + tryCompare(flickStartedSpy,"count",2) // both directions + tryCompare(flickEndedSpy,"count",1) + tryCompare(mapPanStartedSpy,"count", 0) + tryCompare(mapPanFinishedSpy,"count", 0) + //map should not change + verify(center == map.center) + } + + function test_map_grab() + { + var center = QtPositioning.coordinate(map.center.latitude,map.center.longitude) + pan() //pan map + tryCompare(mapPanStartedSpy,"count",1) + tryCompare(mapPanFinishedSpy, "count", 1) + + compare(flickStartedSpy.count, 0) + compare(flickEndedSpy.count, 0) + //map should change + verify(center != map.center) + } + + function test_map_preventsteal() + { + map.gesture.preventStealing = false + compare(preventStealingChangedSpy.count, 0) + map.gesture.preventStealing = true + compare(preventStealingChangedSpy.count, 1) + + var center = QtPositioning.coordinate(map.center.latitude,map.center.longitude) + flick() //flick flickable + tryCompare(flickStartedSpy,"count",1) + pan() //pan map + tryCompare(flickStartedSpy,"count",1) // both directions + tryCompare(flickEndedSpy,"count",1) + tryCompare(mapPanStartedSpy,"count", 1) + tryCompare(mapPanFinishedSpy,"count", 1) + //map should not change + verify(center != map.center) + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_maptype.qml b/tests/auto/declarative_ui/tst_map_maptype.qml new file mode 100644 index 0000000..fa056c4 --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_maptype.qml @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.6 + +Item{ + id: page + x: 0; y: 0; + width: 100 + height: 100 + + Plugin { id: testPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true } + Map { id: map; anchors.fill: parent } + SignalSpy { id: supportedMapTypesSpy; target: map; signalName: "supportedMapTypesChanged" } + SignalSpy { id: activeMapTypeChangedSpy; target: map; signalName: "activeMapTypeChanged" } + + TestCase { + id: testCase + name: "MapType" + when: windowShown + + function initTestCase() + { + compare(map.supportedMapTypes.length, 0) + compare(map.activeMapType.style, MapType.NoMap) + map.plugin = testPlugin + tryCompare(supportedMapTypesSpy, "count", 1) + compare(map.supportedMapTypes.length,3) + compare(map.supportedMapTypes[0].style, MapType.StreetMap) + compare(map.supportedMapTypes[0].name, "StreetMap") + compare(map.supportedMapTypes[0].description, "StreetMap") + compare(map.supportedMapTypes[1].style, MapType.SatelliteMapDay) + compare(map.supportedMapTypes[1].name, "SatelliteMapDay") + compare(map.supportedMapTypes[1].description, "SatelliteMapDay") + compare(map.supportedMapTypes[2].style, MapType.CycleMap) + compare(map.supportedMapTypes[2].name, "CycleMap") + compare(map.supportedMapTypes[2].description, "CycleMap") + //default + compare(map.activeMapType.style, MapType.StreetMap) + } + + function init() + { + supportedMapTypesSpy.clear() + activeMapTypeChangedSpy.clear() + map.activeMapType = map.supportedMapTypes[0] + } + + function test_setting_types() + { + map.activeMapType = map.supportedMapTypes[0] + tryCompare(activeMapTypeChangedSpy, "count", 0) + + map.activeMapType = map.supportedMapTypes[1] + tryCompare(activeMapTypeChangedSpy, "count", 1) + compare(map.supportedMapTypes[1].name, map.activeMapType.name) + compare(map.supportedMapTypes[1].style, map.activeMapType.style) + + map.activeMapType = map.supportedMapTypes[2] + tryCompare(activeMapTypeChangedSpy, "count", 2) + compare(map.supportedMapTypes[2].name, map.activeMapType.name) + compare(map.supportedMapTypes[2].style, map.activeMapType.style) + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_mouse.qml b/tests/auto/declarative_ui/tst_map_mouse.qml new file mode 100644 index 0000000..99aff03 --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_mouse.qml @@ -0,0 +1,723 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtLocation 5.6 +import QtPositioning 5.5 + + /* + MouseArea setup for this test case. + Map dimensions are 100 * 100 + Item containing map is 120,120 + + (50,50) + (0,0) ---------------------------------------------------- (100,0) + | no mouse area | mouse area overlapper | + | | | + (0,20) ---------------------------------------------------- (100,20) + | mouse area upper | mouse area upper, | + | | mouse area overlapper | + | | | + | | | + | | | + (0,50) ---------------------------------------------------- (100,50) + | mouse area lower | mouse area lower, | + | | mouse area overlapper | + | | | + | | | + | | | + | | | + | | | + | | | + (0,100) ---------------------------------------------------- (100,100) | + | + | + ----------(120, 120) + + */ + +Item { + id: page + x: 0; y: 0; + width: 120 + height: 120 + // General-purpose elements for the test: + Plugin { id: testPlugin; name : "qmlgeo.test.plugin"; allowExperimental: true } + + function setMouseData(ma, me) + { + ma.lastX = me.x + ma.lastY = me.y + ma.lastButton = me.button + ma.lastButtons = me.buttons + ma.lastModifiers = me.modifiers + ma.lastWasHeld = me.wasHeld + ma.lastIsClick = me.isClick + ma.lastAccepted = me.accepted + } + + Map { + id: map; + x: 0; y: 0; width: 100; height: 100 + center { + latitude: 20 + longitude: 20 + } + + plugin: testPlugin; + + MouseArea { + id: mouseUpper + objectName: "mouseUpper" + x: 0; y: 20; width: 100; height: 29 + property int lastX: -1 + property int lastY: -1 + property int lastButton: Qt.NoButton + property int lastButtons: Qt.NoButton + property int lastModifiers: Qt.NoModifier + property bool lastWasHeld: false; + property bool lastIsClick: false + property bool lastAccepted: false; + + preventStealing: true + + // The following signal handlers use arguments[0] instead of mouse due to QTBUG-36560 + onClicked: page.setMouseData(mouseUpper, arguments[0]) + onDoubleClicked: page.setMouseData(mouseUpper, arguments[0]) + onPressed: page.setMouseData(mouseUpper, arguments[0]) + onReleased: page.setMouseData(mouseUpper, arguments[0]) + onPositionChanged: page.setMouseData(mouseUpper, arguments[0]) + onPressAndHold: page.setMouseData(mouseUpper, arguments[0]) + } + MouseArea { + id: mouseLower + objectName: "mouseLower" + x: 0; y: 50; width: 100; height: 50 + property int lastX: -1 + property int lastY: -1 + property int lastButton: Qt.NoButton + property int lastButtons: Qt.NoButton + property int lastModifiers: Qt.NoModifier + property bool lastWasHeld: false; + property bool lastIsClick: false + property bool lastAccepted: false; + + // The following signal handlers use arguments[0] instead of mouse due to QTBUG-36560 + onClicked: page.setMouseData(mouseLower, arguments[0]) + onDoubleClicked: page.setMouseData(mouseLower, arguments[0]) + onPressed: page.setMouseData(mouseLower, arguments[0]) + onReleased: page.setMouseData(mouseLower, arguments[0]) + onPositionChanged: page.setMouseData(mouseLower, arguments[0]) + onPressAndHold: page.setMouseData(mouseLower, arguments[0]) + } + MouseArea { + id: mouseOverlapper + objectName: "mouseOverlapper" + x: 50; y: 0; width: 50; height: 100 + property int lastX: -1 + property int lastY: -1 + property int lastButton: Qt.NoButton + property int lastButtons: Qt.NoButton + property int lastModifiers: Qt.NoModifier + property bool lastWasHeld: false; + property bool lastIsClick: false + property bool lastAccepted: false; + + // The following signal handlers use arguments[0] instead of mouse due to QTBUG-36560 + onClicked: page.setMouseData(mouseOverlapper, arguments[0]) + onDoubleClicked: page.setMouseData(mouseOverlapper, arguments[0]) + onPressed: page.setMouseData(mouseOverlapper, arguments[0]) + onReleased: page.setMouseData(mouseOverlapper, arguments[0]) + onPositionChanged: page.setMouseData(mouseOverlapper, arguments[0]) + onPressAndHold: page.setMouseData(mouseOverlapper, arguments[0]) + } + } + + TestCase { + name: "MouseArea" + when: windowShown + SignalSpy {id: mouseUpperClickedSpy; target: mouseUpper; signalName: "clicked"} + SignalSpy {id: mouseLowerClickedSpy; target: mouseLower; signalName: "clicked"} + SignalSpy {id: mouseOverlapperClickedSpy; target: mouseOverlapper; signalName: "clicked"} + SignalSpy {id: mouseUpperDoubleClickedSpy; target: mouseUpper; signalName: "doubleClicked"} + SignalSpy {id: mouseLowerDoubleClickedSpy; target: mouseLower; signalName: "doubleClicked"} + SignalSpy {id: mouseOverlapperDoubleClickedSpy; target: mouseOverlapper; signalName: "doubleClicked"} + SignalSpy {id: mouseUpperPressedSpy; target: mouseUpper; signalName: "onPressed"} + SignalSpy {id: mouseLowerPressedSpy; target: mouseLower; signalName: "onPressed"} + SignalSpy {id: mouseOverlapperPressedSpy; target: mouseOverlapper; signalName: "onPressed"} + SignalSpy {id: mouseUpperReleasedSpy; target: mouseUpper; signalName: "released"} + SignalSpy {id: mouseLowerReleasedSpy; target: mouseLower; signalName: "released"} + SignalSpy {id: mouseOverlapperReleasedSpy; target: mouseOverlapper; signalName: "released"} + SignalSpy {id: mouseUpperPositionChangedSpy; target: mouseUpper; signalName: "positionChanged"} + SignalSpy {id: mouseLowerPositionChangedSpy; target: mouseLower; signalName: "positionChanged"} + SignalSpy {id: mouseOverlapperPositionChangedSpy; target: mouseOverlapper; signalName: "positionChanged"} + SignalSpy {id: mouseUpperPressAndHoldSpy; target: mouseUpper; signalName: "pressAndHold"} + SignalSpy {id: mouseLowerPressAndHoldSpy; target: mouseLower; signalName: "pressAndHold"} + SignalSpy {id: mouseOverlapperPressAndHoldSpy; target: mouseOverlapper; signalName: "pressAndHold"} + SignalSpy {id: mouseUpperEnteredSpy; target: mouseUpper; signalName: "entered"} + SignalSpy {id: mouseLowerEnteredSpy; target: mouseLower; signalName: "entered"} + SignalSpy {id: mouseOverlapperEnteredSpy; target: mouseOverlapper; signalName: "entered"} + SignalSpy {id: mouseUpperExitedSpy; target: mouseUpper; signalName: "exited"} + SignalSpy {id: mouseLowerExitedSpy; target: mouseLower; signalName: "exited"} + SignalSpy {id: mouseOverlapperExitedSpy; target: mouseOverlapper; signalName: "exited"} + + SignalSpy {id: mouseUpperEnabledChangedSpy; target: mouseUpper; signalName: "enabledChanged"} + SignalSpy {id: mouseUpperAcceptedButtonsChangedSpy; target: mouseUpper; signalName: "acceptedButtonsChanged"} + SignalSpy {id: mouseUpperPressedButtonsChangedSpy; target: mouseUpper; signalName: "pressedChanged"} + SignalSpy {id: mouseUpperHoveredChangedSpy; target: mouseUpper; signalName: "hoveredChanged"} + SignalSpy {id: mouseUpperPressedChangedSpy; target: mouseUpper; signalName: "pressedChanged"} + + SignalSpy {id: mouseOverlapperEnabledChangedSpy; target: mouseOverlapper; signalName: "enabledChanged"} + + function clear_data() { + mouseUpperClickedSpy.clear() + mouseLowerClickedSpy.clear() + mouseOverlapperClickedSpy.clear() + mouseUpperDoubleClickedSpy.clear() + mouseLowerDoubleClickedSpy.clear() + mouseOverlapperDoubleClickedSpy.clear() + mouseUpperPressedSpy.clear() + mouseLowerPressedSpy.clear() + mouseOverlapperPressedSpy.clear() + mouseUpperReleasedSpy.clear() + mouseLowerReleasedSpy.clear() + mouseOverlapperReleasedSpy.clear() + mouseUpperPositionChangedSpy.clear() + mouseLowerPositionChangedSpy.clear() + mouseOverlapperPositionChangedSpy.clear() + mouseUpperPressAndHoldSpy.clear() + mouseLowerPressAndHoldSpy.clear() + mouseOverlapperPressAndHoldSpy.clear() + mouseUpperEnteredSpy.clear() + mouseLowerEnteredSpy.clear() + mouseOverlapperEnteredSpy.clear() + mouseUpperExitedSpy.clear() + mouseLowerExitedSpy.clear() + mouseOverlapperExitedSpy.clear() + + mouseUpperEnabledChangedSpy.clear() + mouseUpperAcceptedButtonsChangedSpy.clear() + mouseUpperPressedButtonsChangedSpy.clear() + mouseUpperHoveredChangedSpy.clear() + mouseUpperPressedChangedSpy.clear() + mouseUpperPositionChangedSpy.clear() + + mouseOverlapperEnabledChangedSpy.clear() + } + // these 'real_' prefixed functions do sequences as + // it would occur on real app (e.g. doubleclick is in fact + // a sequence of press, release, doubleclick, release). + // (they were recorded as seen on test app). mouseClick() works ok + // because testlib internally converts it to mousePress + mouseRelease events + function real_click (target, x, y) { + mousePress(target, x,y) + mouseRelease(target, x, y) + } + function real_double_click (target, x, y) { + mousePress(target, x,y) + mouseRelease(target, x, y) + mousePress(target, x, y) + mouseDoubleClick(target, x, y) + mouseRelease(target, x, y) + } + function real_press_and_hold(target, x,y) { + mousePress(target,x,y) + wait(1000) // threshold is 800 ms + mouseRelease(target,x, y) + } + + function test_enabled() { + clear_data() + // check that disabling overlapping mouse areas let events flow through + mouseUpper.enabled = false + compare(mouseUpperEnabledChangedSpy.count, 1) + compare(mouseUpperClickedSpy.count, 0) + mouseClick(map, 5, 25) + compare(mouseUpperClickedSpy.count, 0) + mouseUpper.enabled = true + mouseClick(map, 5, 25) + tryCompare(mouseUpperClickedSpy, "count", 1) + compare(mouseUpperEnabledChangedSpy.count, 2) + // when overlapping are is disabled, the event should flow through + compare(mouseOverlapperClickedSpy.count, 0) + mouseClick(map, 55, 25) + tryCompare(mouseUpperClickedSpy, "count", 1) + compare(mouseOverlapperClickedSpy.count, 1) + mouseOverlapper.enabled = false + compare(mouseOverlapperEnabledChangedSpy.count, 1) + compare(mouseOverlapper.enabled, false) + mouseClick(map, 55, 25) + tryCompare(mouseOverlapperClickedSpy, "count", 1) + compare(mouseUpperClickedSpy.count, 2) + // re-enable and verify that still works + mouseOverlapper.enabled = true + compare(mouseOverlapperEnabledChangedSpy.count, 2) + compare(mouseOverlapper.enabled, true) + mouseClick(map, 55, 25) + tryCompare(mouseOverlapperClickedSpy, "count", 2) // should consume again + compare(mouseUpperClickedSpy.count, 2) + } + + function test_wheel() { + clear_data() + wait(500); + // on map but without mouse area + var startZoomLevel = 6.20 + map.zoomLevel = startZoomLevel + mouseWheel(map, 5, 5, 15, 5, Qt.LeftButton, Qt.NoModifiers) + //see QDeclarativeGeoMapGestureArea::handleWheelEvent + var endZoomLevel = startZoomLevel + 5 * 0.001 + compare(map.zoomLevel,endZoomLevel) + + map.zoomLevel = startZoomLevel + mouseWheel(map, 5, 5, -15, -5, Qt.LeftButton, Qt.NoModifiers) + //see QDeclarativeGeoMapGestureArea::handleWheelEvent + endZoomLevel = startZoomLevel - 5 * 0.001 + compare(map.zoomLevel,endZoomLevel) + + // on map on top of mouse area + map.zoomLevel = startZoomLevel + mouseWheel(map, 55, 75, -30, -2, Qt.LeftButton, Qt.NoModifiers) + endZoomLevel = startZoomLevel - 2 * 0.001 + compare(map.zoomLevel,endZoomLevel) + + // outside of map + map.zoomLevel = startZoomLevel + mouseWheel(map, -100, -100, 40, 4, Qt.LeftButton, Qt.NoModifiers) + compare(map.zoomLevel,startZoomLevel) + } + + function test_aaa_basic_properties() // _aaa_ to ensure execution first + { + clear_data() + wait(50) + // default values + compare(mouseUpper.containsMouse, false) + compare(mouseUpper.pressed, false) + compare(mouseUpper.enabled, true) + compare(mouseUpper.pressedButtons, 0) + compare(mouseUpper.acceptedButtons, Qt.LeftButton) + // accepted buttons + compare(mouseUpperAcceptedButtonsChangedSpy.count, 0) + mouseUpper.acceptedButtons = Qt.RightButton | Qt.MiddleButton + compare(mouseUpper.acceptedButtons, Qt.RightButton | Qt.MiddleButton) + compare(mouseUpperAcceptedButtonsChangedSpy.count, 1) + mouseClick(map, 5, 25) + compare(mouseUpperClickedSpy.count, 0) // left button not accepted + mouseUpper.acceptedButtons = Qt.LeftButton + compare(mouseUpperAcceptedButtonsChangedSpy.count, 2) + mouseClick(map, 5, 25) + tryCompare(mouseUpperClickedSpy, "count", 1) + } + + function test_basic_position_changed() { + // tests basic position changed/move when button is being pressed + clear_data(); + wait(500); + mousePress(map, 5, 25) + compare(mouseUpperPressedSpy.count, 1) + compare(mouseUpper.lastAccepted, true) + compare(mouseUpper.lastButton, Qt.LeftButton) + compare(mouseUpper.lastButtons, Qt.LeftButton) + compare(mouseUpper.lastModifiers, Qt.NoModifier) + // moves within the mouse area + mouseMove(map, 5, 26, 0, Qt.LeftButton) // '0' is 'delay' + wait(1) // mouseMove event goes one extra eventloop round in the test lib + compare(mouseUpperEnteredSpy.count, 1) + compare(mouseUpperPositionChangedSpy.count, 1) + compare(mouseUpper.mouseX, 5) + compare(mouseUpper.mouseY, 6) // 20 offset, mouseXY is relative to the mouse area + compare(mouseUpper.lastAccepted, true) + compare(mouseUpper.lastButton, Qt.NoButton) + compare(mouseUpper.lastButtons, Qt.LeftButton) // buttons being pressed whilst movin' + compare(mouseUpper.lastModifiers, Qt.NoModifier) + compare(mouseUpper.lastWasHeld, false) // testfunction won't take required 800 ms + compare(mouseUpper.lastX, 5) + compare(mouseUpper.lastY, 6) // remember 20 offset of the mouse area + + mouseMove(map, 6, 27, 0, Qt.LeftButton | Qt.RightButton) + wait(1) + compare(mouseUpperEnteredSpy.count, 1) // no re-entry + compare(mouseUpperPositionChangedSpy.count, 2) + compare(mouseUpper.mouseX, 6) + compare(mouseUpper.mouseY, 7) + compare(mouseUpper.lastAccepted, true) + compare(mouseUpper.lastButton, Qt.NoButton) + compare(mouseUpper.lastButtons, Qt.LeftButton | Qt.RightButton) // buttons being pressed whilst movin' + compare(mouseUpper.lastModifiers, Qt.NoModifier) + compare(mouseUpper.lastWasHeld, false) // testfunction won't take required 800 ms + compare(mouseUpper.lastX, 6) + compare(mouseUpper.lastY, 7) // remember 20 offset of the mouse area + + // moves outside of mouse but within map + mouseMove(map, 2, 2, 0) + wait(1) + compare(mouseUpperExitedSpy.count, 1) + compare(mouseUpperPositionChangedSpy.count, 3) + compare(mouseUpper.mouseX, 2) + compare(mouseUpper.mouseY, -18) + // come back to map + mouseMove(map, 7, 28, 0) + wait(1) + compare(mouseUpperEnteredSpy.count, 2) + compare(mouseUpperExitedSpy.count, 1) + compare(mouseUpperPositionChangedSpy.count, 4) + compare(mouseUpper.mouseX, 7) + compare(mouseUpper.mouseY, 8) + + // move outside of widget area (left). make sure that other mouse areas won't get the events + mouseMove(map, -10, 10, 0) + wait(1) + compare(mouseUpperPositionChangedSpy.count, 5) + compare(mouseUpperExitedSpy.count, 2) + compare(mouseUpper.mouseX, -10) + compare(mouseUpper.mouseY, -10) + + // back in and then on top of the widget + mouseMove(map, 5, 25, 0) + wait(1) + compare(mouseUpperPositionChangedSpy.count, 6) + compare(mouseUpperExitedSpy.count, 2) + compare(mouseUpperEnteredSpy.count, 3) + compare(mouseUpper.mouseX, 5) + compare(mouseUpper.mouseY, 5) + mouseMove(map, 5, -25, 0) + wait(1) + compare(mouseUpperPositionChangedSpy.count, 7) + compare(mouseUpperExitedSpy.count, 3) + compare(mouseUpperEnteredSpy.count, 3) + compare(mouseUpper.mouseX, 5) + compare(mouseUpper.mouseY, -45) + + // back in then float on top of other mouse areas + mouseMove(map, 5, 25, 0) + wait(1) + compare(mouseUpperPositionChangedSpy.count, 8) + compare(mouseUpperExitedSpy.count, 3) + compare(mouseUpperEnteredSpy.count, 4) + compare(mouseUpper.mouseX, 5) + compare(mouseUpper.mouseY, 5) + mouseMove(map, 5, 75, 0) + wait(1) + compare(mouseUpperPositionChangedSpy.count, 9) + compare(mouseUpperExitedSpy.count, 4) + compare(mouseUpperEnteredSpy.count, 4) + compare(mouseUpper.mouseX, 5) + compare(mouseUpper.mouseY, 55) // remember the 20 offset of upper mouse area + mouseMove(map, 75, 75, 0) + wait(1) + compare(mouseUpperPositionChangedSpy.count, 10) + compare(mouseUpperExitedSpy.count, 4) + compare(mouseUpperEnteredSpy.count, 4) + compare(mouseUpper.mouseX, 75) + compare(mouseUpper.mouseY, 55) + // finally back in + mouseMove(map, 5, 25, 0) + wait(1) + compare(mouseUpperPositionChangedSpy.count, 11) + compare(mouseUpperExitedSpy.count, 4) + compare(mouseUpperEnteredSpy.count, 5) + compare(mouseUpper.mouseX, 5) + compare(mouseUpper.mouseY, 5) + + // check that these fellas didn't get any stupid ideas + compare(mouseLowerEnteredSpy.count, 0) + compare(mouseLowerPositionChangedSpy.count, 0) + compare(mouseOverlapperEnteredSpy.count, 0) + compare(mouseOverlapperPositionChangedSpy.count, 0) + // release mouse + mouseRelease(map, 5, 25) + // TODO enable these! + compare(mouseUpperEnteredSpy.count, 5) + compare(mouseUpperExitedSpy.count, 5) // release triggers one more exited() + } + + function test_basic_press_release() { + clear_data() + wait(500); + // send to emptiness + mousePress(map, 5, 5) + compare(mouseUpperPressedSpy.count, 0) + compare(mouseLowerPressedSpy.count, 0) + compare(mouseOverlapperPressedSpy.count, 0) + mouseRelease(map, 5, 5) + compare(mouseUpperReleasedSpy.count, 0) + compare(mouseLowerReleasedSpy.count, 0) + compare(mouseOverlapperReleasedSpy.count, 0) + // send to upper mouse area + mousePress(map, 5, 25) + compare(mouseUpperPressedSpy.count, 1) + compare(mouseLowerPressedSpy.count, 0) + compare(mouseOverlapperPressedSpy.count, 0) + + compare(mouseUpper.lastAccepted, true) + compare(mouseUpper.lastButton, Qt.LeftButton) + compare(mouseUpper.lastModifiers, Qt.NoModifier) + compare(mouseUpper.lastWasHeld, false) + compare(mouseUpper.lastX, 5) + compare(mouseUpper.lastY, 5) // remember 20 offset of the mouse area + + mouseRelease(map, 5, 25) + compare(mouseUpperPressedSpy.count, 1) + compare(mouseUpperReleasedSpy.count, 1) + compare(mouseLowerPressedSpy.count, 0) + compare(mouseLowerReleasedSpy.count, 0) + + mousePress(map, 5, 26) + compare(mouseUpperPressedSpy.count, 2) + compare(mouseLowerPressedSpy.count, 0) + compare(mouseOverlapperPressedSpy.count, 0) + + mouseRelease(map, 5, 26) + compare(mouseUpperPressedSpy.count, 2) + compare(mouseUpperReleasedSpy.count, 2) + compare(mouseLowerPressedSpy.count, 0) + compare(mouseLowerReleasedSpy.count, 0) + compare(mouseUpper.lastAccepted, true) + compare(mouseUpper.lastButton, Qt.LeftButton) + compare(mouseUpper.lastModifiers, Qt.NoModifier) + compare(mouseUpper.lastWasHeld, false) + compare(mouseUpper.lastX, 5) + compare(mouseUpper.lastY, 6) // remember 20 offset of the mouse area + + mousePress(map, 5, 75) + compare(mouseUpperPressedSpy.count, 2) + compare(mouseLowerPressedSpy.count, 1) + compare(mouseOverlapperPressedSpy.count, 0) + compare(mouseLower.lastAccepted, true) + compare(mouseLower.lastButton, Qt.LeftButton) + compare(mouseLower.lastModifiers, Qt.NoModifier) + compare(mouseLower.lastWasHeld, false) + compare(mouseLower.lastX, 5) + compare(mouseLower.lastY, 25) // remember 50 offset of the mouse area + + mouseRelease(map, 5, 75) + compare(mouseUpperPressedSpy.count, 2) + compare(mouseUpperReleasedSpy.count, 2) + compare(mouseLowerPressedSpy.count, 1) + compare(mouseLowerReleasedSpy.count, 1) + + + compare(mouseOverlapperPressedSpy.count, 0) + mousePress(map, 55, 75) + compare(mouseUpperPressedSpy.count, 2) + compare(mouseLowerPressedSpy.count, 1) + compare(mouseOverlapperPressedSpy.count, 1) + compare(mouseOverlapperReleasedSpy.count, 0) + mouseRelease(map, 55, 25) + compare(mouseUpperPressedSpy.count, 2) + compare(mouseUpperReleasedSpy.count, 2) + compare(mouseLowerPressedSpy.count, 1) + compare(mouseLowerReleasedSpy.count, 1) + //this should follow the same logic as Flickable + compare(mouseOverlapperReleasedSpy.count, 0) + } + + function test_basic_click() { + clear_data(); + wait(500); + + mouseClick(map, 5, 5, Qt.RightButton, Qt.AltModifier) + compare(mouseUpperClickedSpy.count, 0) + compare(mouseLowerClickedSpy.count, 0) + compare(mouseOverlapperClickedSpy.count, 0) + mouseUpper.acceptedButtons = Qt.LeftButton | Qt.RightButton + // TC sending click event to upper mouse area 5,25 + mouseClick(map, 5, 25, Qt.RightButton, Qt.AltModifier) + tryCompare(mouseUpperClickedSpy, "count", 1) + // TC done and clicked was received + //compare(mouseUpperClickedSpy.count, 1) + compare(mouseLowerClickedSpy.count, 0) + compare(mouseOverlapperClickedSpy.count, 0) + compare(mouseUpper.lastAccepted, true) + compare(mouseUpper.lastButton, Qt.RightButton) + compare(mouseUpper.lastModifiers, Qt.AltModifier) + compare(mouseUpper.lastWasHeld, false) + compare(mouseUpper.lastX, 5) + compare(mouseUpper.lastY, 5) // remember 20 offset of the mouse area + // check we get valid geocoordinates (would be NaN if something was wrong) + // todo + //verify(mouseUpper.lastMouseEvent.coordinate.longitude > -180 && mouseUpper.lastMouseEvent.coordinate.longitude < 180) + //verify(mouseUpper.lastMouseEvent.coordinate.longitude > -90 && mouseUpper.lastMouseEvent.coordinate.latitude < 90) + + // mouse click with unaccepted buttons should not cause click + mouseUpper.acceptedButtons = Qt.LeftButton + mouseClick(map, 5, 25, Qt.RightButton, Qt.AltModifier) + tryCompare(mouseUpperClickedSpy, "count", 1) + compare(mouseLowerClickedSpy.count, 0) + compare(mouseOverlapperClickedSpy.count, 0) + + mouseClick(map, 5, 25) + tryCompare(mouseUpperClickedSpy, "count", 2) + compare(mouseLowerClickedSpy.count, 0) + compare(mouseOverlapperClickedSpy.count, 0) + compare(mouseUpper.lastModifiers, Qt.NoModifier) + compare(mouseUpper.lastButton, Qt.LeftButton) + mouseClick(map, 5, 55) + tryCompare(mouseUpperClickedSpy, "count", 2) + compare(mouseLowerClickedSpy.count, 1) + compare(mouseOverlapperClickedSpy.count, 0) + mouseClick(map, 5, 55) + tryCompare(mouseUpperClickedSpy,"count", 2) + compare(mouseLowerClickedSpy.count, 2) + compare(mouseOverlapperClickedSpy.count, 0) + // declaration order counts on overlap case; overlapping area + // declared later will get the events + mouseClick(map, 55, 25) + tryCompare(mouseUpperClickedSpy, "count", 2) + compare(mouseLowerClickedSpy.count, 2) + compare(mouseOverlapperClickedSpy.count, 1) + mouseClick(map, 55, 75) + tryCompare(mouseUpperClickedSpy, "count", 2) + compare(mouseLowerClickedSpy.count, 2) + compare(mouseOverlapperClickedSpy.count, 2) + real_click(map, 55, 25) + tryCompare(mouseUpperClickedSpy, "count", 2) + compare(mouseLowerClickedSpy.count, 2) + compare(mouseOverlapperClickedSpy.count, 3) + real_click(map, 55, 75) + tryCompare(mouseUpperClickedSpy, "count", 2) + compare(mouseLowerClickedSpy.count, 2) + compare(mouseOverlapperClickedSpy.count, 4) + } + + function test_basic_double_click() { + clear_data(); + wait(500); + real_double_click(map, 5, 5) + + compare(mouseUpperDoubleClickedSpy.count, 0) + compare(mouseLowerDoubleClickedSpy.count, 0) + compare(mouseOverlapperDoubleClickedSpy.count, 0) + real_double_click(map, 5, 25) + tryCompare(mouseUpper, "lastAccepted", true) + compare(mouseUpper.lastButton, Qt.LeftButton) + compare(mouseUpper.lastModifiers, Qt.NoModifier) + compare(mouseUpper.lastWasHeld, false) + compare(mouseUpper.lastX, 5) + compare(mouseUpper.lastY, 5) // remember 20 offset of the mouse area + + compare(mouseUpperDoubleClickedSpy.count, 1) + compare(mouseLowerDoubleClickedSpy.count, 0) + compare(mouseOverlapperDoubleClickedSpy.count, 0) + real_double_click(map, 5, 25) + tryCompare(mouseUpperDoubleClickedSpy, "count", 2) + compare(mouseLowerDoubleClickedSpy.count, 0) + compare(mouseOverlapperDoubleClickedSpy.count, 0) + real_double_click(map, 5, 55) + tryCompare(mouseUpperDoubleClickedSpy, "count", 2) + compare(mouseLowerDoubleClickedSpy.count, 1) + compare(mouseOverlapperDoubleClickedSpy.count, 0) + real_double_click(map, 5, 55) + tryCompare(mouseUpperDoubleClickedSpy, "count", 2) + compare(mouseLowerDoubleClickedSpy.count, 2) + compare(mouseOverlapperDoubleClickedSpy.count, 0) + // declaration order counts on overlap case; overlapping area declared later will get the events + real_double_click(map, 55, 25) + tryCompare(mouseUpperDoubleClickedSpy, "count", 2) + compare(mouseLowerDoubleClickedSpy.count, 2) + compare(mouseOverlapperDoubleClickedSpy.count, 1) + compare(mouseOverlapperPressedSpy.count, 2) + compare(mouseOverlapperReleasedSpy.count, 2) + real_double_click(map, 55, 75) + tryCompare(mouseUpperDoubleClickedSpy, "count", 2) + compare(mouseLowerDoubleClickedSpy.count, 2) + compare(mouseOverlapperDoubleClickedSpy.count, 2) + compare(mouseOverlapperPressedSpy.count, 4) + compare(mouseOverlapperReleasedSpy.count, 4) + // disable overlapping area and check event is delivered to the ones beneath + mouseOverlapper.enabled = false + real_double_click(map, 55, 25) + tryCompare(mouseUpperDoubleClickedSpy, "count", 3) + compare(mouseLowerDoubleClickedSpy.count, 2) + compare(mouseOverlapperDoubleClickedSpy.count, 2) + real_double_click(map, 55, 75) + tryCompare(mouseUpperDoubleClickedSpy, "count", 3) + compare(mouseLowerDoubleClickedSpy.count, 3) + compare(mouseOverlapperDoubleClickedSpy.count, 2) + mouseOverlapper.enabled = true + real_double_click(map, 55, 25) + tryCompare(mouseUpperDoubleClickedSpy, "count", 3) + compare(mouseLowerDoubleClickedSpy.count, 3) + compare(mouseOverlapperDoubleClickedSpy.count, 3) + real_double_click(map, 55, 75) + tryCompare(mouseUpperDoubleClickedSpy, "count", 3) + compare(mouseLowerDoubleClickedSpy.count, 3) + compare(mouseOverlapperDoubleClickedSpy.count, 4) + } + + function test_zzz_basic_press_and_hold() { // _zzz_ to ensure execution last (takes time) + clear_data(); + wait(1000); + real_press_and_hold(map, 5, 5) + compare(mouseUpperPressAndHoldSpy.count, 0) + compare(mouseLowerPressAndHoldSpy.count, 0) + compare(mouseOverlapperPressAndHoldSpy.count, 0) + + mousePress(map,5,25) + wait(1000) // threshold is 800 ms + compare(mouseUpperPressAndHoldSpy.count, 1) + compare(mouseLowerPressAndHoldSpy.count, 0) + compare(mouseOverlapperPressAndHoldSpy.count, 0) + compare(mouseUpper.lastAccepted, true) + compare(mouseUpper.lastButton, Qt.LeftButton) + compare(mouseUpper.lastModifiers, Qt.NoModifier) + compare(mouseUpper.lastWasHeld, true) // notable part + compare(mouseUpper.lastX, 5) + compare(mouseUpper.lastY, 5) // remember 20 offset of the mouse area + mouseRelease(map,5,25) + real_press_and_hold(map, 5, 55) + tryCompare(mouseUpperPressAndHoldSpy, "count", 1) + compare(mouseLowerPressAndHoldSpy.count, 1) + compare(mouseOverlapperPressAndHoldSpy.count, 0) + real_press_and_hold(map, 55, 75) + tryCompare(mouseUpperPressAndHoldSpy, "count", 1) + compare(mouseLowerPressAndHoldSpy.count, 1) + compare(mouseOverlapperPressAndHoldSpy.count, 1) + compare(mouseOverlapper.lastAccepted, true) + compare(mouseOverlapper.lastButton, Qt.LeftButton) + compare(mouseOverlapper.lastModifiers, Qt.NoModifier) + compare(mouseOverlapper.lastWasHeld, true) + compare(mouseOverlapper.lastX, 5) + compare(mouseOverlapper.lastY, 75) + // make sure that the wasHeld is cleared + mouseClick(map, 55, 75) + tryCompare(mouseOverlapper, "lastAccepted", true) + compare(mouseOverlapper.lastButton, Qt.LeftButton) + compare(mouseOverlapper.lastModifiers, Qt.NoModifier) + compare(mouseOverlapper.lastWasHeld, false) + compare(mouseOverlapper.lastX, 5) + compare(mouseOverlapper.lastY, 75) + real_press_and_hold(map, 55, 25) + tryCompare(mouseUpperPressAndHoldSpy, "count", 1) + compare(mouseLowerPressAndHoldSpy.count, 1) + compare(mouseOverlapperPressAndHoldSpy.count, 2) + } + } +} diff --git a/tests/auto/declarative_ui/tst_map_pinch.qml.QTBUG-47970 b/tests/auto/declarative_ui/tst_map_pinch.qml.QTBUG-47970 new file mode 100644 index 0000000..f80e44a --- /dev/null +++ b/tests/auto/declarative_ui/tst_map_pinch.qml.QTBUG-47970 @@ -0,0 +1,576 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtTest 1.0 +import QtLocation 5.5 +import QtPositioning 5.5 +import QtLocation.Test 5.5 + +Item { + // General-purpose elements for the test: + id: page + width: 100 + height: 100 + Plugin { id: testPlugin; name: "qmlgeo.test.plugin"; allowExperimental: true } + + property variant coordinate: QtPositioning.coordinate(10, 11) + + // From QtLocationTest plugin + PinchGenerator { + id: pinchGenerator + anchors.fill: parent + target: page + enabled: false + } + + MouseArea { + id: mouseAreaBottom + anchors.fill: parent + visible: false + } + + Map { + id: map + plugin: testPlugin + center: coordinate; + zoomLevel: 9; + anchors.fill: page + x:0; y:0 + property variant lastPinchEvent: null + property point startPinchPoint1: Qt.point(0,0) + property point startPinchPoint2: Qt.point(0,0) + property point endPinchPoint1: Qt.point(0,0) + property point endPinchPoint2: Qt.point(0,0) + property bool rejectPinch: false + gesture.onPinchStarted: { + map.lastPinchEvent = pinch; + map.startPinchPoint1= pinch.point1; + map.startPinchPoint2= pinch.point2; + if (rejectPinch) + pinch.accepted = false; + } + gesture.onPinchUpdated: map.lastPinchEvent = pinch; + + gesture.onPinchFinished: { + map.lastPinchEvent = pinch; + map.endPinchPoint1 = pinch.point1; + map.endPinchPoint2 = pinch.point2; + } + MouseArea { + id: mouseAreaTop + anchors.fill: parent + visible: false + } + } + + SignalSpy {id: centerSpy; target: map; signalName: 'centerChanged'} + SignalSpy {id: pinchStartedSpy; target: map.gesture; signalName: 'pinchStarted'} + SignalSpy {id: pinchUpdatedSpy; target: map.gesture; signalName: 'pinchUpdated'} + SignalSpy {id: pinchFinishedSpy; target: map.gesture; signalName: 'pinchFinished'} + SignalSpy {id: pinchMaximumZoomLevelChangeSpy; target: map.gesture; signalName: 'maximumZoomLevelChangeChanged'} + SignalSpy {id: gestureEnabledSpy; target: map.gesture; signalName: 'enabledChanged'} + SignalSpy {id: pinchActiveSpy; target: map.gesture; signalName: 'pinchActiveChanged'} + SignalSpy {id: pinchActiveGesturesSpy; target: map.gesture; signalName: 'activeGesturesChanged'} + SignalSpy {id: mapZoomLevelSpy; target: map; signalName: 'zoomLevelChanged'} + SignalSpy {id: mouseAreaTopSpy; target: mouseAreaTop; signalName: 'onPressed'} + SignalSpy {id: mouseAreaBottomSpy; target: mouseAreaBottom; signalName: 'onPressed'} + + TestCase { + when: windowShown + name: "MapPinch" + + function init() + { + map.gesture.activeGestures = MapGestureArea.ZoomGesture + map.gesture.enabled = true + map.rejectPinch = false + map.center = coordinate + map.minimumZoomLevel = 0 + map.maximumZoomLevel = 20 + mouseRelease(mouseAreaTop,0,0) //Fixme: mouse area state gets broken across the tests + mouseAreaBottom.visible = false + mouseAreaTop.visible = false + pinchGenerator.clear() + centerSpy.clear() + pinchStartedSpy.clear() + pinchUpdatedSpy.clear() + pinchFinishedSpy.clear() + pinchMaximumZoomLevelChangeSpy.clear() + gestureEnabledSpy.clear() + pinchActiveSpy.clear() + pinchActiveGesturesSpy.clear() + mapZoomLevelSpy.clear() + mouseAreaTopSpy.clear() + mouseAreaBottomSpy.clear() + } + + //see QDeclarativeGeoMapGestureArea::updatePinch() + function calculateZoom(startPinchPoint1,startPinchPoint2,endPinchPoint1,endPinchPoint2, + width,height, maximumZoomLevelChange, startZoomLevel) + { + var startDistance = Math.sqrt(Math.pow(startPinchPoint2.x - startPinchPoint1.x,2) + + + Math.pow(startPinchPoint2.y - startPinchPoint1.y,2)) + var endDistance = Math.sqrt(Math.pow(endPinchPoint2.x - endPinchPoint1.x,2) + + + Math.pow(endPinchPoint2.y - endPinchPoint1.y,2)) + return 2 * (endDistance - startDistance) * maximumZoomLevelChange / + (width + height) + startZoomLevel; + } + + function initTestCase() + { + //test default properties + compare(map.gesture.enabled, true) + map.gesture.enabled = false + compare(gestureEnabledSpy.count, 1) + compare(map.gesture.enabled, false) + map.gesture.enabled = false + compare(gestureEnabledSpy.count, 1) + compare(map.gesture.enabled, false) + map.gesture.enabled = true + compare(gestureEnabledSpy.count, 2) + compare(map.gesture.enabled, true) + compare(map.gesture.isPinchActive, false) + verify(map.gesture.activeGestures & MapGestureArea.ZoomGesture) + map.gesture.activeGestures = MapGestureArea.NoGesture + compare(map.gesture.activeGestures, MapGestureArea.NoGesture) + compare(pinchActiveGesturesSpy.count, 1) + map.gesture.activeGestures = MapGestureArea.NoGesture + compare(map.gesture.activeGestures, MapGestureArea.NoGesture) + compare(pinchActiveGesturesSpy.count, 1) + map.gesture.activeGestures = MapGestureArea.ZoomGesture | MapGestureArea.PanGesture + compare(map.gesture.activeGestures, MapGestureArea.ZoomGesture | MapGestureArea.PanGesture) + compare(pinchActiveGesturesSpy.count, 2) + map.gesture.activeGestures = MapGestureArea.PanGesture + compare(map.gesture.activeGestures, MapGestureArea.PanGesture) + compare(pinchActiveGesturesSpy.count, 3) + map.gesture.activeGestures = MapGestureArea.ZoomGesture + compare(map.gesture.activeGestures, MapGestureArea.ZoomGesture) + compare(pinchActiveGesturesSpy.count, 4) + compare(map.gesture.maximumZoomLevelChange, 4) + map.gesture.maximumZoomLevelChange = 8 + compare(pinchMaximumZoomLevelChangeSpy.count, 1) + compare (map.gesture.maximumZoomLevelChange, 8) + map.gesture.maximumZoomLevelChange = 8 + compare(pinchMaximumZoomLevelChangeSpy.count, 1) + compare (map.gesture.maximumZoomLevelChange, 8) + map.gesture.maximumZoomLevelChange = 11 // too big + map.gesture.maximumZoomLevelChange = 0.01 // too small + map.gesture.maximumZoomLevelChange = -1 // too small + compare(pinchMaximumZoomLevelChangeSpy.count, 1) + compare (map.gesture.maximumZoomLevelChange, 8) + map.gesture.maximumZoomLevelChange = 2 + compare(pinchMaximumZoomLevelChangeSpy.count, 2) + compare (map.gesture.maximumZoomLevelChange, 2) + } + + + function zoom_in() + { + var startZoomLevel = 9 + map.zoomLevel = startZoomLevel + mapZoomLevelSpy.clear() + map.gesture.maximumZoomLevelChange = 2 + + compare(map.gesture.isPinchActive, false) + pinchGenerator.pinch( + Qt.point(0,50), // point1From + Qt.point(50,50), // point1To + Qt.point(100,50), // point2From + Qt.point(50,50), // point2To + 40, // interval between touch events (swipe1), default 20ms + 40, // interval between touch events (swipe2), default 20ms + 10, // number of touchevents in point1from -> point1to, default 10 + 10); // number of touchevents in point2from -> point2to, default 10 + tryCompare(pinchStartedSpy, "count", 1); + // check the pinch event data for pinchStarted + compare(map.lastPinchEvent.center.x, 50) + compare(map.lastPinchEvent.center.y, 50) + compare(map.lastPinchEvent.angle, 0) + verify((map.lastPinchEvent.point1.x > pinchGenerator.startDragDistance()) + && (map.lastPinchEvent.point1.x < 25)) + compare(map.lastPinchEvent.point1.y, 50) + verify((map.lastPinchEvent.point2.x > 75) + && (map.lastPinchEvent.point2.x < 100 - pinchGenerator.startDragDistance())) + compare(map.lastPinchEvent.point2.y, 50) + compare(map.lastPinchEvent.accepted, true) + compare(map.lastPinchEvent.pointCount, 2) + tryCompare(pinchActiveSpy, "count", 2) // check that pinch is active + compare(map.gesture.isPinchActive, true) + wait(200) // five points, each 40ms + // check the pinch event data for pinchUpdated + compare(map.lastPinchEvent.center.x, 50) + compare(map.lastPinchEvent.center.y, 50) + compare(map.lastPinchEvent.angle, 0) + verify((map.lastPinchEvent.point1.x) > 25 && (map.lastPinchEvent.point1.x <= 50)) + compare(map.lastPinchEvent.point1.y, 50) + verify((map.lastPinchEvent.point2.x) >= 50 && (map.lastPinchEvent.point2.x < 85)) + compare(map.lastPinchEvent.point2.y, 50) + compare(map.lastPinchEvent.accepted, true) + compare(map.lastPinchEvent.pointCount, 2) + tryCompare(pinchFinishedSpy, "count", 1); + compare(map.gesture.isPinchActive, false) + // check the pinch event data for pinchFinished + compare(map.lastPinchEvent.center.x, 50) + compare(map.lastPinchEvent.center.y, 50) + compare(map.lastPinchEvent.angle, 0) + verify((map.lastPinchEvent.point1.x) > 35 && (map.lastPinchEvent.point1.x <= 50)) + compare(map.lastPinchEvent.point1.y, 50) + verify((map.lastPinchEvent.point2.x) >= 50 && (map.lastPinchEvent.point2.x < 65)) + compare(map.lastPinchEvent.point2.y, 50) + compare(map.lastPinchEvent.accepted, true) + compare(map.lastPinchEvent.pointCount, 0) + + verify(pinchUpdatedSpy.count >= 5); // verify 'sane' number of updates received + compare(pinchActiveSpy.count,3) + compare(map.gesture.isPinchActive, false) + compare(mapZoomLevelSpy.count, pinchUpdatedSpy.count) + var endZoomLevel = calculateZoom( map.startPinchPoint1, map.startPinchPoint2, + map.endPinchPoint1, map.endPinchPoint2, + map.width,map.height, + map.gesture.maximumZoomLevelChange,startZoomLevel) + compare(map.zoomLevel, endZoomLevel) + } + + function test_zoom_in() + { + zoom_in() + } + + function test_zoom_in_with_top_filtering() + { + mouseAreaTop.visible = true + zoom_in() + tryCompare(mouseAreaTopSpy, "count", 1) + } + + function test_zoom_in_with_below_filtering() + { + mouseAreaBottom.visible=true + zoom_in() + tryCompare(mouseAreaBottomSpy, "count",0) + } + + function zoom_out() + { + var startZoomLevel = 7.8 + map.zoomLevel = startZoomLevel + map.gesture.maximumZoomLevelChange = 2 + compare (map.gesture.maximumZoomLevelChange, 2) + mapZoomLevelSpy.clear() + pinchGenerator.pinch(Qt.point(45,50), Qt.point(0,50), + Qt.point(55,50), Qt.point(100,50), + 40, 40, 10, 10); + tryCompare(pinchStartedSpy, "count", 1); + tryCompare(pinchFinishedSpy, "count", 1); + compare(map.gesture.isPinchActive, false) + verify(pinchUpdatedSpy.count >= 5); // verify 'sane' number of updates received + compare(mapZoomLevelSpy.count, pinchUpdatedSpy.count) + var endZoomLevel = calculateZoom( map.startPinchPoint1, map.startPinchPoint2, + map.endPinchPoint1, map.endPinchPoint2, + map.width,map.height, + map.gesture.maximumZoomLevelChange,startZoomLevel) + + compare(map.zoomLevel, endZoomLevel) + } + + function test_zoom_out() + { + zoom_out() + } + + function test_zoom_out_with_top_filtering() + { + mouseAreaTop.visible=true + zoom_out() + tryCompare(mouseAreaTopSpy, "count", 1) + } + + function test_zoom_out_with_below_filtering() + { + mouseAreaBottom.visible=true + zoom_out() + tryCompare(mouseAreaBottomSpy, "count",0) + } + + function test_zoom_in_and_back_out() + { + // direction change during same pinch + var startZoomLevel = 7.8 + map.gesture.maximumZoomLevelChange = 2 + map.zoomLevel = startZoomLevel + pinchGenerator.pinch(Qt.point(0,50), Qt.point(100,50), + Qt.point(100,50),Qt.point(0,50), + 40, 40, 10, 10); + tryCompare(pinchStartedSpy, "count", 1); + tryCompare(pinchFinishedSpy, "count", 1); + verify(pinchUpdatedSpy.count >= 5); // verify 'sane' number of updates received + var endZoomLevel = calculateZoom( map.startPinchPoint1, map.startPinchPoint2, + map.endPinchPoint1, map.endPinchPoint2, + map.width,map.height, + map.gesture.maximumZoomLevelChange,startZoomLevel) + compare(map.zoomLevel, endZoomLevel) // should remain the same + } + + function test_zoom_in_with_different_change_level() + { + var startZoomLevel = 8 + map.zoomLevel = startZoomLevel + map.gesture.maximumZoomLevelChange = 4 + compare (map.gesture.maximumZoomLevelChange, 4) + pinchGenerator.pinch(Qt.point(0,50),Qt.point(50,50), + Qt.point(100,50),Qt.point(50,50), + 40, 40, 10, 10); + tryCompare(pinchFinishedSpy, "count", 1); + var endZoomLevel = calculateZoom( map.startPinchPoint1, map.startPinchPoint2, + map.endPinchPoint1, map.endPinchPoint2, + map.width,map.height, + map.gesture.maximumZoomLevelChange,startZoomLevel) + compare(map.zoomLevel, endZoomLevel) + } + + function test_zoom_out_with_different_change_level() + { + var startZoomLevel = 8 + map.gesture.maximumZoomLevelChange = 1 + map.zoomLevel = startZoomLevel + compare (map.gesture.maximumZoomLevelChange, 1) + pinchGenerator.pinch(Qt.point(50,50), Qt.point(0,50), + Qt.point(50,50), Qt.point(100,50), + 40, 40, 10, 10); + tryCompare(pinchFinishedSpy, "count", 1); + var endZoomLevel = calculateZoom( map.startPinchPoint1, map.startPinchPoint2, + map.endPinchPoint1, map.endPinchPoint2, + map.width,map.height, + map.gesture.maximumZoomLevelChange,startZoomLevel) + compare(map.zoomLevel, endZoomLevel) + } + + function test_zoom_in_below_minimum_zoom_level() + { + map.zoomLevel = 8 + map.gesture.maximumZoomLevelChange = 4 + map.minimumZoomLevel = 7 + pinchGenerator.pinch(Qt.point(0,50),Qt.point(50,50),Qt.point(100,50),Qt.point(50,50)); + wait(250); + tryCompare(pinchFinishedSpy, "count", 1); + compare(map.zoomLevel, 7) + } + + function test_zoom_out_above_maximum_zoom_level() + { + map.gesture.maximumZoomLevelChange = 4 + map.maximumZoomLevel = 8 + pinchGenerator.pinch(Qt.point(50,50), Qt.point(0,50),Qt.point(50,50), Qt.point(100,50)); + tryCompare(pinchFinishedSpy, "count", 1); + compare(map.zoomLevel, 8) + } + + function test_pinch_when_max_and_min_are_same() + { + map.maximumZoomLevel = 8 + map.minimumZoomLevel = 8 + compare(map.maximumZoomLevel, 8) + compare(map.minimumZoomLevel, 8) + pinchGenerator.pinch(Qt.point(0,50),Qt.point(50,50),Qt.point(100,50),Qt.point(50,50)); + tryCompare(pinchFinishedSpy, "count", 1); + compare(map.zoomLevel, 8) + map.minimumZoomLevel = 1 + map.maximumZoomLevel = 20 + } + + function test_pinch_when_max_min_is_not_where_map_zoomLevel_currently_is() + { + map.gesture.maximumZoomLevelChange = 4 + map.minimumZoomLevel = 4 + map.maximumZoomLevel = 6 + // first when above the zoom range + map.zoomLevel = 5 + pinchGenerator.pinch(Qt.point(50,50),Qt.point(0,50),Qt.point(50,50),Qt.point(100,50)); // zoom out + tryCompare(pinchFinishedSpy, "count", 1); + compare(map.zoomLevel, 6) + map.zoomLevel = 5 + pinchGenerator.pinch(Qt.point(0,50),Qt.point(50,50),Qt.point(100,50),Qt.point(50,50)); // zoom in + tryCompare(pinchFinishedSpy, "count", 2); + compare(map.zoomLevel, 4) + pinchGenerator.pinch(Qt.point(0,50),Qt.point(50,50),Qt.point(100,50),Qt.point(50,50)); // zoom in + tryCompare(pinchFinishedSpy, "count", 3); + compare(map.zoomLevel, 4) + map.minimumZoomLevel = 1 + map.maximumZoomLevel = 20 + } + + function test_pinch_while_pinch_area_is_disabled() + { + map.zoomLevel = 7.5 + map.gesture.enabled = false + map.gesture.maximumZoomLevelChange = 2 + pinchGenerator.pinch(Qt.point(50,50), Qt.point(0,50), + Qt.point(50,50), Qt.point(100,50), + 40, 40, 10, 10); + wait(200); + compare(pinchActiveSpy.count, 0) + compare(map.gesture.isPinchActive, false) + compare(pinchStartedSpy.count, 0) + compare(pinchUpdatedSpy.count, 0); + compare(pinchFinishedSpy.count, 0); + compare(map.zoomLevel, 7.5) + pinchGenerator.stop() + } + + function test_pinch_disabling_during_pinching() + { + var startZoomLevel = 7.5 + map.zoomLevel = startZoomLevel + pinchGenerator.pinch(Qt.point(50,50), Qt.point(0,50), + Qt.point(50,50), Qt.point(100,50), + 40, 40, 10, 10); + tryCompare(pinchStartedSpy, "count", 1); + // check that pinch is active. then disable the pinch. pinch area should still process + // as long as it is active + compare(pinchActiveSpy.count,2) + compare(map.gesture.isPinchActive, true) + map.gesture.enabled = false + tryCompare(pinchFinishedSpy, "count", 1) + var pinchupdates = pinchUpdatedSpy.count + verify(pinchupdates > 0) + compare(pinchActiveSpy.count,3) + compare(map.gesture.isPinchActive, false) + var endZoomLevel = calculateZoom( map.startPinchPoint1, map.startPinchPoint2, + map.endPinchPoint1, map.endPinchPoint2, + map.width,map.height, + map.gesture.maximumZoomLevelChange,startZoomLevel) + compare(map.zoomLevel, endZoomLevel) + pinchGenerator.pinch(Qt.point(50,50), Qt.point(0,50), + Qt.point(50,50), Qt.point(100,50), + 40, 40, 10, 10); + compare(map.zoomLevel, endZoomLevel) + } + + function test_check_no_active_gestures() + { + map.zoomLevel = 8.5 + map.gesture.activeGestures = MapGestureArea.NoGesture + + pinchGenerator.pinch(Qt.point(50,50), Qt.point(0,50), + Qt.point(50,50), Qt.point(100,50), + 40, 40, 10, 10); + tryCompare(pinchStartedSpy, "count", 0); + wait(300); + compare(pinchUpdatedSpy.count, 0); + compare(pinchStartedSpy.count, 0); + compare(map.zoomLevel, 8.5) + pinchGenerator.stop() + } + + function test_changing_zoom_level_during_active_pinch_zoom() + { + var startZoomLevel = 8.5 + map.zoomLevel = startZoomLevel + map.gesture.maximumZoomLevelChange = 2 + pinchGenerator.pinch(Qt.point(50,50), Qt.point(0,50), + Qt.point(50,50), Qt.point(100,50), + 40, 40, 10, 10); + tryCompare(pinchStartedSpy, "count", 1); + tryCompare(pinchActiveSpy, "count", 2) + compare(map.gesture.isPinchActive, true) + map.zoomLevel = 3 // will get overridden by pinch + tryCompare(pinchFinishedSpy, "count", 1); + verify(pinchUpdatedSpy.count >= 5); // verify 'sane' number of updates received + var endZoomLevel = calculateZoom( map.startPinchPoint1, map.startPinchPoint2, + map.endPinchPoint1, map.endPinchPoint2, + map.width,map.height, + map.gesture.maximumZoomLevelChange,startZoomLevel) + compare(map.zoomLevel, endZoomLevel) + } + + function test_zoom_below_and_above_plugin_support() + { + map.gesture.maximumZoomLevelChange = 4 + map.zoomLevel = map.minimumZoomLevel + 0.5 + pinchGenerator.pinch(Qt.point(0,50),Qt.point(50,50), + Qt.point(100,50),Qt.point(50,50), + 40, 40, 10, 10); + tryCompare(pinchFinishedSpy, "count", 1); + compare(map.zoomLevel, map.minimumZoomLevel) + map.zoomLevel = map.maximumZoomLevel - 0.5 + pinchGenerator.pinch(Qt.point(50,50), Qt.point(0,50),Qt.point(50,50), Qt.point(100,50)); + tryCompare(pinchFinishedSpy, "count", 2); + compare(map.zoomLevel, map.maximumZoomLevel) + } + + function test_check_pinch_accepted() + { + map.zoomLevel = 10 + map.rejectPinch = true + pinchGenerator.pinch(Qt.point(0,50),Qt.point(50,50), + Qt.point(100,50),Qt.point(50,50), + 40, 40, 10, 10); + wait(300) + compare(pinchUpdatedSpy.count, 0) + compare(pinchFinishedSpy.count, 0) + compare(map.gesture.isPinchActive, false) + compare(map.zoomLevel, 10) + var startZoomLevel = 10 + map.rejectPinch = false + wait(500) + pinchGenerator.pinch(Qt.point(0,50),Qt.point(50,50),Qt.point(100,50),Qt.point(50,50),40, 40, 10, 10); + tryCompare(pinchFinishedSpy, "count", 1) + var endZoomLevel = calculateZoom( map.startPinchPoint1, map.startPinchPoint2, + map.endPinchPoint1, map.endPinchPoint2, + map.width,map.height, + map.gesture.maximumZoomLevelChange,startZoomLevel) + compare(map.zoomLevel, endZoomLevel) + compare(map.lastPinchEvent.accepted, true) + } + + function test_moving_center() + { + pinchGenerator.pinch(Qt.point(0, 50), Qt.point(50,100), Qt.point(50,0), Qt.point(100, 50)) + tryCompare(pinchStartedSpy, "count", 1) + compare(map.lastPinchEvent.center.x, (map.lastPinchEvent.point1.x + map.lastPinchEvent.point2.x) /2) + compare(map.lastPinchEvent.center.x, (map.lastPinchEvent.point1.y + map.lastPinchEvent.point2.y) /2) + tryCompare(pinchFinishedSpy, "count", 1) + compare(map.lastPinchEvent.center.x, (map.lastPinchEvent.point1.x + map.lastPinchEvent.point2.x) /2) + compare(map.lastPinchEvent.center.x, (map.lastPinchEvent.point1.y + map.lastPinchEvent.point2.y) /2) + // sanity check that we are not comparing wrong (points) with wrong (center) and calling it a success + verify((map.lastPinchEvent.center.x > 50) && (map.lastPinchEvent.center.x < 100)) + verify((map.lastPinchEvent.center.y > 50) && (map.lastPinchEvent.center.y < 100)) + } + + function test_angle_between_points() + { + // todo calculate the angle from points for comparison + pinchGenerator.pinch(Qt.point(0,0), Qt.point(0,100), Qt.point(100,100), Qt.point(100,0)) + tryCompare(pinchStartedSpy, "count", 1) + verify(map.lastPinchEvent.angle >= -45 && map.lastPinchEvent.angle < -20) + tryCompare(pinchFinishedSpy, "count", 1) + verify(map.lastPinchEvent.angle >= 20 && map.lastPinchEvent.angle <= 45) + } + } +} diff --git a/tests/auto/doublevectors/doublevectors.pro b/tests/auto/doublevectors/doublevectors.pro new file mode 100644 index 0000000..841a19e --- /dev/null +++ b/tests/auto/doublevectors/doublevectors.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_doublevectors + +SOURCES += tst_doublevectors.cpp + +QT += positioning-private testlib diff --git a/tests/auto/doublevectors/tst_doublevectors.cpp b/tests/auto/doublevectors/tst_doublevectors.cpp new file mode 100644 index 0000000..ae1b2ba --- /dev/null +++ b/tests/auto/doublevectors/tst_doublevectors.cpp @@ -0,0 +1,293 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include + +QT_USE_NAMESPACE + +class tst_doubleVectors : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + // 2D + void constructor2dTest(); + void basicFunctions2dTest(); + void unaryOperator2dTest(); + void binaryOperator2dTest(); + + // 3D + void constructor3dTest(); + void basicFunctions3dTest(); + void unaryOperator3dTest(); + void binaryOperator3dTest(); +}; + +// DoubleVector2D + +void tst_doubleVectors::constructor2dTest() +{ + // empty constructor, since it sets to 0, we should check, in case people rely on it + QDoubleVector2D v1; + QCOMPARE(v1.x(), 0.0); + QCOMPARE(v1.y(), 0.0); + QCOMPARE(v1.isNull(), true); + v1 = QDoubleVector2D(1.1, -2.5); // assignment and constructor + QCOMPARE(v1.x(), 1.1); + QCOMPARE(v1.y(), -2.5); + QDoubleVector2D v2(v1); // copy constructor + QCOMPARE(v2.x(), 1.1); + QCOMPARE(v2.y(), -2.5); + const QDoubleVector3D v3d(2.2, 3.3, 4.4); + QDoubleVector2D v3(v3d); // constructor from 3d vector, just copies x and y + QCOMPARE(v3.x(), 2.2); + QCOMPARE(v3.y(), 3.3); + QCOMPARE(v3.isNull(), false); +} + +void tst_doubleVectors::basicFunctions2dTest() +{ + QDoubleVector2D v1; + v1.setX(3.0); + v1.setY(4.0); + QCOMPARE(v1.x(), 3.0); + QCOMPARE(v1.y(), 4.0); + QCOMPARE(v1.length(), 5.0); + QDoubleVector2D v2 = v1.normalized(); + QCOMPARE(v1.lengthSquared(), 25.0); + v1.normalize(); + QCOMPARE(v1.x(), 3.0/5.0); + QCOMPARE(v1.y(), 4.0/5.0); + QCOMPARE(v2.x(), 3.0/5.0); + QCOMPARE(v2.y(), 4.0/5.0); + + QDoubleVector3D v3d = v1.toVector3D(); + QCOMPARE(v3d.x(), 3.0/5.0); + QCOMPARE(v3d.y(), 4.0/5.0); + QCOMPARE(v3d.z(), 0.0); +} + +void tst_doubleVectors::unaryOperator2dTest() +{ + QDoubleVector2D v1(1.1, 2.2); + QDoubleVector2D v2 = -v1; + QCOMPARE(v2.x(), -1.1); + QCOMPARE(v2.y(), -2.2); + + v1 *= 2.0; + QCOMPARE(v1.x(), 2.2); + QCOMPARE(v1.y(), 4.4); + + v2 /= 2.0; + QCOMPARE(v2.x(), -0.55); + QCOMPARE(v2.y(), -1.1); + + v1 += v2; + QCOMPARE(v1.x(), 1.65); + QCOMPARE(v1.y(), 3.3); + + v1 -= v2; + QCOMPARE(v1.x(), 2.2); + QCOMPARE(v1.y(), 4.4); + + v1 *= v2; + QCOMPARE(v1.x(), -1.21); + QCOMPARE(v1.y(), -4.84); +} + +void tst_doubleVectors::binaryOperator2dTest() +{ + QDoubleVector2D v1(1.1, 2.2); + QDoubleVector2D v2(3.4, 4.4); + QDoubleVector2D v3 = v1 + v2; + QCOMPARE(v3.x(), 4.5); + QCOMPARE(v3.y(), 6.6); + + QDoubleVector2D v4 = v1 - v2; + QCOMPARE(v4.x(), -2.3); + QCOMPARE(v4.y(), -2.2); + + QDoubleVector2D v5 = v2 * 2; + QCOMPARE(v5.x(), 6.8); + QCOMPARE(v5.y(), 8.8); + + QDoubleVector2D v6 = 2 * v2; + QCOMPARE(v6.x(), 6.8); + QCOMPARE(v6.y(), 8.8); + + QDoubleVector2D v7 = v2 / 2; + QCOMPARE(v7.x(), 1.7); + QCOMPARE(v7.y(), 2.2); + + double d = QDoubleVector2D::dotProduct(v1, v2); + QCOMPARE(d, 13.42); + + QCOMPARE(v5 == v6, true); + QCOMPARE(v5 != v6, false); + QCOMPARE(v6 == v7, false); + QCOMPARE(v6 != v7, true); +} + + + +// DoubleVector3D + + +void tst_doubleVectors::constructor3dTest() +{ + // empty constructor, since it sets to 0, we should check, in case people rely on it + QDoubleVector3D v1; + QCOMPARE(v1.x(), 0.0); + QCOMPARE(v1.y(), 0.0); + QCOMPARE(v1.z(), 0.0); + QCOMPARE(v1.isNull(), true); + v1 = QDoubleVector3D(1.1, -2.5, 3.2); // assignment and constructor + QCOMPARE(v1.x(), 1.1); + QCOMPARE(v1.y(), -2.5); + QCOMPARE(v1.z(), 3.2); + QDoubleVector3D v2(v1); // copy constructor + QCOMPARE(v2.x(), 1.1); + QCOMPARE(v2.y(), -2.5); + QCOMPARE(v2.z(), 3.2); + const QDoubleVector2D v2d(2.2, 3.3); + QDoubleVector3D v3(v2d); // constructor from 3d vector, just copies x and y + QCOMPARE(v3.x(), 2.2); + QCOMPARE(v3.y(), 3.3); + QCOMPARE(v3.z(), 0.0); + QCOMPARE(v3.isNull(), false); + const QDoubleVector2D v2d2(2.2, 3.3); + QDoubleVector3D v4(v2d2, -13.6); // constructor from 2d vector + QCOMPARE(v4.x(), 2.2); + QCOMPARE(v4.y(), 3.3); + QCOMPARE(v4.z(), -13.6); +} + +void tst_doubleVectors::basicFunctions3dTest() +{ + QDoubleVector3D v1; + v1.setX(2.0); + v1.setY(3.0); + v1.setZ(6.0); + QCOMPARE(v1.x(), 2.0); + QCOMPARE(v1.y(), 3.0); + QCOMPARE(v1.z(), 6.0); + QCOMPARE(v1.length(), 7.0); + QDoubleVector3D v2 = v1.normalized(); + QCOMPARE(v1.lengthSquared(), 49.0); + v1.normalize(); + QCOMPARE(v1.x(), 2.0/7.0); + QCOMPARE(v1.y(), 3.0/7.0); + QCOMPARE(v1.z(), 6.0/7.0); + QCOMPARE(v2.x(), 2.0/7.0); + QCOMPARE(v2.y(), 3.0/7.0); + QCOMPARE(v2.z(), 6.0/7.0); + + QDoubleVector2D v2d = v1.toVector2D(); + QCOMPARE(v2d.x(), 2.0/7.0); + QCOMPARE(v2d.y(), 3.0/7.0); +} + +void tst_doubleVectors::unaryOperator3dTest() +{ + QDoubleVector3D v1(1.1, 2.2, 3.3); + QDoubleVector3D v2 = -v1; + QCOMPARE(v2.x(), -1.1); + QCOMPARE(v2.y(), -2.2); + QCOMPARE(v2.z(), -3.3); + + v1 *= 2.0; + QCOMPARE(v1.x(), 2.2); + QCOMPARE(v1.y(), 4.4); + QCOMPARE(v1.z(), 6.6); + + v2 /= 2.0; + QCOMPARE(v2.x(), -0.55); + QCOMPARE(v2.y(), -1.1); + QCOMPARE(v2.z(), -1.65); + + v1 += v2; + QCOMPARE(v1.x(), 1.65); + QCOMPARE(v1.y(), 3.3); + QCOMPARE(v1.z(), 4.95); + + v1 -= v2; + QCOMPARE(v1.x(), 2.2); + QCOMPARE(v1.y(), 4.4); + QCOMPARE(v1.z(), 6.6); + + v1 *= v2; + QCOMPARE(v1.x(), -1.21); + QCOMPARE(v1.y(), -4.84); + QCOMPARE(v1.z(), -10.89); +} + +void tst_doubleVectors::binaryOperator3dTest() +{ + QDoubleVector3D v1(1.1, 2.2, 3.3); + QDoubleVector3D v2(3.4, 4.4, 5.5); + QDoubleVector3D v3 = v1 + v2; + QCOMPARE(v3.x(), 4.5); + QCOMPARE(v3.y(), 6.6); + QCOMPARE(v3.z(), 8.8); + + QDoubleVector3D v4 = v1 - v2; + QCOMPARE(v4.x(), -2.3); + QCOMPARE(v4.y(), -2.2); + QCOMPARE(v4.z(), -2.2); + + QDoubleVector3D v5 = v2 * 2; + QCOMPARE(v5.x(), 6.8); + QCOMPARE(v5.y(), 8.8); + QCOMPARE(v5.z(), 11.0); + + QDoubleVector3D v6 = 2 * v2; + QCOMPARE(v6.x(), 6.8); + QCOMPARE(v6.y(), 8.8); + QCOMPARE(v6.z(), 11.0); + + QDoubleVector3D v7 = v2 / 2; + QCOMPARE(v7.x(), 1.7); + QCOMPARE(v7.y(), 2.2); + QCOMPARE(v7.z(), 2.75); + + double d = QDoubleVector3D::dotProduct(v1, v2); + QCOMPARE(d, 31.57); + + QCOMPARE(v5 == v6, true); + QCOMPARE(v5 != v6, false); + QCOMPARE(v6 == v7, false); + QCOMPARE(v6 != v7, true); +} + +QTEST_APPLESS_MAIN(tst_doubleVectors) + +#include "tst_doublevectors.moc" diff --git a/tests/auto/geotestplugin/geotestplugin.json b/tests/auto/geotestplugin/geotestplugin.json new file mode 100644 index 0000000..5272171 --- /dev/null +++ b/tests/auto/geotestplugin/geotestplugin.json @@ -0,0 +1,19 @@ +{ + "Keys": ["qmlgeo.test.plugin"], + "Provider": "qmlgeo.test.plugin", + "Version": 100, + "Experimental": true, + "Features": [ + "OfflineMappingFeature", + "OfflineRoutingFeature", + "AlternativeRoutesFeature", + "ExcludeAreasRoutingFeature", + "RouteUpdatesFeature", + "OfflineGeocodingFeature", + "ReverseGeocodingFeature", + "OfflinePlacesFeature", + "SavePlaceFeature", + "SaveCategoryFeature", + "SearchSuggestionsFeature" + ] +} diff --git a/tests/auto/geotestplugin/geotestplugin.pro b/tests/auto/geotestplugin/geotestplugin.pro new file mode 100644 index 0000000..fb3f1b3 --- /dev/null +++ b/tests/auto/geotestplugin/geotestplugin.pro @@ -0,0 +1,22 @@ +TARGET = qtgeoservices_qmltestplugin +QT += location-private positioning-private testlib + +PLUGIN_TYPE = geoservices +PLUGIN_CLASS_NAME = TestGeoServicePlugin +PLUGIN_EXTENDS = - +load(qt_plugin) + +HEADERS += qgeocodingmanagerengine_test.h \ + qgeoserviceproviderplugin_test.h \ + qgeoroutingmanagerengine_test.h \ + qplacemanagerengine_test.h \ + qgeotiledmappingmanagerengine_test.h \ + qgeotiledmap_test.h \ + qgeotilefetcher_test.h + +SOURCES += qgeoserviceproviderplugin_test.cpp + +OTHER_FILES += \ + geotestplugin.json \ + place_data.json +RESOURCES += testdata.qrc diff --git a/tests/auto/geotestplugin/place_data.json b/tests/auto/geotestplugin/place_data.json new file mode 100644 index 0000000..2006281 --- /dev/null +++ b/tests/auto/geotestplugin/place_data.json @@ -0,0 +1,145 @@ +{ + "categories": [ + { + "name": "Accommodation", + "id": "4b79794f-e146-4adc-9bdf-68c06e7209fd" + }, + { + "name": "Hotel", + "id": "70ab5807-26d2-46be-a860-dc48f17133f0", + "parentId": "4b79794f-e146-4adc-9bdf-68c06e7209fd" + }, + { + "name": "Motel", + "id": "e0478f8a-fe8f-4bf9-8392-c1910e49223f", + "parentId": "4b79794f-e146-4adc-9bdf-68c06e7209fd" + }, + { + "name": "Camping", + "id": "b0434495-9429-4c9f-96e5-75f52f0b8dc8", + "parentId": "4b79794f-e146-4adc-9bdf-68c06e7209fd" + }, + { + "name": "Park", + "id": "c2e1252c-b997-44fc-8165-e53dd00f66a7" + } + ], + + "places": [ + { + "name": "Park View Hotel", + "id": "4dcc74ce-fdeb-443e-827c-367438017cf1", + "categories": [ "70ab5807-26d2-46be-a860-dc48f17133f0" ], + "location": { + "latitude": 0.1001, + "longitude": 0.1001 + }, + "recommendations": [ + "8f72057a-54b2-4e95-a7bb-97b4d2b5721e", + "dacb2181-3f67-4e6a-bd4d-635e99ad5b03" + ], + "reviews": [ + { + "title": "Park View Review 1", + "text": "Park View Review 1 Text", + "dateTime": "13:01 22-09-2004", + "language": "en", + "rating": 3.5, + "reviewId": "0001" + }, + { + "title": "Park View Review 2", + "text": "Park View Review 2 Text", + "dateTime": "04:17 14-09-2005", + "language": "en", + "rating": 1, + "reviewId": "0002" + }, + { + "title": "Park View Review 3", + "text": "Park View Review 3 Text", + "dateTime": "04:12 14-10-2005", + "language": "en", + "rating": 5, + "reviewId": "0003" + }, + { + }, + { + "title": "Park View Review 5", + "text": "Park View Review 5 Text", + "dateTime": "14:53 20-11-2005", + "language": "en", + "rating": 2.3, + "reviewId": "0005" + } + ], + "images": [ + { + "url": "http://somewhere.com/image1.png", + "imageId": "0001", + "mimeType": "image/png" + }, + { + "url": "http://somewhere.com/image2.png", + "imageId": "0002", + "mimeType": "image/png" + }, + { + "url": "http://somewhere.com/image3.png", + "imageId": "0003", + "mimeType": "image/png" + }, + { + }, + { + "url": "http://somewhere.com/image5.png", + "imageId": "0005", + "mimeType": "image/png" + } + ], + "editorials": [ + { + "title": "Editorial 1", + "text": "Editorial 1 Text", + "language": "en" + }, + { + "title": "Editorial 2", + "text": "Editorial 2 Text", + "language": "en" + }, + { + "title": "Editorial 3", + "text": "Editorial 3 Text", + "language": "en" + }, + { + }, + { + "title": "Editorial 5", + "text": "Editorial 5 Text", + "language": "en" + } + ] + }, + { + "name": "Sea View Hotel", + "id": "8f72057a-54b2-4e95-a7bb-97b4d2b5721e", + "categories": [ "70ab5807-26d2-46be-a860-dc48f17133f0" ], + "location": { + "latitude": 0.1002, + "longitude": 0.1002 + } + }, + { + "name": "Country Gardens", + "id": "dacb2181-3f67-4e6a-bd4d-635e99ad5b03", + "categories": [ "c2e1252c-b997-44fc-8165-e53dd00f66a7" ], + "location": { + "latitude": 0.1001, + "longitude": 0.1002 + } + } + ] +} diff --git a/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h b/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h new file mode 100644 index 0000000..1d9f079 --- /dev/null +++ b/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h @@ -0,0 +1,274 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODINGMANAGERENGINE_TEST_H +#define QGEOCODINGMANAGERENGINE_TEST_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +QT_USE_NAMESPACE + + +class GeocodeReplyTest :public QGeoCodeReply +{ + Q_OBJECT +public: + GeocodeReplyTest(QObject *parent = 0) : QGeoCodeReply (parent) {} + + void callAddLocation ( const QGeoLocation & location ) {addLocation(location);} + void callSetError ( Error error, const QString & errorString ) {setError(error, errorString);} + void callSetFinished ( bool finished ) {setFinished(finished);} + void callSetLimit ( int limit ) {setLimit(limit);} + void callSetOffset ( int offset ) {setOffset(offset);} + void callSetLocations ( const QList & locations ) {setLocations(locations);} + void callSetViewport ( const QGeoShape &viewport ) {setViewport(viewport);} + void abort() { + emit aborted(); + } +Q_SIGNALS: + void aborted(); +}; + +class QGeoCodingManagerEngineTest: public QGeoCodingManagerEngine + +{ +Q_OBJECT +public: + QGeoCodingManagerEngineTest(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) : + QGeoCodingManagerEngine(parameters), + validateWellKnownValues_(false), + finishRequestImmediately_(true), + supported_(true), + geocodeReply_(0), + timerId_(0), + errorCode_(QGeoCodeReply::NoError) + { + Q_UNUSED(error) + Q_UNUSED(errorString) + if (parameters.contains("supported")) + supported_ = qvariant_cast(parameters.value("supported")); + if (parameters.contains("finishRequestImmediately")) + finishRequestImmediately_ = qvariant_cast(parameters.value("finishRequestImmediately")); + if (parameters.contains("validateWellKnownValues")) + validateWellKnownValues_ = qvariant_cast(parameters.value("validateWellKnownValues")); + + setLocale(QLocale (QLocale::German, QLocale::Germany)); + } + + QGeoCodeReply* geocode(const QString &searchString, + int limit = -1, + int offset = 0, + const QGeoShape &bounds = QGeoShape()) + { + geocodeReply_ = new GeocodeReplyTest(); + connect(geocodeReply_, SIGNAL(aborted()), this, SLOT(requestAborted())); + geocodeReply_->callSetViewport(bounds); + + if (searchString.length() == 1) { + errorString_ = searchString; + errorCode_ = (QGeoCodeReply::Error)searchString.toInt(); + } else { + errorString_ = ""; + errorCode_ = QGeoCodeReply::NoError; + } + + if (errorCode_ == QGeoCodeReply::NoError) + setLocations(geocodeReply_, searchString, limit, offset); + + if (finishRequestImmediately_) { + // check if we should finish with error + if (errorCode_) { + geocodeReply_->callSetError(errorCode_, errorString_); + } else { + geocodeReply_->callSetFinished(true); + } + } else { + // we only allow serialized requests in QML - previous must have been aborted + Q_ASSERT(timerId_ == 0); + timerId_ = startTimer(200); + } + return static_cast(geocodeReply_); + } + + QGeoCodeReply* geocode(const QGeoAddress & address, const QGeoShape &bounds) + { + geocodeReply_ = new GeocodeReplyTest(); + connect(geocodeReply_, SIGNAL(aborted()), this, SLOT(requestAborted())); + geocodeReply_->callSetViewport(bounds); + + if (address.street().startsWith("error")) { + errorString_ = address.street(); + errorCode_ = (QGeoCodeReply::Error)address.county().toInt(); + } else { + errorString_ = ""; + errorCode_ = QGeoCodeReply::NoError; + } + // 1. Check if we are to validate values + if (validateWellKnownValues_) { + if (address.street() != "wellknown street") { + geocodeReply_->callSetError(QGeoCodeReply::EngineNotSetError, address.street()); + } else { + geocodeReply_->callSetError(QGeoCodeReply::NoError,address.street()); + } + } + + // 2. Set the locations into the reply + setLocations(geocodeReply_, address); + + // 3. Finish the request + if (finishRequestImmediately_) { + // check if we should finish with error + if (errorCode_) { + geocodeReply_->callSetError(errorCode_, errorString_); + } else { + geocodeReply_->callSetFinished(true); + } + } else { + // we only allow serialized requests in QML - previous must have been aborted + Q_ASSERT(timerId_ == 0); + timerId_ = startTimer(200); + } + return static_cast(geocodeReply_); + } + +public Q_SLOTS: + void requestAborted() + { + if (timerId_) { + killTimer(timerId_); + timerId_ = 0; + } + errorString_ = ""; + errorCode_ = QGeoCodeReply::NoError; + } + +public: + void setLocations(GeocodeReplyTest* reply, const QString searchString, int limit, int offset) + { + if (limit < 0) + limit = 0; + for (int i = 0; i < limit; ++i) { + QGeoLocation location; + QGeoAddress address; + address.setStreet(searchString); + address.setCounty(QString::number(offset)); + location.setAddress(address); + reply->callAddLocation(location); + } + } + + void setLocations(GeocodeReplyTest* reply, const QGeoAddress& address) + { + int count = address.county().toInt(); + + for (int i = 0; i < count; ++i) { + QGeoLocation location; + location.setAddress(address); + reply->callAddLocation(location); + } + } + + void setLocations(GeocodeReplyTest* reply, const QGeoCoordinate & coordinate) + { + for (int i = 0; i < coordinate.longitude(); ++i) { + QGeoLocation location; + location.setCoordinate(coordinate); + reply->callAddLocation(location); + } + } + + QGeoCodeReply* reverseGeocode(const QGeoCoordinate &coordinate, const QGeoShape &bounds) + { + geocodeReply_ = new GeocodeReplyTest(); + connect(geocodeReply_, SIGNAL(aborted()), this, SLOT(requestAborted())); + + setLocations(geocodeReply_, coordinate); + geocodeReply_->callSetViewport(bounds); + + if (coordinate.latitude() > 70) { + errorString_ = "error"; + errorCode_ = (QGeoCodeReply::Error) (qRound(coordinate.latitude() - 70)); + } else { + errorString_ = ""; + errorCode_ = QGeoCodeReply::NoError; + } + if (finishRequestImmediately_) { + if (errorCode_) { + geocodeReply_->callSetError(errorCode_, errorString_); + } else { + geocodeReply_->callSetError(QGeoCodeReply::NoError,coordinate.toString()); + geocodeReply_->callSetFinished(true); + } + } else { + // we only allow serialized requests in QML - previous must have been aborted or finished + Q_ASSERT(timerId_ == 0); + timerId_ = startTimer(200); + } + return static_cast(geocodeReply_); + } + +protected: + void timerEvent(QTimerEvent *event) + { + Q_UNUSED(event); + Q_ASSERT(timerId_ == event->timerId()); + Q_ASSERT(geocodeReply_); + killTimer(timerId_); + timerId_ = 0; + if (errorCode_) { + geocodeReply_->callSetError(errorCode_, errorString_); + emit error(geocodeReply_, errorCode_, errorString_); + } else { + geocodeReply_->callSetError(QGeoCodeReply::NoError, "no error"); + geocodeReply_->callSetFinished(true); + } + emit finished(geocodeReply_); + } + +private: + bool validateWellKnownValues_; + bool finishRequestImmediately_; + bool supported_; + GeocodeReplyTest* geocodeReply_; + int timerId_; + QGeoCodeReply::Error errorCode_; + QString errorString_; +}; + +#endif diff --git a/tests/auto/geotestplugin/qgeomappingmanagerengine_test.h b/tests/auto/geotestplugin/qgeomappingmanagerengine_test.h new file mode 100644 index 0000000..07d832c --- /dev/null +++ b/tests/auto/geotestplugin/qgeomappingmanagerengine_test.h @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPPINGMANAGERENGINE_TEST_H +#define QGEOMAPPINGMANAGERENGINE_TEST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qgeomaptype.h" +#include "qgeotilespec.h" +#include "qgeocameracapabilities_p.h" + +#include +#include +#include + +QT_USE_NAMESPACE + + +class TiledMapReplyTest :public QGeoTiledMapReply +{ + Q_OBJECT +public: + TiledMapReplyTest(const QGeoTileSpec &spec, QObject *parent=0): QGeoTiledMapReply (spec, parent) {} + void callSetError ( Error error, const QString & errorString ) {setError(error, errorString);} + void callSetFinished ( bool finished ) { setFinished(finished);} + void callSetCached(bool cached) { setFinished(cached);} + void callSetMapImageData(const QByteArray &data) { setMapImageData(data); } + void callSetMapImageFormat(const QString &format) { setMapImageFormat(format); } + void abort() { emit aborted(); } + +Q_SIGNALS: + void aborted(); +}; + +class QGeoMappingManagerEngineTest: public QGeoMappingManagerEngine + +{ +Q_OBJECT +public: + QGeoMappingManagerEngineTest(const QMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) : + QGeoMappingManagerEngine(parameters), + finishRequestImmediately_(true), + mappingReply_(0), + timerId_(0), + errorCode_(QGeoTiledMapReply::NoError) + { + Q_UNUSED(error) + Q_UNUSED(errorString) + if (parameters.contains("finishRequestImmediately")) + finishRequestImmediately_ = qvariant_cast(parameters.value("finishRequestImmediately")); + setLocale(QLocale (QLocale::German, QLocale::Germany)); + QGeoCameraCapabilities capabilities; + capabilities.setMinimumZoomLevel(0.0); + capabilities.setMaximumZoomLevel(20.0); + capabilities.setSupportsBearing(true); + setCameraCapabilities(capabilities); + } + + void init() + { + setTileSize(256); + QList types; + types << QGeoMapType(QGeoMapType::StreetMap,tr("Street Map"),tr("Test Street Map"), false, 1); + setSupportedMapTypes(types); + QGeoMappingManagerEngine::init(); + } + + QGeoTiledMapReply* getTileImage(const QGeoTileSpec &spec) + { + mappingReply_ = new TiledMapReplyTest(spec, this); + + QImage im(256, 256, QImage::Format_RGB888); + im.fill(QColor("lightgray")); + QRectF rect; + QString text("X: " + QString::number(spec.x()) + "\nY: " + QString::number(spec.y()) + "\nZ: " + QString::number(spec.zoom())); + rect.setWidth(250); + rect.setHeight(250); + rect.setLeft(3); + rect.setTop(3); + QPainter painter; + QPen pen(QColor("firebrick")); + painter.begin(&im); + painter.setPen(pen); + painter.setFont( QFont("Times", 35, 10, false)); + painter.drawText(rect, text); + // different border color for vertically and horizontally adjacent frames + if ((spec.x() + spec.y()) % 2 == 0) + pen.setColor(QColor("yellow")); + pen.setWidth(5); + painter.setPen(pen); + painter.drawRect(0,0,255,255); + painter.end(); + QPixmap pm = QPixmap::fromImage(im); + QByteArray bytes; + QBuffer buffer(&bytes); + buffer.open(QIODevice::WriteOnly); + pm.save(&buffer, "PNG"); + + mappingReply_->callSetMapImageData(bytes); + mappingReply_->callSetMapImageFormat("png"); + mappingReply_->callSetFinished(true); + + return static_cast(mappingReply_); + } + +public Q_SLOTS: + void requestAborted() + { + if (timerId_) { + killTimer(timerId_); + timerId_ = 0; + } + errorString_ = ""; + errorCode_ = QGeoTiledMapReply::NoError; + } + +protected: + void timerEvent(QTimerEvent *event) + { + Q_ASSERT(timerId_ == event->timerId()); + Q_ASSERT(mappingReply_); + killTimer(timerId_); + timerId_ = 0; + if (errorCode_) { + mappingReply_->callSetError(errorCode_, errorString_); + emit tileError(mappingReply_->tileSpec(), errorString_); + } else { + mappingReply_->callSetError(QGeoTiledMapReply::NoError, "no error"); + mappingReply_->callSetFinished(true); + } + // emit finished(mappingReply_); todo tileFinished + } + +private: + bool finishRequestImmediately_; + TiledMapReplyTest* mappingReply_; + int timerId_; + QGeoTiledMapReply::Error errorCode_; + QString errorString_; +}; + +#endif diff --git a/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h new file mode 100644 index 0000000..8ae5804 --- /dev/null +++ b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTINGMANAGERENGINE_TEST_H +#define QGEOROUTINGMANAGERENGINE_TEST_H + +#include +#include +#include +#include +#include + +#include +#include +#include + +QT_USE_NAMESPACE + + +class RouteReplyTest :public QGeoRouteReply +{ + Q_OBJECT + +public: + RouteReplyTest(QObject *parent=0) :QGeoRouteReply (QGeoRouteRequest(), parent) + {} + void callSetError ( Error error, const QString & errorString ) {setError(error, errorString);} + void callSetFinished ( bool finished ) {setFinished(finished);} + void callSetRoutes(const QList &routes) {setRoutes(routes);} + + void abort() { + emit aborted(); + } +Q_SIGNALS: + void aborted(); +}; + +class QGeoRoutingManagerEngineTest: public QGeoRoutingManagerEngine +{ + Q_OBJECT + RouteReplyTest* routeReply_; + bool finishRequestImmediately_; + int timerId_; + QGeoRouteReply::Error errorCode_; + QString errorString_; + +public: + QGeoRoutingManagerEngineTest(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) : + QGeoRoutingManagerEngine(parameters), + routeReply_(0), + finishRequestImmediately_(true), + timerId_(0), + errorCode_(QGeoRouteReply::NoError) + { + Q_UNUSED(error) + Q_UNUSED(errorString) + + if (parameters.contains("gc_finishRequestImmediately")) { + finishRequestImmediately_ = qvariant_cast(parameters.value("gc_finishRequestImmediately")); + } + + setLocale(QLocale (QLocale::German, QLocale::Germany)); + setSupportedFeatureTypes ( + QGeoRouteRequest::NoFeature | QGeoRouteRequest::TollFeature | + QGeoRouteRequest::HighwayFeature | QGeoRouteRequest::PublicTransitFeature | + QGeoRouteRequest::FerryFeature | QGeoRouteRequest::TunnelFeature | + QGeoRouteRequest::DirtRoadFeature | QGeoRouteRequest::ParksFeature | + QGeoRouteRequest::MotorPoolLaneFeature ); + setSupportedFeatureWeights ( + QGeoRouteRequest::NeutralFeatureWeight | QGeoRouteRequest::PreferFeatureWeight | + QGeoRouteRequest::RequireFeatureWeight | QGeoRouteRequest::AvoidFeatureWeight | + QGeoRouteRequest::DisallowFeatureWeight ); + setSupportedManeuverDetails ( + QGeoRouteRequest::NoManeuvers | QGeoRouteRequest::BasicManeuvers); + setSupportedRouteOptimizations ( + QGeoRouteRequest::ShortestRoute | QGeoRouteRequest::FastestRoute | + QGeoRouteRequest::MostEconomicRoute | QGeoRouteRequest::MostScenicRoute); + setSupportedSegmentDetails ( + QGeoRouteRequest::NoSegmentData | QGeoRouteRequest::BasicSegmentData ); + setSupportedTravelModes ( + QGeoRouteRequest::CarTravel | QGeoRouteRequest::PedestrianTravel | + QGeoRouteRequest::BicycleTravel | QGeoRouteRequest::PublicTransitTravel | + QGeoRouteRequest::TruckTravel ); + } + + virtual QGeoRouteReply* calculateRoute(const QGeoRouteRequest& request) + { + routeReply_ = new RouteReplyTest(); + connect(routeReply_, SIGNAL(aborted()), this, SLOT(requestAborted())); + + if (request.numberAlternativeRoutes() > 70) { + errorCode_ = (QGeoRouteReply::Error)(request.numberAlternativeRoutes() - 70); + errorString_ = "error"; + } else { + errorCode_ = QGeoRouteReply::NoError; + errorString_ = ""; + } + setRoutes(request, routeReply_); + if (finishRequestImmediately_) { + if (errorCode_) { + routeReply_->callSetError(errorCode_, errorString_); + } else { + routeReply_->callSetError(QGeoRouteReply::NoError, "no error"); + routeReply_->callSetFinished(true); + } + } else { + // we only allow serialized requests in QML - previous must have been aborted or finished + Q_ASSERT(timerId_ == 0); + timerId_ = startTimer(200); + } + return static_cast(routeReply_); + } + + void setRoutes(const QGeoRouteRequest& request, RouteReplyTest* reply) + { + QList routes; + for (int i = 0; i < request.numberAlternativeRoutes(); ++i) { + QGeoRoute route; + route.setPath(request.waypoints()); + routes.append(route); + } + reply->callSetRoutes(routes); + } + +public Q_SLOTS: + void requestAborted() + { + if (timerId_) { + killTimer(timerId_); + timerId_ = 0; + } + errorCode_ = QGeoRouteReply::NoError; + errorString_ = ""; + } + +protected: + void timerEvent(QTimerEvent *event) + { + Q_UNUSED(event); + Q_ASSERT(timerId_ == event->timerId()); + Q_ASSERT(routeReply_); + killTimer(timerId_); + timerId_ = 0; + if (errorCode_) { + routeReply_->callSetError(errorCode_, errorString_); + emit error(routeReply_, errorCode_, errorString_); + } else { + routeReply_->callSetError(QGeoRouteReply::NoError, "no error"); + routeReply_->callSetFinished(true); + emit finished(routeReply_); + } + } +}; + +#endif diff --git a/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.cpp b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.cpp new file mode 100644 index 0000000..d3b0461 --- /dev/null +++ b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoserviceproviderplugin_test.h" +#include "qgeocodingmanagerengine_test.h" +#include "qgeoroutingmanagerengine_test.h" +#include "qgeotiledmappingmanagerengine_test.h" +#include "qplacemanagerengine_test.h" + +#include + +namespace +{ + template + EngineType * createEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) + { + const QString failError = parameters.value(QStringLiteral("error")).toString(); + const QString failErrorString = parameters.value(QStringLiteral("errorString")).toString(); + + if (!failError.isEmpty()) { + *error = QGeoServiceProvider::Error(failError.toInt()); + *errorString = failErrorString; + return 0; + } else { + return new EngineType(parameters, error, errorString); + } + } +} + +QGeoServiceProviderFactoryTest::QGeoServiceProviderFactoryTest() +{ +} + +QGeoServiceProviderFactoryTest::~QGeoServiceProviderFactoryTest() +{ +} + +QGeoRoutingManagerEngine* QGeoServiceProviderFactoryTest::createRoutingManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const +{ + return createEngine(parameters, error, errorString); +} + + +QGeoCodingManagerEngine* QGeoServiceProviderFactoryTest::createGeocodingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, + QString *errorString) const +{ + return createEngine(parameters, error, errorString); +} + + +QGeoMappingManagerEngine* QGeoServiceProviderFactoryTest::createMappingManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const +{ + return createEngine(parameters, error, errorString); +} + +QPlaceManagerEngine* QGeoServiceProviderFactoryTest::createPlaceManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const +{ + Q_UNUSED(error); + Q_UNUSED(errorString); + return new QPlaceManagerEngineTest(parameters); +} diff --git a/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h new file mode 100644 index 0000000..c606fdb --- /dev/null +++ b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDER_TEST_H +#define QGEOSERVICEPROVIDER_TEST_H + +#include +#include + +QT_USE_NAMESPACE + +class QGeoServiceProviderFactoryTest: public QObject, public QGeoServiceProviderFactory +{ + Q_OBJECT + Q_INTERFACES(QGeoServiceProviderFactory) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0" + FILE "geotestplugin.json") + +public: + QGeoServiceProviderFactoryTest(); + ~QGeoServiceProviderFactoryTest(); + + QGeoMappingManagerEngine* createMappingManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const; + QGeoRoutingManagerEngine* createRoutingManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString ) const; + QGeoCodingManagerEngine* createGeocodingManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const; + QPlaceManagerEngine* createPlaceManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const; +}; + +#endif + + diff --git a/tests/auto/geotestplugin/qgeotiledmap_test.h b/tests/auto/geotestplugin/qgeotiledmap_test.h new file mode 100644 index 0000000..27ff716 --- /dev/null +++ b/tests/auto/geotestplugin/qgeotiledmap_test.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEDMAP_TEST_H +#define QGEOTILEDMAP_TEST_H + +#include +#include + +QT_USE_NAMESPACE +class QGeoTiledMappingManagerEngineTest; +class QGeoTiledMapTest: public QGeoTiledMap +{ + Q_OBJECT +public: + QGeoTiledMapTest(QGeoTiledMappingManagerEngine *engine, QObject *parent = 0): + QGeoTiledMap(engine, parent), + m_engine(engine){} +public: + using QGeoTiledMap::setCameraData; + QGeoTiledMappingManagerEngine *m_engine; +}; + +#endif diff --git a/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h new file mode 100644 index 0000000..2765c26 --- /dev/null +++ b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEDMAPPINGMANAGERENGINE_TEST_H +#define QGEOTILEDMAPPINGMANAGERENGINE_TEST_H + +#include +#include +#include +#include +#include +#include + +#include "qgeotiledmap_test.h" +#include "qgeotilefetcher_test.h" + +QT_USE_NAMESPACE + +class QGeoTiledMappingManagerEngineTest: public QGeoTiledMappingManagerEngine +{ +Q_OBJECT +public: + QGeoTiledMappingManagerEngineTest(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) : + QGeoTiledMappingManagerEngine() + { + Q_UNUSED(error) + Q_UNUSED(errorString) + + setLocale(QLocale (QLocale::German, QLocale::Germany)); + QGeoCameraCapabilities capabilities; + capabilities.setMinimumZoomLevel(0.0); + capabilities.setMaximumZoomLevel(20.0); + capabilities.setSupportsBearing(true); + setTileSize(QSize(256, 256)); + + QList mapTypes; + mapTypes << QGeoMapType(QGeoMapType::StreetMap, tr("StreetMap"), tr("StreetMap"), false, false, 1); + mapTypes << QGeoMapType(QGeoMapType::SatelliteMapDay, tr("SatelliteMapDay"), tr("SatelliteMapDay"), false, false, 2); + mapTypes << QGeoMapType(QGeoMapType::CycleMap, tr("CycleMap"), tr("CycleMap"), false, false, 3); + setSupportedMapTypes(mapTypes); + + QGeoTileFetcherTest *fetcher = new QGeoTileFetcherTest(this); + if (parameters.contains(QStringLiteral("finishRequestImmediately"))) + fetcher->setFinishRequestImmediately(parameters.value(QStringLiteral("finishRequestImmediately")).toBool()); + if (parameters.contains(QStringLiteral("tileSize"))) { + int tileSize = parameters.value(QStringLiteral("tileSize")).toInt(); + setTileSize(QSize(tileSize, tileSize)); + } + if (parameters.contains(QStringLiteral("maxZoomLevel"))) { + double maxZoomLevel = parameters.value(QStringLiteral("maxZoomLevel")).toDouble(); + capabilities.setMaximumZoomLevel(maxZoomLevel); + } + + setCameraCapabilities(capabilities); + fetcher->setTileSize(tileSize()); + setTileFetcher(fetcher); + } + + QGeoMap *createMap() + { + return new QGeoTiledMapTest(this); + } + +}; + +#endif diff --git a/tests/auto/geotestplugin/qgeotilefetcher_test.h b/tests/auto/geotestplugin/qgeotilefetcher_test.h new file mode 100644 index 0000000..a25b011 --- /dev/null +++ b/tests/auto/geotestplugin/qgeotilefetcher_test.h @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOTILEFETCHER_TEST_H +#define QGEOTILEFETCHER_TEST_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class TiledMapReplyTest :public QGeoTiledMapReply +{ + Q_OBJECT +public: + TiledMapReplyTest(const QGeoTileSpec &spec, QObject *parent=0): QGeoTiledMapReply (spec, parent) {} + void callSetError ( Error error, const QString & errorString ) {setError(error, errorString);} + void callSetFinished ( bool finished ) { setFinished(finished);} + void callSetCached(bool cached) { setFinished(cached);} + void callSetMapImageData(const QByteArray &data) { setMapImageData(data); } + void callSetMapImageFormat(const QString &format) { setMapImageFormat(format); } + void abort() { emit aborted(); } + +Q_SIGNALS: + void aborted(); +}; + +class QGeoTileFetcherTest: public QGeoTileFetcher +{ + Q_OBJECT +public: + QGeoTileFetcherTest(QObject *parent = 0) + : QGeoTileFetcher(parent), finishRequestImmediately_(false), errorCode_(QGeoTiledMapReply::NoError) + { + } + + bool init() + { + return true; + } + + QGeoTiledMapReply* getTileImage(const QGeoTileSpec &spec) + { + TiledMapReplyTest* mappingReply = new TiledMapReplyTest(spec, this); + + QImage im(256, 256, QImage::Format_RGB888); + im.fill(QColor("lightgray")); + QRectF rect; + QString text("X: " + QString::number(spec.x()) + "\nY: " + QString::number(spec.y()) + "\nZ: " + QString::number(spec.zoom())); + rect.setWidth(250); + rect.setHeight(250); + rect.setLeft(3); + rect.setTop(3); + QPainter painter; + QPen pen(QColor("firebrick")); + painter.begin(&im); + painter.setPen(pen); + painter.setFont( QFont("Times", 35, 10, false)); + painter.drawText(rect, text); + // different border color for vertically and horizontally adjacent frames + if ((spec.x() + spec.y()) % 2 == 0) + pen.setColor(QColor("yellow")); + pen.setWidth(5); + painter.setPen(pen); + painter.drawRect(0,0,255,255); + painter.end(); + QPixmap pm = QPixmap::fromImage(im); + QByteArray bytes; + QBuffer buffer(&bytes); + buffer.open(QIODevice::WriteOnly); + pm.save(&buffer, "PNG"); + + mappingReply->callSetMapImageData(bytes); + mappingReply->callSetMapImageFormat("png"); + + if (finishRequestImmediately_) { + updateRequest(mappingReply); + return mappingReply; + } else { + if (m_queue.isEmpty()) + timer_.start(500, this); + m_queue.append(mappingReply); + } + + return mappingReply; + } + + void setFinishRequestImmediately(bool enabled) + { + finishRequestImmediately_ = enabled; + } + + void setTileSize(QSize tileSize) + { + tileSize_ = tileSize; + } + +public Q_SLOTS: + void requestAborted() + { + timer_.stop(); + errorString_.clear(); + errorCode_ = QGeoTiledMapReply::NoError; + } +Q_SIGNALS: + void tileFetched(const QGeoTileSpec&); + +protected: + void updateRequest(TiledMapReplyTest* mappingReply) + { + if (errorCode_) { + mappingReply->callSetError(errorCode_, errorString_); + emit tileError(mappingReply->tileSpec(), errorString_); + } else { + mappingReply->callSetError(QGeoTiledMapReply::NoError, "no error"); + mappingReply->callSetFinished(true); + emit tileFetched(mappingReply->tileSpec()); + } + } + + void timerEvent(QTimerEvent *event) + { + if (event->timerId() != timer_.timerId()) { + QGeoTileFetcher::timerEvent(event); + return; + } + updateRequest(m_queue.takeFirst()); + if (m_queue.isEmpty()) { + timer_.stop(); + } + } + +private: + bool finishRequestImmediately_; + QBasicTimer timer_; + QGeoTiledMapReply::Error errorCode_; + QString errorString_; + QSize tileSize_; + QList m_queue; +}; + +#endif diff --git a/tests/auto/geotestplugin/qplacemanagerengine_test.h b/tests/auto/geotestplugin/qplacemanagerengine_test.h new file mode 100644 index 0000000..f8af1ed --- /dev/null +++ b/tests/auto/geotestplugin/qplacemanagerengine_test.h @@ -0,0 +1,693 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLACEMANAGERENGINE_TEST_H +#define QPLACEMANAGERENGINE_TEST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +inline uint qHash(const QPlaceCategory &category) +{ + return qHash(QUuid(category.categoryId().toLatin1())); +} + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +class PlaceReply : public QPlaceReply +{ + Q_OBJECT + + friend class QPlaceManagerEngineTest; + +public: + PlaceReply(QObject *parent = 0) + : QPlaceReply(parent) + { } + + Q_INVOKABLE void emitFinished() + { + emit finished(); + } +}; + +class ContentReply : public QPlaceContentReply +{ + Q_OBJECT + + friend class QPlaceManagerEngineTest; + +public: + ContentReply(QObject *parent = 0) + : QPlaceContentReply(parent) + {} + + Q_INVOKABLE void emitError() + { + emit error(error(), errorString()); + } + + Q_INVOKABLE void emitFinished() + { + emit finished(); + } +}; + +class DetailsReply : public QPlaceDetailsReply +{ + Q_OBJECT + + friend class QPlaceManagerEngineTest; + +public: + DetailsReply(QObject *parent = 0) + : QPlaceDetailsReply(parent) + { } + + Q_INVOKABLE void emitError() + { + emit error(error(), errorString()); + } + + Q_INVOKABLE void emitFinished() + { + emit finished(); + } +}; + +class IdReply : public QPlaceIdReply +{ + Q_OBJECT + + friend class QPlaceManagerEngineTest; + +public: + IdReply(QPlaceIdReply::OperationType type, QObject *parent = 0) + : QPlaceIdReply(type, parent) + { } + + Q_INVOKABLE void emitError() + { + emit error(error(), errorString()); + } + + Q_INVOKABLE void emitFinished() + { + emit finished(); + } +}; + +class PlaceSearchReply : public QPlaceSearchReply +{ + Q_OBJECT + +public: + PlaceSearchReply(const QList &results, QObject *parent = 0) + : QPlaceSearchReply(parent) + { + setResults(results); + } + + Q_INVOKABLE void emitError() + { + emit error(error(), errorString()); + } + + Q_INVOKABLE void emitFinished() + { + emit finished(); + } +}; + +class SuggestionReply : public QPlaceSearchSuggestionReply +{ + Q_OBJECT + +public: + SuggestionReply(const QStringList &suggestions, QObject *parent = 0) + : QPlaceSearchSuggestionReply(parent) + { + setSuggestions(suggestions); + } + + Q_INVOKABLE void emitError() + { + emit error(error(), errorString()); + } + + Q_INVOKABLE void emitFinished() + { + emit finished(); + } +}; + +class QPlaceManagerEngineTest : public QPlaceManagerEngine +{ + Q_OBJECT +public: + QPlaceManagerEngineTest(const QVariantMap ¶meters) + : QPlaceManagerEngine(parameters) + { + m_locales << QLocale(); + if (parameters.value(QStringLiteral("initializePlaceData"), false).toBool()) { + QFile placeData(QFINDTESTDATA("place_data.json")); + QVERIFY(placeData.exists()); + if (placeData.open(QIODevice::ReadOnly)) { + QJsonDocument document = QJsonDocument::fromJson(placeData.readAll()); + + if (document.isObject()) { + QJsonObject o = document.object(); + + if (o.contains(QStringLiteral("categories"))) { + QJsonArray categories = o.value(QStringLiteral("categories")).toArray(); + + for (int i = 0; i < categories.count(); ++i) { + QJsonObject c = categories.at(i).toObject(); + + QPlaceCategory category; + + category.setName(c.value(QStringLiteral("name")).toString()); + category.setCategoryId(c.value(QStringLiteral("id")).toString()); + + m_categories.insert(category.categoryId(), category); + + const QString parentId = c.value(QStringLiteral("parentId")).toString(); + m_childCategories[parentId].append(category.categoryId()); + } + } + + if (o.contains(QStringLiteral("places"))) { + QJsonArray places = o.value(QStringLiteral("places")).toArray(); + + for (int i = 0; i < places.count(); ++i) { + QJsonObject p = places.at(i).toObject(); + + QPlace place; + + place.setName(p.value(QStringLiteral("name")).toString()); + place.setPlaceId(p.value(QStringLiteral("id")).toString()); + + QList categories; + QJsonArray ca = p.value(QStringLiteral("categories")).toArray(); + for (int j = 0; j < ca.count(); ++j) { + QPlaceCategory c = m_categories.value(ca.at(j).toString()); + if (!c.isEmpty()) + categories.append(c); + } + place.setCategories(categories); + + QGeoCoordinate coordinate; + QJsonObject lo = p.value(QStringLiteral("location")).toObject(); + coordinate.setLatitude(lo.value(QStringLiteral("latitude")).toDouble()); + coordinate.setLongitude(lo.value(QStringLiteral("longitude")).toDouble()); + + QGeoLocation location; + location.setCoordinate(coordinate); + + place.setLocation(location); + + m_places.insert(place.placeId(), place); + + QStringList recommendations; + QJsonArray ra = p.value(QStringLiteral("recommendations")).toArray(); + for (int j = 0; j < ra.count(); ++j) + recommendations.append(ra.at(j).toString()); + m_placeRecommendations.insert(place.placeId(), recommendations); + + QJsonArray revArray = p.value(QStringLiteral("reviews")).toArray(); + QList reviews; + for (int j = 0; j < revArray.count(); ++j) { + QJsonObject ro = revArray.at(j).toObject(); + QPlaceReview review; + if (ro.contains(QStringLiteral("title"))) + review.setTitle(ro.value(QStringLiteral("title")).toString()); + if (ro.contains(QStringLiteral("text"))) + review.setText(ro.value(QStringLiteral("text")).toString()); + + if (ro.contains(QStringLiteral("language"))) + review.setLanguage(ro.value("language").toString()); + + if (ro.contains(QStringLiteral("rating"))) + review.setRating(ro.value("rating").toDouble()); + + if (ro.contains(QStringLiteral("dateTime"))) + review.setDateTime(QDateTime::fromString( + ro.value(QStringLiteral("dateTime")).toString(), + QStringLiteral("hh:mm dd-MM-yyyy"))); + if (ro.contains(QStringLiteral("reviewId"))) + review.setReviewId(ro.value("reviewId").toString()); + + reviews << review; + } + m_placeReviews.insert(place.placeId(), reviews); + + QJsonArray imgArray = p.value(QStringLiteral("images")).toArray(); + QList images; + for (int j = 0; j < imgArray.count(); ++j) { + QJsonObject imgo = imgArray.at(j).toObject(); + QPlaceImage image; + if (imgo.contains(QStringLiteral("url"))) + image.setUrl(imgo.value(QStringLiteral("url")).toString()); + + if (imgo.contains("imageId")) + image.setImageId(imgo.value(QStringLiteral("imageId")).toString()); + + if (imgo.contains("mimeType")) + image.setMimeType(imgo.value(QStringLiteral("mimeType")).toString()); + + images << image; + } + + m_placeImages.insert(place.placeId(), images); + + QJsonArray edArray = p.value(QStringLiteral("editorials")).toArray(); + QList editorials; + for (int j = 0; j < edArray.count(); ++j) { + QJsonObject edo = edArray.at(j).toObject(); + QPlaceEditorial editorial; + if (edo.contains(QStringLiteral("title"))) + editorial.setTitle(edo.value(QStringLiteral("title")).toString()); + + if (edo.contains(QStringLiteral("text"))) + editorial.setText(edo.value(QStringLiteral("text")).toString()); + + if (edo.contains(QStringLiteral("language"))) + editorial.setLanguage(edo.value(QStringLiteral("language")).toString()); + + editorials << editorial; + } + + m_placeEditorials.insert(place.placeId(), editorials); + } + } + } + } + } + } + + QPlaceDetailsReply *getPlaceDetails(const QString &placeId) Q_DECL_OVERRIDE + { + DetailsReply *reply = new DetailsReply(this); + + if (placeId.isEmpty() || !m_places.contains(placeId)) { + reply->setError(QPlaceReply::PlaceDoesNotExistError, tr("Place does not exist")); + QMetaObject::invokeMethod(reply, "emitError", Qt::QueuedConnection); + } else { + reply->setPlace(m_places.value(placeId)); + } + + QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); + + return reply; + } + + QPlaceContentReply *getPlaceContent(const QPlaceContentRequest &query) Q_DECL_OVERRIDE + { + ContentReply *reply = new ContentReply(this); + if (query.placeId().isEmpty() || !m_places.contains(query.placeId())) { + reply->setError(QPlaceReply::PlaceDoesNotExistError, tr("Place does not exist")); + QMetaObject::invokeMethod(reply, "emitError", Qt::QueuedConnection); + + } else { + QPlaceContent::Collection collection; + int totalCount = 0; + switch (query.contentType()) { + case QPlaceContent::ReviewType: + totalCount = m_placeReviews.value(query.placeId()).count(); + break; + case QPlaceContent::ImageType: + totalCount = m_placeImages.value(query.placeId()).count(); + break; + case QPlaceContent::EditorialType: + totalCount = m_placeEditorials.value(query.placeId()).count(); + default: + //do nothing + break; + } + + QVariantMap context = query.contentContext().toMap(); + + int offset = context.value(QStringLiteral("offset"), 0).toInt(); + int max = (query.limit() == -1) ? totalCount + : qMin(offset + query.limit(), totalCount); + for (int i = offset; i < max; ++i) { + switch (query.contentType()) { + case QPlaceContent::ReviewType: + collection.insert(i, m_placeReviews.value(query.placeId()).at(i)); + break; + case QPlaceContent::ImageType: + collection.insert(i, m_placeImages.value(query.placeId()).at(i)); + break; + case QPlaceContent::EditorialType: + collection.insert(i, m_placeEditorials.value(query.placeId()).at(i)); + default: + //do nothing + break; + } + } + + reply->setContent(collection); + reply->setTotalCount(totalCount); + + if (max != totalCount) { + context.clear(); + context.insert(QStringLiteral("offset"), offset + query.limit()); + QPlaceContentRequest request = query; + request.setContentContext(context); + reply->setNextPageRequest(request); + } + if (offset > 0) { + context.clear(); + context.insert(QStringLiteral("offset"), qMin(0, offset - query.limit())); + QPlaceContentRequest request = query; + request.setContentContext(context); + reply->setPreviousPageRequest(request); + } + } + + QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); + return reply; + } + + QPlaceSearchReply *search(const QPlaceSearchRequest &query) Q_DECL_OVERRIDE + { + QList results; + + if (!query.searchTerm().isEmpty()) { + foreach (const QPlace &place, m_places) { + if (!place.name().contains(query.searchTerm(), Qt::CaseInsensitive)) + continue; + + QPlaceResult r; + r.setPlace(place); + r.setTitle(place.name()); + + results.append(r); + } + } else if (!query.categories().isEmpty()) { + QSet categories = query.categories().toSet(); + foreach (const QPlace &place, m_places) { + if (place.categories().toSet().intersect(categories).isEmpty()) + continue; + + QPlaceResult r; + r.setPlace(place); + r.setTitle(place.name()); + + results.append(r); + } + } else if (!query.recommendationId().isEmpty()) { + QStringList recommendations = m_placeRecommendations.value(query.recommendationId()); + foreach (const QString &id, recommendations) { + QPlaceResult r; + r.setPlace(m_places.value(id)); + r.setTitle(r.place().name()); + + results.append(r); + } + } + + PlaceSearchReply *reply = new PlaceSearchReply(results, this); + + QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); + + return reply; + } + + QPlaceSearchSuggestionReply *searchSuggestions(const QPlaceSearchRequest &query) Q_DECL_OVERRIDE + { + QStringList suggestions; + if (query.searchTerm() == QLatin1String("test")) { + suggestions << QStringLiteral("test1"); + suggestions << QStringLiteral("test2"); + suggestions << QStringLiteral("test3"); + } + + SuggestionReply *reply = new SuggestionReply(suggestions, this); + + QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); + + return reply; + } + + QPlaceIdReply *savePlace(const QPlace &place) Q_DECL_OVERRIDE + { + IdReply *reply = new IdReply(QPlaceIdReply::SavePlace, this); + + if (!place.placeId().isEmpty() && !m_places.contains(place.placeId())) { + reply->setError(QPlaceReply::PlaceDoesNotExistError, tr("Place does not exist")); + QMetaObject::invokeMethod(reply, "emitError", Qt::QueuedConnection); + } else if (!place.placeId().isEmpty()) { + m_places.insert(place.placeId(), place); + reply->setId(place.placeId()); + } else { + QPlace p = place; + p.setPlaceId(QUuid::createUuid().toString()); + m_places.insert(p.placeId(), p); + + reply->setId(p.placeId()); + } + + QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); + + return reply; + } + + QPlaceIdReply *removePlace(const QString &placeId) Q_DECL_OVERRIDE + { + IdReply *reply = new IdReply(QPlaceIdReply::RemovePlace, this); + reply->setId(placeId); + + if (!m_places.contains(placeId)) { + reply->setError(QPlaceReply::PlaceDoesNotExistError, tr("Place does not exist")); + QMetaObject::invokeMethod(reply, "emitError", Qt::QueuedConnection); + } else { + m_places.remove(placeId); + } + + QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); + + return reply; + } + + QPlaceIdReply *saveCategory(const QPlaceCategory &category, const QString &parentId) Q_DECL_OVERRIDE + { + IdReply *reply = new IdReply(QPlaceIdReply::SaveCategory, this); + + if ((!category.categoryId().isEmpty() && !m_categories.contains(category.categoryId())) || + (!parentId.isEmpty() && !m_categories.contains(parentId))) { + reply->setError(QPlaceReply::CategoryDoesNotExistError, tr("Category does not exist")); + QMetaObject::invokeMethod(reply, "emitError", Qt::QueuedConnection); + } else if (!category.categoryId().isEmpty()) { + m_categories.insert(category.categoryId(), category); + QStringList children = m_childCategories.value(parentId); + + QMutableHashIterator i(m_childCategories); + while (i.hasNext()) { + i.next(); + i.value().removeAll(category.categoryId()); + } + + if (!children.contains(category.categoryId())) { + children.append(category.categoryId()); + m_childCategories.insert(parentId, children); + } + reply->setId(category.categoryId()); + } else { + QPlaceCategory c = category; + c.setCategoryId(QUuid::createUuid().toString()); + m_categories.insert(c.categoryId(), c); + QStringList children = m_childCategories.value(parentId); + if (!children.contains(c.categoryId())) { + children.append(c.categoryId()); + m_childCategories.insert(parentId, children); + } + + reply->setId(c.categoryId()); + } + + QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); + + return reply; + } + + QPlaceIdReply *removeCategory(const QString &categoryId) Q_DECL_OVERRIDE + { + IdReply *reply = new IdReply(QPlaceIdReply::RemoveCategory, this); + reply->setId(categoryId); + + if (!m_categories.contains(categoryId)) { + reply->setError(QPlaceReply::CategoryDoesNotExistError, tr("Category does not exist")); + QMetaObject::invokeMethod(reply, "emitError", Qt::QueuedConnection); + } else { + m_categories.remove(categoryId); + + QMutableHashIterator i(m_childCategories); + while (i.hasNext()) { + i.next(); + i.value().removeAll(categoryId); + } + } + + QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); + + return reply; + } + + QPlaceReply *initializeCategories() Q_DECL_OVERRIDE + { + QPlaceReply *reply = new PlaceReply(this); + + QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); + + return reply; + } + + QString parentCategoryId(const QString &categoryId) const Q_DECL_OVERRIDE + { + QHashIterator i(m_childCategories); + while (i.hasNext()) { + i.next(); + if (i.value().contains(categoryId)) + return i.key(); + } + + return QString(); + } + + virtual QStringList childCategoryIds(const QString &categoryId) const Q_DECL_OVERRIDE + { + return m_childCategories.value(categoryId); + } + + virtual QPlaceCategory category(const QString &categoryId) const Q_DECL_OVERRIDE + { + return m_categories.value(categoryId); + } + + QList childCategories(const QString &parentId) const Q_DECL_OVERRIDE + { + QList categories; + + foreach (const QString &id, m_childCategories.value(parentId)) + categories.append(m_categories.value(id)); + + return categories; + } + + QList locales() const Q_DECL_OVERRIDE + { + return m_locales; + } + + void setLocales(const QList &locales) Q_DECL_OVERRIDE + { + m_locales = locales; + } + + QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size) const Q_DECL_OVERRIDE + { + QList > candidates; + + QMap sizeDictionary; + sizeDictionary.insert(QStringLiteral("s"), 20); + sizeDictionary.insert(QStringLiteral("m"), 30); + sizeDictionary.insert(QStringLiteral("l"), 50); + + QStringList sizeKeys; + sizeKeys << QStringLiteral("s") << QStringLiteral("m") << QStringLiteral("l"); + + foreach (const QString &sizeKey, sizeKeys) + { + if (icon.parameters().contains(sizeKey)) + candidates.append(QPair(sizeDictionary.value(sizeKey), + icon.parameters().value(sizeKey).toUrl())); + } + + if (candidates.isEmpty()) + return QUrl(); + else if (candidates.count() == 1) { + return candidates.first().second; + } else { + //we assume icons are squarish so we can use height to + //determine which particular icon to return + int requestedHeight = size.height(); + + for (int i = 0; i < candidates.count() - 1; ++i) { + int thresholdHeight = (candidates.at(i).first + candidates.at(i+1).first) / 2; + if (requestedHeight < thresholdHeight) + return candidates.at(i).second; + } + return candidates.last().second; + } + } + + QPlace compatiblePlace(const QPlace &original) const Q_DECL_OVERRIDE + { + QPlace place; + place.setName(original.name()); + return place; + } + +private: + QList m_locales; + QHash m_places; + QHash m_categories; + QHash m_childCategories; + QHash m_placeRecommendations; + QHash > m_placeReviews; + QHash > m_placeImages; + QHash > m_placeEditorials; +}; + +#endif diff --git a/tests/auto/geotestplugin/testdata.qrc b/tests/auto/geotestplugin/testdata.qrc new file mode 100644 index 0000000..23eed23 --- /dev/null +++ b/tests/auto/geotestplugin/testdata.qrc @@ -0,0 +1,5 @@ + + + place_data.json + + diff --git a/tests/auto/maptype/maptype.pro b/tests/auto/maptype/maptype.pro new file mode 100644 index 0000000..1622dc5 --- /dev/null +++ b/tests/auto/maptype/maptype.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_maptype + +SOURCES += tst_maptype.cpp + +QT += location-private testlib diff --git a/tests/auto/maptype/tst_maptype.cpp b/tests/auto/maptype/tst_maptype.cpp new file mode 100644 index 0000000..9b7956f --- /dev/null +++ b/tests/auto/maptype/tst_maptype.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QGeoMapType) + +class tst_MapType : public QObject +{ + Q_OBJECT + +public: + tst_MapType(); + +private Q_SLOTS: + void constructorTest(); + void comparison(); + void comparison_data(); +}; + +tst_MapType::tst_MapType() {} + +void tst_MapType::constructorTest() +{ + QGeoMapType *testObjPtr = new QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street map"), + QStringLiteral("map description"), true, true, 1); + QVERIFY(testObjPtr); + QCOMPARE(testObjPtr->style(), QGeoMapType::StreetMap); + QCOMPARE(testObjPtr->name(), QStringLiteral("street map")); + QCOMPARE(testObjPtr->description(), QStringLiteral("map description")); + QVERIFY(testObjPtr->mobile()); + QVERIFY(testObjPtr->night()); + QCOMPARE(testObjPtr->mapId(), 1); + delete testObjPtr; + + testObjPtr = new QGeoMapType(); + QCOMPARE(testObjPtr->style(), QGeoMapType::NoMap); + QVERIFY2(testObjPtr->name().isEmpty(), "Wrong default value"); + QVERIFY2(testObjPtr->description().isEmpty(), "Wrong default value"); + QVERIFY2(!testObjPtr->mobile(), "Wrong default value"); + QVERIFY2(!testObjPtr->night(), "Wrong default value"); + QCOMPARE(testObjPtr->mapId(), 0); + delete testObjPtr; +} + +void tst_MapType::comparison_data() +{ + QTest::addColumn("type1"); + QTest::addColumn("type2"); + QTest::addColumn("expected"); + + QTest::newRow("null") << QGeoMapType() << QGeoMapType() << true; + + QTest::newRow("equal") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42) + << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42) + << true; + + QTest::newRow("style") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42) + << QGeoMapType(QGeoMapType::TerrainMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42) + << false; + + QTest::newRow("name") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42) + << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("different name"), + QStringLiteral("street desc"), false, false, 42) + << false; + + QTest::newRow("description") << QGeoMapType(QGeoMapType::StreetMap, + QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42) + << QGeoMapType(QGeoMapType::StreetMap, + QStringLiteral("street name"), + QStringLiteral("different desc"), false, false, 42) + << false; + + QTest::newRow("mobile") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42) + << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), true, false, 42) + << false; + + QTest::newRow("night") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42) + << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, true, 42) + << false; + + QTest::newRow("id") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42) + << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 99) + << false; +} + +void tst_MapType::comparison() +{ + QFETCH(QGeoMapType, type1); + QFETCH(QGeoMapType, type2); + QFETCH(bool, expected); + + QCOMPARE(type1 == type2, expected); + QCOMPARE(type1 != type2, !expected); +} + +QTEST_APPLESS_MAIN(tst_MapType) + +#include "tst_maptype.moc" diff --git a/tests/auto/nokia_services/nokia_services.pro b/tests/auto/nokia_services/nokia_services.pro new file mode 100644 index 0000000..4c56e9f --- /dev/null +++ b/tests/auto/nokia_services/nokia_services.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += routing places_semiauto diff --git a/tests/auto/nokia_services/places_semiauto/places_semiauto.pro b/tests/auto/nokia_services/places_semiauto/places_semiauto.pro new file mode 100644 index 0000000..7953509 --- /dev/null +++ b/tests/auto/nokia_services/places_semiauto/places_semiauto.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplaces + +HEADERS += ../../placemanager_utils/placemanager_utils.h + +SOURCES += tst_places.cpp \ + ../../placemanager_utils/placemanager_utils.cpp + +QT += location testlib diff --git a/tests/auto/nokia_services/places_semiauto/tst_places.cpp b/tests/auto/nokia_services/places_semiauto/tst_places.cpp new file mode 100644 index 0000000..8e5289d --- /dev/null +++ b/tests/auto/nokia_services/places_semiauto/tst_places.cpp @@ -0,0 +1,745 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../placemanager_utils/placemanager_utils.h" + +QT_USE_NAMESPACE + +class tst_QPlaceManagerNokia : public PlaceManagerUtils +{ + Q_OBJECT +public: + enum ExpectedResults { + AnyResults, //zero or more results expected + SomeResults, //at least one result expected + NoResults // zero results expected + }; + + tst_QPlaceManagerNokia(); + +private Q_SLOTS: + void initTestCase(); + void search(); + void search_data(); + void searchResultFields(); + void recommendations(); + void recommendations_data(); + void details(); + void categories(); + void suggestions(); + void suggestions_data(); + void suggestionsMisc(); + void locale(); + void content(); + void content_data(); + void unsupportedFunctions(); + +private: + void commonAreas(QList *dataTags, QList *areas, + QList *errors, + QList *results); + + static const QLatin1String ValidKnownPlaceId; + static const QLatin1String ProxyEnv; + static const QLatin1String AppIdEnv; + static const QLatin1String TokenEnv; + + QGeoServiceProvider *provider; +}; + +Q_DECLARE_METATYPE(tst_QPlaceManagerNokia::ExpectedResults) + +// ValidKnownPlaceId is the id of a place with a full complement of place content. Editorials, +// reviews, images, recommendations. If it disappears these tests will fail. +// Currently it is set to an Eiffel Tower tourist office. +const QLatin1String tst_QPlaceManagerNokia::ValidKnownPlaceId("250u09tu-4561b8da952f4fd79c4e1998c3fcf032"); + +const QLatin1String tst_QPlaceManagerNokia::ProxyEnv("NOKIA_PLUGIN_PROXY"); +const QLatin1String tst_QPlaceManagerNokia::AppIdEnv("NOKIA_APPID"); +const QLatin1String tst_QPlaceManagerNokia::TokenEnv("NOKIA_TOKEN"); + +tst_QPlaceManagerNokia::tst_QPlaceManagerNokia() +{ +} + +void tst_QPlaceManagerNokia::initTestCase() +{ + QVariantMap params; + QStringList providers = QGeoServiceProvider::availableServiceProviders(); + QVERIFY(providers.contains("here")); +#ifndef QT_NO_PROCESS + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + + if (!(env.contains(AppIdEnv) && env.contains(TokenEnv))) + QSKIP("NOKIA_APPID and NOKIA_TOKEN environment variables not set");\ + + params.insert(QStringLiteral("here.app_id"), env.value(AppIdEnv)); + params.insert(QStringLiteral("here.token"), env.value(TokenEnv)); + + if (env.contains(ProxyEnv)) + params.insert(QStringLiteral("here.proxy"), env.value(ProxyEnv)); +#else + QSKIP("Cannot parse process environment, NOKIA_APPID and NOKIA_TOKEN not set"); +#endif + provider = new QGeoServiceProvider("here", params); + placeManager = provider->placeManager(); + QVERIFY(placeManager); +} + +void tst_QPlaceManagerNokia::search() +{ + QFETCH(QGeoShape, area); + QFETCH(QString, searchTerm); + QFETCH(QList, categories); + QFETCH(QPlaceReply::Error, error); + QFETCH(ExpectedResults, expectedResults); + + QPlaceSearchRequest searchRequest; + searchRequest.setSearchArea(area); + searchRequest.setSearchTerm(searchTerm); + if (categories.count() == 1) + searchRequest.setCategory(categories.first()); + else + searchRequest.setCategories(categories); + + QList results; + QVERIFY(doSearch(searchRequest, &results, error)); + + if (expectedResults == NoResults) + QVERIFY(results.count() == 0); + else if (expectedResults == SomeResults) + QVERIFY(results.count() > 0); +} + +void tst_QPlaceManagerNokia::search_data() +{ + QTest::addColumn("area"); + QTest::addColumn("searchTerm"); + QTest::addColumn >("categories"); + QTest::addColumn("hint"); + QTest::addColumn ("error"); + QTest::addColumn("expectedResults"); + + for (int i = 0; i < 3; i++) { + QByteArray suffix; + QGeoShape area; + if (i==0) { + area = QGeoCircle(QGeoCoordinate(-27.5, 153)); + suffix = " (Circle - center only)"; + } else if (i==1) { + area = QGeoCircle(QGeoCoordinate(-27.5, 153), 5000); + suffix = " (Circle - with radius specified)"; + } else { + area = QGeoRectangle(QGeoCoordinate(-26.5, 152), QGeoCoordinate(-28.5, 154)); + suffix = " (Rectangle)"; + } + + QByteArray dataTag = QByteArray("coordinate only") + suffix; + QTest::newRow(dataTag) << area + << QString() + << QList() + << QPlaceSearchRequest::UnspecifiedHint + << QPlaceReply::NoError + << SomeResults; + + dataTag = QByteArray("seach term") + suffix; + QTest::newRow(dataTag) << area + << "sushi" + << QList() + << QPlaceSearchRequest::UnspecifiedHint + << QPlaceReply::NoError + << SomeResults; + + QPlaceCategory eatDrinkCat; + eatDrinkCat.setCategoryId(QStringLiteral("eat-drink")); + dataTag = QByteArray("single valid category") + suffix; + QTest::newRow(dataTag) << area + << QString() + << (QList() + << eatDrinkCat) + << QPlaceSearchRequest::UnspecifiedHint + << QPlaceReply::NoError + << SomeResults; + + QPlaceCategory accommodationCat; + accommodationCat.setCategoryId(QStringLiteral("accommodation")); + dataTag = QByteArray("multiple valid categories") + suffix; + QTest::newRow(dataTag) << area + << QString() + << (QList() + << eatDrinkCat + << accommodationCat) + << QPlaceSearchRequest::UnspecifiedHint + << QPlaceReply::NoError + << SomeResults; + + QPlaceCategory nonExistentCat; + nonExistentCat.setCategoryId(QStringLiteral("klingon cuisine")); + dataTag = QByteArray("non-existent category") + suffix; + QTest::newRow(dataTag) << area + << QString() + << (QList() + << nonExistentCat) + << QPlaceSearchRequest::UnspecifiedHint + << QPlaceReply::NoError + << NoResults; + + dataTag = QByteArray("search term and category") + suffix; + QTest::newRow(dataTag) << area + << "sushi" + << (QList() + << eatDrinkCat) + << QPlaceSearchRequest::UnspecifiedHint + << QPlaceReply::BadArgumentError + << NoResults; + } + + + //invalid areas and boundary testing + QList dataTags; + QList areas; + QList errors; + QList results; + commonAreas(&dataTags, &areas, &errors, &results); + + for (int i = 0; i < dataTags.count(); ++i) { + QTest::newRow(dataTags.at(i)) << areas.at(i) + << "sushi" + << QList() + << QPlaceSearchRequest::UnspecifiedHint + << errors.at(i) + << results.at(i); + } + + //relevancy hints will be ignored by the backend, but should give a valid result + QTest::newRow("check using a distance relevancy hint") + << static_cast(QGeoCircle(QGeoCoordinate(-27.5, 153))) + << QStringLiteral("sushi") + << QList() + << QPlaceSearchRequest::DistanceHint + << QPlaceReply::NoError + << AnyResults; + + QTest::newRow("check using lexical place name hint") + << static_cast(QGeoCircle(QGeoCoordinate(-27.5, 153))) + << QStringLiteral("sushi") + << QList() + << QPlaceSearchRequest::LexicalPlaceNameHint + << QPlaceReply::NoError + << AnyResults; +} + +void tst_QPlaceManagerNokia::searchResultFields() +{ + //check that using a distance relevancy hint will give a valid result + //even though it will be ignored by the backend. + QPlaceSearchRequest searchRequest; + searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153))); + searchRequest.setSearchTerm(QStringLiteral("sushi")); + + QPlaceSearchReply *reply = placeManager->search(searchRequest); + QSignalSpy spy(reply, SIGNAL(finished())); + QTRY_VERIFY_WITH_TIMEOUT(spy.count() == 1, Timeout); + QVERIFY(reply->results().count() > 0); + + //check that search results have basic data filled in + QPlaceResult result= reply->results().at(0); + QVERIFY(!result.title().isEmpty()); + QVERIFY(!result.icon().url().isEmpty()); + QVERIFY(!qIsNaN(result.distance())); + QVERIFY(!result.place().name().isEmpty()); + QVERIFY(result.place().location().coordinate().isValid()); + QVERIFY(!result.place().location().address().text().isEmpty()); + QVERIFY(!result.place().location().address().isTextGenerated()); + QVERIFY(result.place().categories().count() == 1);//only primary category retrieved on + //search + + //sponsored and ratings fields are optional and thus have not been explicitly tested. +} + +void tst_QPlaceManagerNokia::recommendations() +{ + QFETCH(QString, recommendationId); + QFETCH(QString, searchTerm); + QFETCH(QGeoShape, searchArea); + QFETCH(QList, categories); + QFETCH(QPlaceReply::Error, error); + + QPlaceSearchRequest searchRequest; + searchRequest.setRecommendationId(recommendationId); + searchRequest.setSearchTerm(searchTerm); + searchRequest.setSearchArea(searchArea); + searchRequest.setCategories(categories); + + QList results; + QVERIFY(doSearch(searchRequest, &results, error)); + + if (error == QPlaceReply::NoError) + QVERIFY(results.count() > 0); +} + +void tst_QPlaceManagerNokia::recommendations_data() +{ + QTest::addColumn("recommendationId"); + QTest::addColumn("searchTerm"); + QTest::addColumn("searchArea"); + QTest::addColumn >("categories"); + QTest::addColumn("error"); + + QPlaceCategory eatDrinkCat; + eatDrinkCat.setCategoryId(QStringLiteral("eat-drink")); + + QTest::newRow("search recommendations with valid id") + << QString(ValidKnownPlaceId) + << QString() + << QGeoShape() + << QList() + << QPlaceReply::NoError; + + QTest::newRow("search for recommendations with invalid id") + << QStringLiteral("does_not_exist_id") + << QString() + << QGeoShape() + << QList() + << QPlaceReply::PlaceDoesNotExistError; + + QTest::newRow("search for recommendations with id and search term") + << QString(ValidKnownPlaceId) + << QStringLiteral("sushi") + << QGeoShape() + << QList() + << QPlaceReply::BadArgumentError; + + QTest::newRow("search for recommendations with an id and category") + << QString(ValidKnownPlaceId) + << QString() + << QGeoShape() + << (QList() << eatDrinkCat) + << QPlaceReply::BadArgumentError; + + QTest::newRow("search for recommendations with id, search term and category") + << QString(ValidKnownPlaceId) + << QStringLiteral("sushi") + << QGeoShape() + << (QList() << eatDrinkCat) + << QPlaceReply::BadArgumentError; + + QTest::newRow("search for recommendations with an id and search area") + << QString(ValidKnownPlaceId) + << QString() + << static_cast(QGeoCircle(QGeoCoordinate(-27.5, 153))) + << QList() + << QPlaceReply::BadArgumentError; +} + +void tst_QPlaceManagerNokia::details() +{ + QSKIP("Fetching details from HERE place server always fails - QTBUG-44837"); + //fetch the details of a valid place + QPlace place; + QVERIFY(doFetchDetails(ValidKnownPlaceId, &place)); + QVERIFY(!place.name().isEmpty()); + QVERIFY(!place.icon().url().isEmpty()); + QStringList contactTypes = place.contactTypes(); + QVERIFY(!contactTypes.isEmpty()); + foreach (const QString &contactType, contactTypes) { + QList details = place.contactDetails(contactType); + QVERIFY(details.count() > 0); + foreach (const QPlaceContactDetail &detail, details) { + QVERIFY(!detail.label().isEmpty()); + QVERIFY(!detail.value().isEmpty()); + } + } + + QVERIFY(place.location().coordinate().isValid()); + QVERIFY(!place.location().address().isEmpty()); + QVERIFY(!place.location().address().text().isEmpty()); + QVERIFY(!place.location().address().isTextGenerated()); + + QVERIFY(place.ratings().average() >= 1 && place.ratings().average() <= 5); + QVERIFY(place.ratings().maximum() == 5); + QVERIFY(place.ratings().count() > 0); + + QVERIFY(place.categories().count() > 0); + foreach (const QPlaceCategory &category, place.categories()) { + QVERIFY(!category.name().isEmpty()); + QVERIFY(!category.categoryId().isEmpty()); + QVERIFY(!category.icon().url().isEmpty()); + } + + QVERIFY(!place.extendedAttributeTypes().isEmpty()); + QVERIFY(place.visibility() == QLocation::PublicVisibility); + QVERIFY(place.detailsFetched()); + + //attributions are optional and thus have not been explicitly tested. + + //fetch the details of a non-existent place + QVERIFY(doFetchDetails(QStringLiteral("does_not_exist"), &place, + QPlaceReply::PlaceDoesNotExistError)); +} + +void tst_QPlaceManagerNokia::categories() +{ + QVERIFY(doInitializeCategories()); + + QList categories = placeManager->childCategories(); + QVERIFY(categories.count() > 0); + foreach (const QPlaceCategory &category, categories) { + //check that we have valid fields + QVERIFY(!category.categoryId().isEmpty()); + QVERIFY(!category.name().isEmpty()); + QVERIFY(!category.icon().url().isEmpty()); + + //check we can retrieve the very same category by id + QCOMPARE(placeManager->category(category.categoryId()), category); + + //the here plugin supports a two-level level category tree + QVERIFY(placeManager->parentCategoryId(category.categoryId()).isEmpty()); + const QList childCats = + placeManager->childCategories(category.categoryId()); + if (!childCats.isEmpty()) { + foreach (const QPlaceCategory &child, childCats) { + // only two levels of categories hence 2.nd level has no further children + QVERIFY(placeManager->childCategories(child.categoryId()).isEmpty()); + QVERIFY(placeManager->parentCategoryId(child.categoryId()) == category.categoryId()); + } + } + } +} + +void tst_QPlaceManagerNokia::suggestions() +{ + QFETCH(QGeoShape, area); + QFETCH(QString, searchTerm); + QFETCH(QPlaceReply::Error, error); + QFETCH(ExpectedResults, expectedResults); + + QPlaceSearchRequest searchRequest; + searchRequest.setSearchArea(area); + searchRequest.setSearchTerm(searchTerm); + + QStringList results; + QVERIFY(doSearchSuggestions(searchRequest, &results, error)); + + if (expectedResults == NoResults) + QVERIFY(results.count() == 0); + else if (expectedResults == SomeResults) + QVERIFY(results.count() > 0); +} + + +void tst_QPlaceManagerNokia::suggestions_data() +{ + QTest::addColumn("area"); + QTest::addColumn("searchTerm"); + QTest::addColumn ("error"); + QTest::addColumn("expectedResults"); + + for (int i = 0; i < 3; i++) { + QByteArray suffix; + QGeoShape area; + if (i == 0) { + area = QGeoCircle(QGeoCoordinate(-27.5, 153)); + suffix = " (Circle - center only)"; + } else if (i == 1) { + area = QGeoCircle(QGeoCoordinate(-27.5, 153), 5000); + suffix = " (Circle - with radius specified)"; + } else { + area = QGeoRectangle(QGeoCoordinate(-26.5, 152), QGeoCoordinate(-28.5, 154)); + suffix = " (Rectangle)"; + } + + QByteArray dataTag = QByteArray("valid usage") + suffix; + QTest::newRow(dataTag) << area + << "sus" + << QPlaceReply::NoError + << SomeResults; + } + + //invalid areas and boundary testing + QList dataTags; + QList areas; + QList errors; + QList results; + commonAreas(&dataTags, &areas, &errors, &results); + + for (int i = 0; i < dataTags.count(); ++i) { + QTest::newRow(dataTags.at(i)) << areas.at(i) + << "sus" + << errors.at(i) + << results.at(i); + } + + QTest::newRow("no text") << static_cast(QGeoCircle(QGeoCoordinate(-27.5, 153))) + << QString() + << QPlaceReply::NoError + << NoResults; +} + +void tst_QPlaceManagerNokia::suggestionsMisc() +{ + //check providing a distance relevancy hint (should be ignored) + QPlaceSearchRequest searchRequest; + QStringList results; + searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153))); + searchRequest.setSearchTerm(QStringLiteral("sus")); + searchRequest.setRelevanceHint(QPlaceSearchRequest::DistanceHint); + QVERIFY(doSearchSuggestions(searchRequest, &results, QPlaceReply::NoError)); + QVERIFY(results.count() > 0); + searchRequest.clear(); + + //check porviding a lexical place name relevancy hint (should be ignored) + searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153))); + searchRequest.setSearchTerm(QStringLiteral("sus")); + searchRequest.setRelevanceHint(QPlaceSearchRequest::LexicalPlaceNameHint); + QVERIFY(doSearchSuggestions(searchRequest, &results, QPlaceReply::NoError)); + QVERIFY(results.count() > 0); + searchRequest.clear(); + + //check providing a category + QPlaceCategory eatDrinkCat; + eatDrinkCat.setCategoryId(QStringLiteral("eat-drink")); + searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153))); + searchRequest.setSearchTerm(QStringLiteral("sus")); + searchRequest.setCategory(eatDrinkCat); + QVERIFY(doSearchSuggestions(searchRequest, &results, QPlaceReply::BadArgumentError)); + QCOMPARE(results.count(), 0); + searchRequest.clear(); + + //check providing a recommendation id + searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153))); + searchRequest.setSearchTerm(QStringLiteral("sus")); + searchRequest.setRecommendationId("id"); + QVERIFY(doSearchSuggestions(searchRequest, &results, QPlaceReply::BadArgumentError)); +} + +void tst_QPlaceManagerNokia::locale() +{ + //check that the defualt locale is set + QCOMPARE(placeManager->locales().count(), 1); + QCOMPARE(placeManager->locales().at(0), QLocale()); + + //check that we can set different locales for the categories + placeManager->setLocale(QLocale("en")); + QVERIFY(doInitializeCategories()); + QList enCategories = placeManager->childCategories(); + QVERIFY(enCategories.count() > 0); + + placeManager->setLocale(QLocale("fi")); + QVERIFY(doInitializeCategories()); + QList fiCategories = placeManager->childCategories(); + + foreach (const QPlaceCategory enCat, enCategories) { + foreach (const QPlaceCategory fiCat, fiCategories) { + if (enCat.categoryId() == fiCat.categoryId()) { + QVERIFY(fiCat.name() != enCat.name()); + QVERIFY(fiCat == placeManager->category(fiCat.categoryId())); + } + } + } + + // we are skipping the check below because we are requesting + // details for a place without a search before. This implies + // URL templating must be possible which the HERE place + // server refuses. + + QSKIP("remainder of test skipped due to QTBUG-44837"); + + //check that setting a locale will affect place detail fetches. + QPlace place; + placeManager->setLocale(QLocale("en")); + QVERIFY(doFetchDetails(ValidKnownPlaceId, + &place)); + QString englishName = place.name(); + placeManager->setLocale(QLocale("fr")); + QVERIFY(doFetchDetails(ValidKnownPlaceId, + &place)); + QVERIFY(englishName != place.name()); +} + +void tst_QPlaceManagerNokia::content() +{ + QFETCH(QPlaceContent::Type, type); + + //check fetching of content + QPlaceContentRequest request; + request.setContentType(type); + request.setPlaceId(ValidKnownPlaceId); + QPlaceContent::Collection results; + QVERIFY(doFetchContent(request, &results)); + + QVERIFY(results.count() > 0); + + QMapIterator iter(results); + while (iter.hasNext()) { + iter.next(); + switch (type) { + case (QPlaceContent::ImageType): { + QPlaceImage image = iter.value(); + QVERIFY(!image.url().isEmpty()); + break; + } case (QPlaceContent::ReviewType) : { + QPlaceReview review = iter.value(); + QVERIFY(!review.dateTime().isValid()); + QVERIFY(!review.text().isEmpty()); + QVERIFY(review.rating() >= 1 && review.rating() <= 5); + + //title and language fields are optional and thus have not been + //explicitly tested + break; + } case (QPlaceContent::EditorialType): { + QPlaceEditorial editorial = iter.value(); + QVERIFY(!editorial.text().isEmpty()); + + //The language field is optional and thus has not been + //explicitly tested. + break; + } default: + QFAIL("Unknown content type"); + } + } + + //check total count + QPlaceContentReply *contentReply = placeManager->getPlaceContent(request); + QSignalSpy contentSpy(contentReply, SIGNAL(finished())); + QTRY_VERIFY_WITH_TIMEOUT(contentSpy.count() ==1, Timeout); + QVERIFY(contentReply->totalCount() > 0); + + if (contentReply->totalCount() >= 2) { + //try testing with a limit + request.setLimit(1); + QPlaceContent::Collection newResults; + QVERIFY(doFetchContent(request, &newResults)); + QCOMPARE(newResults.count(), 1); + QCOMPARE(newResults.values().first(), results.value(0)); + } +} + +void tst_QPlaceManagerNokia::content_data() +{ + QTest::addColumn("type"); + + QTest::newRow("images") << QPlaceContent::ImageType; + QTest::newRow("reviews") << QPlaceContent::ReviewType; + QTest::newRow("editorials") << QPlaceContent::EditorialType; +} + +void tst_QPlaceManagerNokia::unsupportedFunctions() +{ + QPlace place; + place.setName(QStringLiteral("Brisbane")); + + QVERIFY(doSavePlace(place, QPlaceReply::UnsupportedError)); + QVERIFY(doRemovePlace(place, QPlaceReply::UnsupportedError)); + + QPlaceCategory category; + category.setName(QStringLiteral("Accommodation")); + QVERIFY(doSaveCategory(category, QPlaceReply::UnsupportedError)); + QVERIFY(doRemoveCategory(category, QPlaceReply::UnsupportedError)); +} + +void tst_QPlaceManagerNokia::commonAreas(QList *dataTags, + QList *areas, + QList *errors, + QList *results) +{ + Q_ASSERT(dataTags); + Q_ASSERT(areas); + dataTags->append("Unknown shape for search area"); + areas->append(QGeoShape()); + errors->append(QPlaceReply::BadArgumentError); + results->append(NoResults); + + dataTags->append("NaN coordinate"); + areas->append(QGeoCircle(QGeoCoordinate())); + errors->append(QPlaceReply::BadArgumentError); + results->append(NoResults); + + dataTags->append("Valid latitude (upper boundary)"); + areas->append(QGeoCircle(QGeoCoordinate(90.0, 45))); + errors->append(QPlaceReply::NoError); + results->append(AnyResults); + + dataTags->append("Invalid latitude (upper boundary)"); + areas->append(QGeoCircle(QGeoCoordinate(90.1, 45))); + errors->append(QPlaceReply::BadArgumentError); + results->append(NoResults); + + dataTags->append("Valid latitude (lower boundary)"); + areas->append(QGeoCircle(QGeoCoordinate(-90.0, 45))); + errors->append(QPlaceReply::NoError); + results->append(AnyResults); + + dataTags->append("Invalid latitude (lower boundary)"); + areas->append(QGeoCircle(QGeoCoordinate(-90.1, 45))); + errors->append(QPlaceReply::BadArgumentError); + results->append(NoResults); + + dataTags->append("Valid longitude (lower boundary)"); + areas->append(QGeoCircle(QGeoCoordinate(-45, -180.0))); + errors->append(QPlaceReply::NoError); + results->append(AnyResults); + + dataTags->append("Invalid longitude (lower boundary)"); + areas->append(QGeoCircle(QGeoCoordinate(-45, -180.1))); + errors->append(QPlaceReply::BadArgumentError); + results->append(NoResults); + + dataTags->append("Valid longitude (upper boundary)"); + areas->append(QGeoCircle(QGeoCoordinate(-45, 180.0))); + errors->append(QPlaceReply::NoError); + results->append(AnyResults); + + dataTags->append("Invalid longitude (upper boundary)"); + areas->append(QGeoCircle(QGeoCoordinate(-45, 180.1))); + errors->append(QPlaceReply::BadArgumentError); + results->append(NoResults); + + dataTags->append("Invalid rectangular area"); + areas->append(QGeoRectangle(QGeoCoordinate(20,20), + QGeoCoordinate(30,10))); + errors->append(QPlaceReply::BadArgumentError); + results->append(NoResults); +} + +QTEST_GUILESS_MAIN(tst_QPlaceManagerNokia) + +#include "tst_places.moc" diff --git a/tests/auto/nokia_services/routing/error-no-route.xml b/tests/auto/nokia_services/routing/error-no-route.xml new file mode 100644 index 0000000..1e1560a --- /dev/null +++ b/tests/auto/nokia_services/routing/error-no-route.xml @@ -0,0 +1 @@ +
NOROUTE: Request failed
\ No newline at end of file diff --git a/tests/auto/nokia_services/routing/invalid-response-half-way-through.xml b/tests/auto/nokia_services/routing/invalid-response-half-way-through.xml new file mode 100644 index 0000000..545954a --- /dev/null +++ b/tests/auto/nokia_services/routing/invalid-response-half-way-through.xml @@ -0,0 +1,150 @@ + + + + + 2012-04-26T14:49:24.451Z + 2012-04-26T14:47:00.025+0000 + 5094886 + 2012-04-26T14:47:02.481+0000 + 12015 + 2012-04-26T14:47:02.481+0000 + 857 + 2011Q3 + routeserver,9.2-2012.02.20-hotfix6.2.13.1 + 22 + routing-route-service,6.2.13.1 + + + REMvaQUAAAB4tdyZCURKQJROJJhqxipAAAAAYAlESkAAAADAasYqQAAAAAAAAPB_AAAAAAAA8H9pqM_8V_SHZp4MKQHNgLOULCerAAEAAICiDCkBAQAAADAnqwABAAAAAADA_wEAAAAAAMD_HY0-82dwsAoDCQ + + -53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + + fastestNow + car + enabled + + 52.5315361,13.3875332 52.5315094,13.3872204 52.5314484,13.3868303 52.5308685,13.3871498 52.5304298,13.3873901 52.5303993,13.3872299 52.5303612,13.3871202 52.5293198,13.3846502 52.5289383,13.3851404 52.5288315,13.3852901 52.5287399,13.3853998 52.5285416,13.3856297 52.5283089,13.38591 52.5281982,13.3860397 52.5280991,13.3861103 52.5274811,13.3867598 52.5271416,13.3869896 52.5270386,13.3870201 52.5262985,13.3871603 52.5262985,13.38727 52.5262489,13.3874302 52.5261917,13.3877001 52.5260506,13.3882999 52.5259895,13.38873 52.5257187,13.3898802 52.5249786,13.3928604 52.5246773,13.3941345 + + + 52.5315361 + 13.3846502 + + + 52.5246773 + 13.3941345 + + + + + -53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + 1271.0 + 273.9 + + + 52.5315361 + 13.3875332 + + Head toward Eichendorffstraße on Invalidenstraße. Go for 150 feet. + 5.2 + 48.0 + -53499799 + forward + + + + 52.5314484 + 13.3868303 + + Turn left onto Eichendorffstraße. Go for 400 feet. + 47.1 + 119.0 + -780236888 + left + + + + 52.5304298 + 13.3873901 + + Turn right onto Schlegelstraße. Go for 0.1 miles. + 55.9 + 223.0 + -53499914 + right + + + + 52.5293198 + 13.3846502 + + Turn left onto Chausseestraße. Go for 0.2 miles. + 68.0 + 286.0 + -749446557 + left + + + + 52.5271416 + 13.3869896 + + Continue on Friedrichstraße, Oranienburger Tor. Go for 300 feet. + 20.1 + 93.0 + -572708773 + forward + + + + 52.5262985 + 13.3871603 + + Turn left onto Oranienburger Straße. Go for 0.3 miles. + 77.6 + 502.0 + +812293299 + left diff --git a/tests/auto/nokia_services/routing/invalid-response-no-route-tag.xml b/tests/auto/nokia_services/routing/invalid-response-no-route-tag.xml new file mode 100644 index 0000000..322f1a1 --- /dev/null +++ b/tests/auto/nokia_services/routing/invalid-response-no-route-tag.xml @@ -0,0 +1,18 @@ + + + + + 2012-04-26T14:49:24.451Z + 2012-04-26T14:47:00.025+0000 + 5094886 + 2012-04-26T14:47:02.481+0000 + 12015 + 2012-04-26T14:47:02.481+0000 + 857 + 2011Q3 + routeserver,9.2-2012.02.20-hotfix6.2.13.1 + 22 + routing-route-service,6.2.13.1 + + + \ No newline at end of file diff --git a/tests/auto/nokia_services/routing/invalid-response-trash.xml b/tests/auto/nokia_services/routing/invalid-response-trash.xml new file mode 100644 index 0000000..ec6a3ae Binary files /dev/null and b/tests/auto/nokia_services/routing/invalid-response-trash.xml differ diff --git a/tests/auto/nokia_services/routing/littered-with-new-tags.xml b/tests/auto/nokia_services/routing/littered-with-new-tags.xml new file mode 100644 index 0000000..40e8388 --- /dev/null +++ b/tests/auto/nokia_services/routing/littered-with-new-tags.xml @@ -0,0 +1,648 @@ + + + + + + + + 2012-04-26T14:49:24.451Z + + 2012-04-26T14:47:00.025+0000 + 5094886 + 2012-04-26T14:47:02.481+0000 + 12015 + 2012-04-26T14:47:02.481+0000 + 857 + 2011Q3 + routeserver,9.2-2012.02.20-hotfix6.2.13.1 + 22 + routing-route-service,6.2.13.1 + + + + + + + + + REMvaQUAAAB4tdyZCURKQJROJJhqxipAAAAAYAlESkAAAADAasYqQAAAAAAAAPB_AAAAAAAA8H9pqM_8V_SHZp4MKQHNgLOULCerAAEAAICiDCkBAQAAADAnqwABAAAAAADA_wEAAAAAAMD_HY0-82dwsAoDCQ + + + -53499799 + + 52.5315361 + 13.3875332 + 32 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + + fastestNow + car + enabled + + 52.5315361,13.3875332 52.5315094,13.3872204 52.5314484,13.3868303 52.5308685,13.3871498 52.5304298,13.3873901 52.5303993,13.3872299 52.5303612,13.3871202 52.5293198,13.3846502 52.5289383,13.3851404 52.5288315,13.3852901 52.5287399,13.3853998 52.5285416,13.3856297 52.5283089,13.38591 52.5281982,13.3860397 52.5280991,13.3861103 52.5274811,13.3867598 52.5271416,13.3869896 52.5270386,13.3870201 52.5262985,13.3871603 52.5262985,13.38727 52.5262489,13.3874302 52.5261917,13.3877001 52.5260506,13.3882999 52.5259895,13.38873 52.5257187,13.3898802 52.5249786,13.3928604 52.5246773,13.3941345 + + + 52.5315361 + 13.3846502 + + + 52.5246773 + 13.3941345 + + + + + + + + + + -53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + 1271.0 + 273.9 + + 232 + + 52.5315361 + 13.3875332 + + Head toward Eichendorffstraße on Invalidenstraße. Go for 150 feet. + 5.2 + 48.0 + -53499799 + forward + + + + 52.5314484 + 13.3868303 + + Turn left onto Eichendorffstraße. Go for 400 feet. + 47.1 + 119.0 + -780236888 + left + + + + 52.5304298 + 13.3873901 + + Turn right onto Schlegelstraße. Go for 0.1 miles. + 55.9 + 223.0 + -53499914 + right + + + + 52.5293198 + 13.3846502 + + Turn left onto Chausseestraße. Go for 0.2 miles. + 68.0 + 286.0 + -749446557 + left + + + + 52.5271416 + 13.3869896 + + Continue on Friedrichstraße, Oranienburger Tor. Go for 300 feet. + 20.1 + 93.0 + -572708773 + forward + + + + 52.5262985 + 13.3871603 + + Turn left onto Oranienburger Straße. Go for 0.3 miles. + 77.6 + 502.0 + +812293299 + left + + + + 52.5246773 + 13.3941345 + + Your destination on Oranienburger Straße is on the right. The trip takes 0.8 miles and 5 mins. + 0.0 + 0.0 + forward + + + -53499799 + 52.5315361,13.3875332 52.5315094,13.3872204 52.5314484,13.3868303 + 48.0 + 13.89 + + 9.17 + 5.2 + 9.72 + 4.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Invalidenstraße +
+ + + -780236888 + 52.5314484,13.3868303 52.5308685,13.3871498 + 68.0 + + 5.0 + 13.6 + 6.94 + 9.8 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Eichendorffstraße +
+ + + -780236887 + 52.5308685,13.3871498 52.5304298,13.3873901 + 51.0 + + 5.28 + 9.7 + 6.94 + 7.3 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Eichendorffstraße +
+ + + -53499914 + 52.5304298,13.3873901 52.5303993,13.3872299 52.5303612,13.3871202 52.5293198,13.3846502 + 223.0 + + 5.28 + 42.3 + 6.94 + 32.1 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Schlegelstraße +
+ + + -749446557 + 52.5293198,13.3846502 52.5289383,13.3851404 + 53.0 + 13.89 + + 10.83 + 4.9 + 9.72 + 5.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763170 + 52.5289383,13.3851404 52.5288315,13.3852901 + 15.0 + 13.89 + + 10.83 + 1.4 + 9.72 + 1.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763169 + 52.5288315,13.3852901 52.5287399,13.3853998 + 12.0 + 13.89 + + 10.83 + 1.1 + 9.72 + 1.2 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763164 + 52.5287399,13.3853998 52.5285416,13.3856297 + 26.0 + 13.89 + + 10.83 + 2.4 + 9.72 + 2.7 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763163 + 52.5285416,13.3856297 52.5283089,13.38591 + 32.0 + 13.89 + + 10.83 + 3.0 + 9.72 + 3.3 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -749446551 + 52.5283089,13.38591 52.5281982,13.3860397 + 15.0 + 13.89 + + 10.83 + 1.4 + 9.72 + 1.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -572708771 + 52.5281982,13.3860397 52.5280991,13.3861103 52.5274811,13.3867598 + 93.0 + 13.89 + + 10.83 + 8.6 + 9.72 + 9.6 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -53500039 + 52.5274811,13.3867598 52.5271416,13.3869896 + 40.0 + 13.89 + + 10.83 + 3.7 + 9.72 + 4.1 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -572708773 + 52.5271416,13.3869896 52.5270386,13.3870201 + 11.0 + 13.89 + + 10.28 + 1.1 + 9.72 + 1.1 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Friedrichstraße, Oranienburger Tor +
+ + + -572708772 + 52.5270386,13.3870201 52.5262985,13.3871603 + 82.0 + 13.89 + + 10.28 + 8.0 + 9.72 + 8.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Friedrichstraße +
+ + + +812293299 + 52.5262985,13.3871603 52.5262985,13.38727 + 7.0 + 13.89 + + 3.61 + 1.9 + 9.72 + 0.7 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -733054082 + 52.5262985,13.38727 52.5262489,13.3874302 + 12.0 + 13.89 + + 11.39 + 1.1 + 9.72 + 1.2 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -733054081 + 52.5262489,13.3874302 52.5261917,13.3877001 + 19.0 + 13.89 + + 11.39 + 1.7 + 9.72 + 2.0 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -572680644 + 52.5261917,13.3877001 52.5260506,13.3882999 + 43.0 + 13.89 + + 10.0 + 4.3 + 9.72 + 4.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -572680642 + 52.5260506,13.3882999 52.5259895,13.38873 + 29.0 + 13.89 + + 11.39 + 2.5 + 9.72 + 3.0 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -572680640 + 52.5259895,13.38873 52.5257187,13.3898802 + 83.0 + 13.89 + + 11.11 + 7.5 + 9.72 + 8.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -53501098 + 52.5257187,13.3898802 52.5249786,13.3928604 + 217.0 + 13.89 + + 8.33 + 26.0 + 9.72 + 22.3 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -53501113 + 52.5249786,13.3928604 52.5246773,13.3941345 + 92.0 + 13.89 + + 8.61 + 10.7 + 9.72 + 9.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ +
+ + 1271.0 + 1271.0 + 243.0 + + +
+
+
\ No newline at end of file diff --git a/tests/auto/nokia_services/routing/multiple-routes-in-response.xml b/tests/auto/nokia_services/routing/multiple-routes-in-response.xml new file mode 100644 index 0000000..12a4d21 --- /dev/null +++ b/tests/auto/nokia_services/routing/multiple-routes-in-response.xml @@ -0,0 +1 @@ +2012-04-26T15:01:07.170Z2012-04-26T14:59:00.073+000050949822012-04-26T14:59:02.647+0000122232012-04-26T14:59:02.647+00007032011Q3routeserver,9.2-2012.02.20-hotfix6.2.13.120routing-route-service,6.2.13.1REMvFQUAAAB4tdyZCURKQJROJJhqxipAAAAAYAlESkAAAADAasYqQAAAAAAAAPB_AAAAAAAA8H-XVzADV_SHZp4MKQHNgLOULCerAAEAAICiDCkBAQAAADAnqwABAAAAAADA_wEAAAAAAMD_HY0-83dwYQCu+5349979952.531536113.387533252.53154313.387532stopOver-5350111352.524677313.394134552.52464613.394128stopOversceniccar52.5315361,13.3875332 52.5315819,13.3880997 52.5316582,13.3889303 52.5317612,13.3896999 52.5316315,13.3899002 52.5302505,13.3916502 52.5300598,13.3919001 52.5286217,13.3937197 52.5285416,13.3938799 52.5282288,13.3924398 52.5276604,13.3927898 52.5274887,13.39293 52.5264091,13.3935404 52.5262985,13.3935604 52.5254402,13.3931103 52.5249786,13.3928604 52.5246773,13.394134552.531761213.387533252.524677313.3941345+5349979952.531536113.387533252.53154313.387532stopOver-5350111352.524677313.394134552.52464613.394128stopOver1177.0237.752.531536113.3875332Head toward Borsigstraße on Invalidenstraße. Go for 500 feet.15.2148.0+53499799forward52.531761213.3896999Turn right onto Gartenstraße. Go for 0.3 miles.90.8454.0-811854188right52.528541613.3938799Turn right onto Torstraße. Go for 350 feet.28.4103.0-53499981right52.528228813.3924398Turn left onto Tucholskystraße. Go for 0.2 miles.72.4380.0-53500024left52.524978613.3928604Turn left onto Oranienburger Straße. Go for 300 feet.30.992.0-53501113left52.524677313.3941345Your destination on Oranienburger Straße is on the right. The trip takes 0.7 miles and 4 mins.0.00.0forward+5349979952.5315361,13.3875332 52.5315819,13.388099738.013.897.774.99.723.9
DEBerlinBerlinBerlinMitteInvalidenstraße
+5349978852.5315819,13.3880997 52.5316582,13.3889303 52.5317612,13.3896999110.013.897.7714.19.7211.3
DEBerlinBerlinBerlinMitteInvalidenstraße
-81185418852.5317612,13.3896999 52.5316315,13.389900219.05.03.86.942.7
DEBerlinBerlinBerlinMitteGartenstraße
-81185418752.5316315,13.3899002 52.5302505,13.3916502193.05.2836.66.9427.8
DEBerlinBerlinBerlinMitteGartenstraße
-5349987852.5302505,13.3916502 52.5300598,13.391900127.05.285.16.943.9
DEBerlinBerlinBerlinMitteGartenstraße
-5349996052.5300598,13.3919001 52.5286217,13.3937197 52.5285416,13.3938799215.05.2840.76.9431.0
DEBerlinBerlinBerlinMitteGartenstraße
-5349998152.5285416,13.3938799 52.5282288,13.3924398103.013.898.3312.46.9414.8
DEBerlinBerlinBerlinMitteTorstraße
-5350002452.5282288,13.3924398 52.5276604,13.3927898 52.5274887,13.3929388.04.7218.69.729.1
DEBerlinBerlinBerlinMitteTucholskystraße
-5350009152.5274887,13.39293 52.5264091,13.3935404126.04.7226.79.7213.0
DEBerlinBerlinBerlinMitteTucholskystraße
-84490623952.5264091,13.3935404 52.5262985,13.3935604 52.5254402,13.3931103112.04.1726.99.7211.5
DEBerlinBerlinBerlinMitteTucholskystraße
-84490623852.5254402,13.3931103 52.5249786,13.392860454.03.8913.99.725.6
DEBerlinBerlinBerlinMitteTucholskystraße
-5350111352.5249786,13.3928604 52.5246773,13.394134592.013.898.6110.79.729.5
DEBerlinBerlinBerlinMitteOranienburger Straße
1177.0309.0237.0
REMvaQUAAAB4tdyZCURKQJROJJhqxipAAAAAYAlESkAAAADAasYqQAAAAAAAAPB_AAAAAAAA8H9pqM_8V_SHZp4MKQHNgLOULCerAAEAAICiDCkBAQAAADAnqwABAAAAAADA_wEAAAAAAMD_HY0-82dwsAoDCQ-5349979952.531536113.387533252.53154313.387532stopOver-5350111352.524677313.394134552.52464613.394128stopOverfastestNowcarenabled52.5315361,13.3875332 52.5315094,13.3872204 52.5314484,13.3868303 52.5308685,13.3871498 52.5304298,13.3873901 52.5303993,13.3872299 52.5303612,13.3871202 52.5293198,13.3846502 52.5289383,13.3851404 52.5288315,13.3852901 52.5287399,13.3853998 52.5285416,13.3856297 52.5283089,13.38591 52.5281982,13.3860397 52.5280991,13.3861103 52.5274811,13.3867598 52.5271416,13.3869896 52.5270386,13.3870201 52.5262985,13.3871603 52.5262985,13.38727 52.5262489,13.3874302 52.5261917,13.3877001 52.5260506,13.3882999 52.5259895,13.38873 52.5257187,13.3898802 52.5249786,13.3928604 52.5246773,13.394134552.531536113.384650252.524677313.3941345-5349979952.531536113.387533252.53154313.387532stopOver-5350111352.524677313.394134552.52464613.394128stopOver1271.0270.052.531536113.3875332Head toward Eichendorffstraße on Invalidenstraße. Go for 150 feet.5.248.0-53499799forward52.531448413.3868303Turn left onto Eichendorffstraße. Go for 400 feet.47.1119.0-780236888left52.530429813.3873901Turn right onto Schlegelstraße. Go for 0.1 miles.55.9223.0-53499914right52.529319813.3846502Turn left onto Chausseestraße. Go for 0.2 miles.64.9286.0-749446557left52.527141613.3869896Continue on Friedrichstraße, Oranienburger Tor. Go for 300 feet.19.393.0-572708773forward52.526298513.3871603Turn left onto Oranienburger Straße. Go for 0.3 miles.77.6502.0+812293299left52.524677313.3941345Your destination on Oranienburger Straße is on the right. The trip takes 0.8 miles and 5 mins.0.00.0forward-5349979952.5315361,13.3875332 52.5315094,13.3872204 52.5314484,13.386830348.013.899.175.29.724.9
DEBerlinBerlinBerlinMitteInvalidenstraße
-78023688852.5314484,13.3868303 52.5308685,13.387149868.05.013.66.949.8
DEBerlinBerlinBerlinMitteEichendorffstraße
-78023688752.5308685,13.3871498 52.5304298,13.387390151.05.289.76.947.3
DEBerlinBerlinBerlinMitteEichendorffstraße
-5349991452.5304298,13.3873901 52.5303993,13.3872299 52.5303612,13.3871202 52.5293198,13.3846502223.05.2842.36.9432.1
DEBerlinBerlinBerlinMitteSchlegelstraße
-74944655752.5293198,13.3846502 52.5289383,13.385140453.013.8910.834.99.725.5
DEBerlinBerlinBerlinMitteChausseestraße
-78176317052.5289383,13.3851404 52.5288315,13.385290115.013.8910.831.49.721.5
DEBerlinBerlinBerlinMitteChausseestraße
-78176316952.5288315,13.3852901 52.5287399,13.385399812.013.8910.831.19.721.2
DEBerlinBerlinBerlinMitteChausseestraße
-78176316452.5287399,13.3853998 52.5285416,13.385629726.013.8910.832.49.722.7
DEBerlinBerlinBerlinMitteChausseestraße
-78176316352.5285416,13.3856297 52.5283089,13.3859132.013.8910.833.09.723.3
DEBerlinBerlinBerlinMitteChausseestraße
-74944655152.5283089,13.38591 52.5281982,13.386039715.013.8910.831.49.721.5
DEBerlinBerlinBerlinMitteChausseestraße
-57270877152.5281982,13.3860397 52.5280991,13.3861103 52.5274811,13.386759893.013.8910.838.69.729.6
DEBerlinBerlinBerlinMitteChausseestraße
-5350003952.5274811,13.3867598 52.5271416,13.386989640.013.8910.833.79.724.1
DEBerlinBerlinBerlinMitteChausseestraße
-57270877352.5271416,13.3869896 52.5270386,13.387020111.013.8910.281.19.721.1
DEBerlinBerlinBerlinMitteFriedrichstraße, Oranienburger Tor
-57270877252.5270386,13.3870201 52.5262985,13.387160382.013.8910.288.09.728.4
DEBerlinBerlinBerlinMitteFriedrichstraße
+81229329952.5262985,13.3871603 52.5262985,13.387277.013.893.611.99.720.7
DEBerlinBerlinBerlinMitteOranienburger Straße
-73305408252.5262985,13.38727 52.5262489,13.387430212.013.8911.391.19.721.2
DEBerlinBerlinBerlinMitteOranienburger Straße
-73305408152.5262489,13.3874302 52.5261917,13.387700119.013.8911.391.79.722.0
DEBerlinBerlinBerlinMitteOranienburger Straße
-57268064452.5261917,13.3877001 52.5260506,13.388299943.013.8910.04.39.724.4
DEBerlinBerlinBerlinMitteOranienburger Straße
-57268064252.5260506,13.3882999 52.5259895,13.3887329.013.8911.392.59.723.0
DEBerlinBerlinBerlinMitteOranienburger Straße
-57268064052.5259895,13.38873 52.5257187,13.389880283.013.8911.117.59.728.5
DEBerlinBerlinBerlinMitteOranienburger Straße
-5350109852.5257187,13.3898802 52.5249786,13.3928604217.013.898.3326.09.7222.3
DEBerlinBerlinBerlinMitteOranienburger Straße
-5350111352.5249786,13.3928604 52.5246773,13.394134592.013.898.6110.79.729.5
DEBerlinBerlinBerlinMitteOranienburger Straße
1271.0243.0
\ No newline at end of file diff --git a/tests/auto/nokia_services/routing/optim-fastest.xml b/tests/auto/nokia_services/routing/optim-fastest.xml new file mode 100644 index 0000000..43a7a77 --- /dev/null +++ b/tests/auto/nokia_services/routing/optim-fastest.xml @@ -0,0 +1,628 @@ + + + + + 2012-04-26T14:49:24.451Z + 2012-04-26T14:47:00.025+0000 + 5094886 + 2012-04-26T14:47:02.481+0000 + 12015 + 2012-04-26T14:47:02.481+0000 + 857 + 2011Q3 + routeserver,9.2-2012.02.20-hotfix6.2.13.1 + 22 + routing-route-service,6.2.13.1 + + + REMvaQUAAAB4tdyZCURKQJROJJhqxipAAAAAYAlESkAAAADAasYqQAAAAAAAAPB_AAAAAAAA8H9pqM_8V_SHZp4MKQHNgLOULCerAAEAAICiDCkBAQAAADAnqwABAAAAAADA_wEAAAAAAMD_HY0-82dwsAoDCQ + + -53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + + fastestNow + car + enabled + + 52.5315361,13.3875332 52.5315094,13.3872204 52.5314484,13.3868303 52.5308685,13.3871498 52.5304298,13.3873901 52.5303993,13.3872299 52.5303612,13.3871202 52.5293198,13.3846502 52.5289383,13.3851404 52.5288315,13.3852901 52.5287399,13.3853998 52.5285416,13.3856297 52.5283089,13.38591 52.5281982,13.3860397 52.5280991,13.3861103 52.5274811,13.3867598 52.5271416,13.3869896 52.5270386,13.3870201 52.5262985,13.3871603 52.5262985,13.38727 52.5262489,13.3874302 52.5261917,13.3877001 52.5260506,13.3882999 52.5259895,13.38873 52.5257187,13.3898802 52.5249786,13.3928604 52.5246773,13.3941345 + + + 52.5315361 + 13.3846502 + + + 52.5246773 + 13.3941345 + + + + + -53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + 1271.0 + 273.9 + + + 52.5315361 + 13.3875332 + + Head toward Eichendorffstraße on Invalidenstraße. Go for 150 feet. + 5.2 + 48.0 + -53499799 + forward + + + + 52.5314484 + 13.3868303 + + Turn left onto Eichendorffstraße. Go for 400 feet. + 47.1 + 119.0 + -780236888 + left + + + + 52.5304298 + 13.3873901 + + Turn right onto Schlegelstraße. Go for 0.1 miles. + 55.9 + 223.0 + -53499914 + right + + + + 52.5293198 + 13.3846502 + + Turn left onto Chausseestraße. Go for 0.2 miles. + 68.0 + 286.0 + -749446557 + left + + + + 52.5271416 + 13.3869896 + + Continue on Friedrichstraße, Oranienburger Tor. Go for 300 feet. + 20.1 + 93.0 + -572708773 + forward + + + + 52.5262985 + 13.3871603 + + Turn left onto Oranienburger Straße. Go for 0.3 miles. + 77.6 + 502.0 + +812293299 + left + + + + 52.5246773 + 13.3941345 + + Your destination on Oranienburger Straße is on the right. The trip takes 0.8 miles and 5 mins. + 0.0 + 0.0 + forward + + + -53499799 + 52.5315361,13.3875332 52.5315094,13.3872204 52.5314484,13.3868303 + 48.0 + 13.89 + + 9.17 + 5.2 + 9.72 + 4.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Invalidenstraße +
+ + + -780236888 + 52.5314484,13.3868303 52.5308685,13.3871498 + 68.0 + + 5.0 + 13.6 + 6.94 + 9.8 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Eichendorffstraße +
+ + + -780236887 + 52.5308685,13.3871498 52.5304298,13.3873901 + 51.0 + + 5.28 + 9.7 + 6.94 + 7.3 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Eichendorffstraße +
+ + + -53499914 + 52.5304298,13.3873901 52.5303993,13.3872299 52.5303612,13.3871202 52.5293198,13.3846502 + 223.0 + + 5.28 + 42.3 + 6.94 + 32.1 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Schlegelstraße +
+ + + -749446557 + 52.5293198,13.3846502 52.5289383,13.3851404 + 53.0 + 13.89 + + 10.83 + 4.9 + 9.72 + 5.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763170 + 52.5289383,13.3851404 52.5288315,13.3852901 + 15.0 + 13.89 + + 10.83 + 1.4 + 9.72 + 1.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763169 + 52.5288315,13.3852901 52.5287399,13.3853998 + 12.0 + 13.89 + + 10.83 + 1.1 + 9.72 + 1.2 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763164 + 52.5287399,13.3853998 52.5285416,13.3856297 + 26.0 + 13.89 + + 10.83 + 2.4 + 9.72 + 2.7 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763163 + 52.5285416,13.3856297 52.5283089,13.38591 + 32.0 + 13.89 + + 10.83 + 3.0 + 9.72 + 3.3 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -749446551 + 52.5283089,13.38591 52.5281982,13.3860397 + 15.0 + 13.89 + + 10.83 + 1.4 + 9.72 + 1.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -572708771 + 52.5281982,13.3860397 52.5280991,13.3861103 52.5274811,13.3867598 + 93.0 + 13.89 + + 10.83 + 8.6 + 9.72 + 9.6 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -53500039 + 52.5274811,13.3867598 52.5271416,13.3869896 + 40.0 + 13.89 + + 10.83 + 3.7 + 9.72 + 4.1 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -572708773 + 52.5271416,13.3869896 52.5270386,13.3870201 + 11.0 + 13.89 + + 10.28 + 1.1 + 9.72 + 1.1 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Friedrichstraße, Oranienburger Tor +
+ + + -572708772 + 52.5270386,13.3870201 52.5262985,13.3871603 + 82.0 + 13.89 + + 10.28 + 8.0 + 9.72 + 8.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Friedrichstraße +
+ + + +812293299 + 52.5262985,13.3871603 52.5262985,13.38727 + 7.0 + 13.89 + + 3.61 + 1.9 + 9.72 + 0.7 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -733054082 + 52.5262985,13.38727 52.5262489,13.3874302 + 12.0 + 13.89 + + 11.39 + 1.1 + 9.72 + 1.2 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -733054081 + 52.5262489,13.3874302 52.5261917,13.3877001 + 19.0 + 13.89 + + 11.39 + 1.7 + 9.72 + 2.0 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -572680644 + 52.5261917,13.3877001 52.5260506,13.3882999 + 43.0 + 13.89 + + 10.0 + 4.3 + 9.72 + 4.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -572680642 + 52.5260506,13.3882999 52.5259895,13.38873 + 29.0 + 13.89 + + 11.39 + 2.5 + 9.72 + 3.0 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -572680640 + 52.5259895,13.38873 52.5257187,13.3898802 + 83.0 + 13.89 + + 11.11 + 7.5 + 9.72 + 8.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -53501098 + 52.5257187,13.3898802 52.5249786,13.3928604 + 217.0 + 13.89 + + 8.33 + 26.0 + 9.72 + 22.3 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -53501113 + 52.5249786,13.3928604 52.5246773,13.3941345 + 92.0 + 13.89 + + 8.61 + 10.7 + 9.72 + 9.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ +
+ + 1271.0 + 243.0 + +
+
+
\ No newline at end of file diff --git a/tests/auto/nokia_services/routing/optim-shortest.xml b/tests/auto/nokia_services/routing/optim-shortest.xml new file mode 100644 index 0000000..5aa8679 --- /dev/null +++ b/tests/auto/nokia_services/routing/optim-shortest.xml @@ -0,0 +1 @@ +2012-04-26T14:57:30.304Z2012-04-26T14:56:00.027+000050949832012-04-26T14:56:02.406+0000122232012-04-26T14:56:02.406+00005062011Q3routeserver,9.2-2012.02.20-hotfix6.2.13.141routing-route-service,6.2.13.1REMvFQUAAAB4tdyZCURKQJROJJhqxipAAAAAYAlESkAAAADAasYqQAAAAAAAAPB_AAAAAAAA8H-XVzADV_SHZp4MKQHNgLOULCerAAEAAICiDCkBAQAAADAnqwABAAAAAADA_wEAAAAAAMD_HY0-83dwYQCu+5349979952.531536113.387533252.53154313.387532stopOver-5350111352.524677313.394134552.52464613.394128stopOvershortestcar52.5315361,13.3875332 52.5315819,13.3880997 52.5316582,13.3889303 52.5317612,13.3896999 52.5316315,13.3899002 52.5302505,13.3916502 52.5300598,13.3919001 52.5286217,13.3937197 52.5285416,13.3938799 52.5282288,13.3924398 52.5276604,13.3927898 52.5274887,13.39293 52.5264091,13.3935404 52.5262985,13.3935604 52.5254402,13.3931103 52.5249786,13.3928604 52.5246773,13.394134552.531761213.387533252.524677313.3941345+5349979952.531536113.387533252.53154313.387532stopOver-5350111352.524677313.394134552.52464613.394128stopOver1177.0237.752.531536113.3875332Head toward Borsigstraße on Invalidenstraße. Go for 500 feet.15.2148.0+53499799forward52.531761213.3896999Turn right onto Gartenstraße. Go for 0.3 miles.90.8454.0-811854188right52.528541613.3938799Turn right onto Torstraße. Go for 350 feet.28.4103.0-53499981right52.528228813.3924398Turn left onto Tucholskystraße. Go for 0.2 miles.72.4380.0-53500024left52.524978613.3928604Turn left onto Oranienburger Straße. Go for 300 feet.30.992.0-53501113left52.524677313.3941345Your destination on Oranienburger Straße is on the right. The trip takes 0.7 miles and 4 mins.0.00.0forward+5349979952.5315361,13.3875332 52.5315819,13.388099738.013.897.774.99.723.9
DEBerlinBerlinBerlinMitteInvalidenstraße
+5349978852.5315819,13.3880997 52.5316582,13.3889303 52.5317612,13.3896999110.013.897.7714.19.7211.3
DEBerlinBerlinBerlinMitteInvalidenstraße
-81185418852.5317612,13.3896999 52.5316315,13.389900219.05.03.86.942.7
DEBerlinBerlinBerlinMitteGartenstraße
-81185418752.5316315,13.3899002 52.5302505,13.3916502193.05.2836.66.9427.8
DEBerlinBerlinBerlinMitteGartenstraße
-5349987852.5302505,13.3916502 52.5300598,13.391900127.05.285.16.943.9
DEBerlinBerlinBerlinMitteGartenstraße
-5349996052.5300598,13.3919001 52.5286217,13.3937197 52.5285416,13.3938799215.05.2840.76.9431.0
DEBerlinBerlinBerlinMitteGartenstraße
-5349998152.5285416,13.3938799 52.5282288,13.3924398103.013.898.3312.46.9414.8
DEBerlinBerlinBerlinMitteTorstraße
-5350002452.5282288,13.3924398 52.5276604,13.3927898 52.5274887,13.3929388.04.7218.69.729.1
DEBerlinBerlinBerlinMitteTucholskystraße
-5350009152.5274887,13.39293 52.5264091,13.3935404126.04.7226.79.7213.0
DEBerlinBerlinBerlinMitteTucholskystraße
-84490623952.5264091,13.3935404 52.5262985,13.3935604 52.5254402,13.3931103112.04.1726.99.7211.5
DEBerlinBerlinBerlinMitteTucholskystraße
-84490623852.5254402,13.3931103 52.5249786,13.392860454.03.8913.99.725.6
DEBerlinBerlinBerlinMitteTucholskystraße
-5350111352.5249786,13.3928604 52.5246773,13.394134592.013.898.6110.79.729.5
DEBerlinBerlinBerlinMitteOranienburger Straße
1177.0309.0237.0
\ No newline at end of file diff --git a/tests/auto/nokia_services/routing/routing.pro b/tests/auto/nokia_services/routing/routing.pro new file mode 100644 index 0000000..f0ec3d6 --- /dev/null +++ b/tests/auto/nokia_services/routing/routing.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_nokia_routing + +QT += network location testlib +INCLUDEPATH += $$PWD/../../../../src/plugins/geoservices/nokia + +HEADERS += $$PWD/../../../../src/plugins/geoservices/nokia/qgeonetworkaccessmanager.h +SOURCES += tst_routing.cpp + +OTHER_FILES += *.xml + +TESTDATA = $$OTHER_FILES diff --git a/tests/auto/nokia_services/routing/travelmode-car.xml b/tests/auto/nokia_services/routing/travelmode-car.xml new file mode 100644 index 0000000..43a7a77 --- /dev/null +++ b/tests/auto/nokia_services/routing/travelmode-car.xml @@ -0,0 +1,628 @@ + + + + + 2012-04-26T14:49:24.451Z + 2012-04-26T14:47:00.025+0000 + 5094886 + 2012-04-26T14:47:02.481+0000 + 12015 + 2012-04-26T14:47:02.481+0000 + 857 + 2011Q3 + routeserver,9.2-2012.02.20-hotfix6.2.13.1 + 22 + routing-route-service,6.2.13.1 + + + REMvaQUAAAB4tdyZCURKQJROJJhqxipAAAAAYAlESkAAAADAasYqQAAAAAAAAPB_AAAAAAAA8H9pqM_8V_SHZp4MKQHNgLOULCerAAEAAICiDCkBAQAAADAnqwABAAAAAADA_wEAAAAAAMD_HY0-82dwsAoDCQ + + -53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + + fastestNow + car + enabled + + 52.5315361,13.3875332 52.5315094,13.3872204 52.5314484,13.3868303 52.5308685,13.3871498 52.5304298,13.3873901 52.5303993,13.3872299 52.5303612,13.3871202 52.5293198,13.3846502 52.5289383,13.3851404 52.5288315,13.3852901 52.5287399,13.3853998 52.5285416,13.3856297 52.5283089,13.38591 52.5281982,13.3860397 52.5280991,13.3861103 52.5274811,13.3867598 52.5271416,13.3869896 52.5270386,13.3870201 52.5262985,13.3871603 52.5262985,13.38727 52.5262489,13.3874302 52.5261917,13.3877001 52.5260506,13.3882999 52.5259895,13.38873 52.5257187,13.3898802 52.5249786,13.3928604 52.5246773,13.3941345 + + + 52.5315361 + 13.3846502 + + + 52.5246773 + 13.3941345 + + + + + -53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + 1271.0 + 273.9 + + + 52.5315361 + 13.3875332 + + Head toward Eichendorffstraße on Invalidenstraße. Go for 150 feet. + 5.2 + 48.0 + -53499799 + forward + + + + 52.5314484 + 13.3868303 + + Turn left onto Eichendorffstraße. Go for 400 feet. + 47.1 + 119.0 + -780236888 + left + + + + 52.5304298 + 13.3873901 + + Turn right onto Schlegelstraße. Go for 0.1 miles. + 55.9 + 223.0 + -53499914 + right + + + + 52.5293198 + 13.3846502 + + Turn left onto Chausseestraße. Go for 0.2 miles. + 68.0 + 286.0 + -749446557 + left + + + + 52.5271416 + 13.3869896 + + Continue on Friedrichstraße, Oranienburger Tor. Go for 300 feet. + 20.1 + 93.0 + -572708773 + forward + + + + 52.5262985 + 13.3871603 + + Turn left onto Oranienburger Straße. Go for 0.3 miles. + 77.6 + 502.0 + +812293299 + left + + + + 52.5246773 + 13.3941345 + + Your destination on Oranienburger Straße is on the right. The trip takes 0.8 miles and 5 mins. + 0.0 + 0.0 + forward + + + -53499799 + 52.5315361,13.3875332 52.5315094,13.3872204 52.5314484,13.3868303 + 48.0 + 13.89 + + 9.17 + 5.2 + 9.72 + 4.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Invalidenstraße +
+ + + -780236888 + 52.5314484,13.3868303 52.5308685,13.3871498 + 68.0 + + 5.0 + 13.6 + 6.94 + 9.8 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Eichendorffstraße +
+ + + -780236887 + 52.5308685,13.3871498 52.5304298,13.3873901 + 51.0 + + 5.28 + 9.7 + 6.94 + 7.3 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Eichendorffstraße +
+ + + -53499914 + 52.5304298,13.3873901 52.5303993,13.3872299 52.5303612,13.3871202 52.5293198,13.3846502 + 223.0 + + 5.28 + 42.3 + 6.94 + 32.1 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Schlegelstraße +
+ + + -749446557 + 52.5293198,13.3846502 52.5289383,13.3851404 + 53.0 + 13.89 + + 10.83 + 4.9 + 9.72 + 5.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763170 + 52.5289383,13.3851404 52.5288315,13.3852901 + 15.0 + 13.89 + + 10.83 + 1.4 + 9.72 + 1.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763169 + 52.5288315,13.3852901 52.5287399,13.3853998 + 12.0 + 13.89 + + 10.83 + 1.1 + 9.72 + 1.2 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763164 + 52.5287399,13.3853998 52.5285416,13.3856297 + 26.0 + 13.89 + + 10.83 + 2.4 + 9.72 + 2.7 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -781763163 + 52.5285416,13.3856297 52.5283089,13.38591 + 32.0 + 13.89 + + 10.83 + 3.0 + 9.72 + 3.3 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -749446551 + 52.5283089,13.38591 52.5281982,13.3860397 + 15.0 + 13.89 + + 10.83 + 1.4 + 9.72 + 1.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -572708771 + 52.5281982,13.3860397 52.5280991,13.3861103 52.5274811,13.3867598 + 93.0 + 13.89 + + 10.83 + 8.6 + 9.72 + 9.6 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -53500039 + 52.5274811,13.3867598 52.5271416,13.3869896 + 40.0 + 13.89 + + 10.83 + 3.7 + 9.72 + 4.1 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Chausseestraße +
+ + + -572708773 + 52.5271416,13.3869896 52.5270386,13.3870201 + 11.0 + 13.89 + + 10.28 + 1.1 + 9.72 + 1.1 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Friedrichstraße, Oranienburger Tor +
+ + + -572708772 + 52.5270386,13.3870201 52.5262985,13.3871603 + 82.0 + 13.89 + + 10.28 + 8.0 + 9.72 + 8.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Friedrichstraße +
+ + + +812293299 + 52.5262985,13.3871603 52.5262985,13.38727 + 7.0 + 13.89 + + 3.61 + 1.9 + 9.72 + 0.7 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -733054082 + 52.5262985,13.38727 52.5262489,13.3874302 + 12.0 + 13.89 + + 11.39 + 1.1 + 9.72 + 1.2 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -733054081 + 52.5262489,13.3874302 52.5261917,13.3877001 + 19.0 + 13.89 + + 11.39 + 1.7 + 9.72 + 2.0 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -572680644 + 52.5261917,13.3877001 52.5260506,13.3882999 + 43.0 + 13.89 + + 10.0 + 4.3 + 9.72 + 4.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -572680642 + 52.5260506,13.3882999 52.5259895,13.38873 + 29.0 + 13.89 + + 11.39 + 2.5 + 9.72 + 3.0 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -572680640 + 52.5259895,13.38873 52.5257187,13.3898802 + 83.0 + 13.89 + + 11.11 + 7.5 + 9.72 + 8.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -53501098 + 52.5257187,13.3898802 52.5249786,13.3928604 + 217.0 + 13.89 + + 8.33 + 26.0 + 9.72 + 22.3 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -53501113 + 52.5249786,13.3928604 52.5246773,13.3941345 + 92.0 + 13.89 + + 8.61 + 10.7 + 9.72 + 9.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ +
+ + 1271.0 + 243.0 + +
+
+
\ No newline at end of file diff --git a/tests/auto/nokia_services/routing/travelmode-pedestrian.xml b/tests/auto/nokia_services/routing/travelmode-pedestrian.xml new file mode 100644 index 0000000..56a79e3 --- /dev/null +++ b/tests/auto/nokia_services/routing/travelmode-pedestrian.xml @@ -0,0 +1,798 @@ + + + + + 2012-04-26T14:48:17.998Z + 2012-04-26T14:47:00.026+0000 + 5094886 + 2012-04-26T14:47:02.413+0000 + 12015 + 2012-04-26T14:47:02.413+0000 + 857 + 2011Q3 + routeserver,9.2-2012.02.20-hotfix6.2.13.1 + 96 + routing-route-service,6.2.13.1 + + + REMvSAkAAAB4tdyZCURKQJROJJhqxipAAAAAYAlESkAAAADAasYqQAAAAAAAAPB_AAAAAAAA8H-XVzADV_SHZp4MKQHNgLOULCerAAEAAICiDCkBAQAAADAnqwABAAAAAADA_wEAAAAAAMD_HY0-84fTC85nlF5wPmO1JsEZpheczwc8AOrpMz9xhQUzcABtrGd-FJ0-86Po9JnfAAHBo80GTA + + +53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + + fastestNow + pedestrian + enabled + + 52.5314903,13.3875389 52.5315857,13.3881445 52.5315475,13.3880892 52.5310287,13.388505 52.5309753,13.3885479 52.5307274,13.3887367 52.530674,13.3887777 52.5297775,13.3894777 52.5297241,13.3895216 52.5280571,13.3913355 52.5279846,13.3914194 52.5281792,13.3924217 52.5276413,13.392765 52.527504,13.3928776 52.5274544,13.3929157 52.5274773,13.3929968 52.5264435,13.3935556 52.5263863,13.3935757 52.5262947,13.3935919 52.525425,13.393137 52.5249977,13.3929052 52.5249405,13.3928967 52.5246468,13.3941231 + + + 52.5315857 + 13.3875389 + + + 52.5246468 + 13.3941231 + + + + + +53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + 1107.0 + 798.2 + + + 52.5315361 + 13.3875332 + + Head toward Borsigstraße on Invalidenstraße. Go for 100 feet. + 27.4 + 38.0 + +53499799 + forward + + + + 52.5315819 + 13.3880997 + + Turn right and use the crosswalk. + 6.0 + 8.0 + -811853913 + right + + + + 52.5315819 + 13.3880997 + + Continue on Borsigstraße. Go for 0.3 miles. + 343.4 + 476.0 + -811853915 + forward + + + + 52.5280304 + 13.3914099 + + Cross Torstraße. + 5.0 + 8.0 + -833290988 + forward + + + + 52.5280304 + 13.3914099 + + Turn left onto Torstraße. Go for 250 feet. + 52.6 + 73.0 + +53499991 + left + + + + 52.5282288 + 13.3924398 + + Turn right onto Tucholskystraße. Go for 300 feet. + 63.4 + 88.0 + -53500024 + right + + + + 52.5274887 + 13.39293 + + Cross Linienstraße, Tucholskystraße. + 12.0 + 16.0 + -53520166 + forward + + + + 52.5274887 + 13.39293 + + Turn right onto Tucholskystraße. Go for 0.2 miles. + 216.2 + 300.0 + -53500091 + right + + + + 52.5249786 + 13.3928604 + + Cross Oranienburger Straße. + 6.0 + 8.0 + -53501113 + forward + + + + 52.5249786 + 13.3928604 + + Turn left onto Oranienburger Straße. Go for 300 feet. + 66.2 + 92.0 + -53501113 + left + + + + 52.5246773 + 13.3941345 + + Your destination on Oranienburger Straße is on the right. The trip takes 0.7 miles and 13 mins. + 0.0 + 0.0 + forward + + + +53499799 + 52.5314903,13.3875389 52.5315857,13.3881445 + 38.0 + 13.89 + + 7.77 + 4.9 + 1.39 + 27.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Invalidenstraße +
+ + + -811853913 + 52.5315857,13.3881445 52.5315475,13.3880892 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte +
+ + + +811853913 + 52.5315475,13.3880892 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte +
+ + + -811853915 + 52.5315475,13.3880892 52.5310287,13.388505 + 70.0 + + 1.39 + 50.4 + 1.39 + 50.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Borsigstraße +
+ + + -838257237 + 52.5310287,13.388505 52.5309753,13.3885479 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte +
+ + + +838257237 + 52.5309753,13.3885479 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte +
+ + + -811853914 + 52.5309753,13.3885479 52.5307274,13.3887367 + 36.0 + + 1.39 + 25.9 + 1.39 + 25.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Borsigstraße +
+ + + -53499858 + 52.5307274,13.3887367 52.530674,13.3887777 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Schlegelstraße +
+ + + +53499858 + 52.530674,13.3887777 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Schlegelstraße +
+ + + -53499890 + 52.530674,13.3887777 52.5297775,13.3894777 + 116.0 + + 1.39 + 83.5 + 1.39 + 83.5 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Borsigstraße +
+ + + -53499910 + 52.5297775,13.3894777 52.5297241,13.3895216 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tieckstraße +
+ + + +53499910 + 52.5297241,13.3895216 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tieckstraße +
+ + + -53499992 + 52.5297241,13.3895216 52.5280571,13.3913355 + 230.0 + + 1.39 + 165.6 + 1.39 + 165.6 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Borsigstraße +
+ + + -833290988 + 52.5280571,13.3913355 52.5279846,13.3914194 + 4.0 + 13.89 + + 8.33 + 0.5 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Torstraße +
+ + + +833290988 + 52.5279846,13.3914194 + 4.0 + 13.89 + + 7.5 + 0.5 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Torstraße +
+ + + +53499991 + 52.5279846,13.3914194 52.5281792,13.3924217 + 73.0 + 13.89 + + 7.5 + 9.7 + 1.39 + 52.6 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Torstraße +
+ + + -53500024 + 52.5281792,13.3924217 52.5276413,13.392765 52.527504,13.3928776 + 88.0 + + 1.39 + 63.4 + 1.39 + 63.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tucholskystraße +
+ + + -53520166 + 52.527504,13.3928776 52.5274544,13.3929157 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Linienstraße +
+ + + +53520166 + 52.5274544,13.3929157 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Linienstraße +
+ + + -53500091 + 52.5274544,13.3929157 52.5274773,13.3929968 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tucholskystraße +
+ + + +53500091 + 52.5274773,13.3929968 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tucholskystraße +
+ + + -53500091 + 52.5274773,13.3929968 52.5264435,13.3935556 + 126.0 + + 1.39 + 90.7 + 1.39 + 90.7 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tucholskystraße +
+ + + +53500090 + 52.5264435,13.3935556 52.5263863,13.3935757 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Auguststraße +
+ + + -53500090 + 52.5263863,13.3935757 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Auguststraße +
+ + + -844906239 + 52.5263863,13.3935757 52.5262947,13.3935919 52.525425,13.393137 + 112.0 + + 1.39 + 80.6 + 1.39 + 80.6 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tucholskystraße +
+ + + -844906238 + 52.525425,13.393137 52.5249977,13.3929052 + 54.0 + + 1.39 + 38.9 + 1.39 + 38.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tucholskystraße +
+ + + -53501113 + 52.5249977,13.3929052 52.5249405,13.3928967 + 4.0 + 13.89 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + +53501113 + 52.5249405,13.3928967 + 4.0 + 13.89 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -53501113 + 52.5249405,13.3928967 52.5246468,13.3941231 + 92.0 + 13.89 + + 1.39 + 66.2 + 1.39 + 66.2 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ +
+ + 1107.0 + 798.0 + 798.0 + noThroughRoad + +
+
+
\ No newline at end of file diff --git a/tests/auto/nokia_services/routing/travelmode-public-transport.xml b/tests/auto/nokia_services/routing/travelmode-public-transport.xml new file mode 100644 index 0000000..cf146ea --- /dev/null +++ b/tests/auto/nokia_services/routing/travelmode-public-transport.xml @@ -0,0 +1,343 @@ + + + + + 2012-04-26T14:49:40.902Z + 2012-04-26T14:47:00.026+0000 + 5094886 + 2012-04-26T14:47:02.494+0000 + 12015 + 2012-04-26T14:47:02.494+0000 + 857 + 2011Q3 + routeserver,9.2-2012.02.20-hotfix6.2.13.1 + 142 + routing-route-service,6.2.13.1 + + + REMvTwUAAAB4tdyZCURKQJROJJhqxipAAAAAYAlESkAAAADAasYqQAAAAAAAAPB_AAAAAAAA8H-XVzADV_SHZp4MKQHNgLOULCerAAEAAICiDCkBAQAAADAnqwABAAAAAADA_wEAAAAAAMD_HY0-84f6AgAAvBcAABjgZf7_Hyzz__8Hkw + + +53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + + fastestNow + publicTransport + enabled + + 52.5315819,13.3875275 52.5315819,13.3880997 52.5316086,13.3882599 52.5323792,13.3873796 52.5251007,13.3922596 52.5251007,13.3922596 52.5249786,13.3928604 52.5249443,13.3928757 52.5246468,13.3941231 + + + 52.5323792 + 13.3873796 + + + 52.5246468 + 13.3941231 + + + + + +53499799 + + 52.5315361 + 13.3875332 + + + 52.531543 + 13.387532 + + stopOver + + + -53501113 + + 52.5246773 + 13.3941345 + + + 52.524646 + 13.394128 + + stopOver + + 1388.0 + 641.3 + + + 52.5315361 + 13.3875332 + + Head toward Borsigstraße on Invalidenstraße. Go for 100 feet. + 27.4 + 38.0 + +53499799 + forward + + + + 52.5315819 + 13.3880997 + + Leave Invalidenstraße Go for 400 feet. + 115.7 + 115.0 + +1525 + forward + + + + 52.5323792 + 13.3873796 + + Take REGIONALMETRO "?es "?ains (Deutsche Bahn), departure 18:55. + 378.7 + 1092.0 + + + + + 52.5251007 + 13.3922596 + + Go through the virtual connection. Go for 150 feet. + 47.4 + 43.0 + -3281 + forward + + + + 52.5249786 + 13.3928604 + + Turn right and cross Tucholskystraße. + 6.0 + 8.0 + -53501259 + right + + + + 52.5249786 + 13.3928604 + + Continue on Oranienburger Straße. Go for 300 feet. + 66.2 + 92.0 + -53501113 + forward + + + + 52.5246773 + 13.3941345 + + Your destination on Oranienburger Straße is on the right. The trip takes 0.9 miles and 11 mins. + 0.0 + 0.0 + forward + + + +53499799 + 52.5315819,13.3875275 52.5315819,13.3880997 + 38.0 + 13.89 + + 7.77 + 4.9 + 1.39 + 27.4 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Invalidenstraße +
+ + + +1525 + 52.5315819,13.3880997 52.5316086,13.3882599 + 11.0 + 1.39 + + 1.39 + 7.9 + 1.39 + 7.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Nordbahnhof +
+ + + +1519 + 52.5316086,13.3882599 52.5323792,13.3873796 + 104.0 + 1.39 + + 1.39 + 74.9 + 1.39 + 74.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Nordbahnhof +
+ + + -8016 + 52.5323792,13.3873796 52.5251007,13.3922596 + 1092.0 + + + -3281 + 52.5251007,13.3922596 52.5251007,13.3922596 + 1.0 + 1.39 + + 1.39 + 0.7 + 1.39 + 0.7 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -3284 + 52.5251007,13.3922596 52.5249786,13.3928604 + 42.0 + 1.39 + + 1.39 + 30.2 + 1.39 + 30.2 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ + + -53501259 + 52.5249786,13.3928604 52.5249443,13.3928757 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tucholskystraße +
+ + + +53501259 + 52.5249443,13.3928757 + 4.0 + + 1.39 + 2.9 + 1.39 + 2.9 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Tucholskystraße +
+ + + -53501113 + 52.5249443,13.3928757 52.5246468,13.3941231 + 92.0 + 13.89 + + 1.39 + 66.2 + 1.39 + 66.2 + +
+ + DE + Berlin + Berlin + Berlin + Mitte + Oranienburger Straße +
+ +
+ + 1388.0 + 641.0 + 641.0 + noThroughRoad + unpaved + publicTransport + +
+
+
\ No newline at end of file diff --git a/tests/auto/nokia_services/routing/tst_routing.cpp b/tests/auto/nokia_services/routing/tst_routing.cpp new file mode 100644 index 0000000..c214556 --- /dev/null +++ b/tests/auto/nokia_services/routing/tst_routing.cpp @@ -0,0 +1,517 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +#define CHECK_CLOSE_E(expected, actual, e) QVERIFY((qAbs(actual - expected) <= e)) +#define CHECK_CLOSE(expected, actual) CHECK_CLOSE_E(expected, actual, qreal(1e-6)) + +class MockGeoNetworkReply : public QNetworkReply +{ +public: + MockGeoNetworkReply( QObject* parent = 0); + virtual void abort(); + + void setFile(QFile* file); + void complete(); + using QNetworkReply::setRequest; + using QNetworkReply::setOperation; + using QNetworkReply::setError; + +protected: + virtual qint64 readData(char *data, qint64 maxlen); + virtual qint64 writeData(const char *data, qint64 len); + +private: + QFile* m_file; +}; + +MockGeoNetworkReply::MockGeoNetworkReply(QObject* parent) +: QNetworkReply(parent) +, m_file(0) +{ + setOpenMode(QIODevice::ReadOnly); +} + +void MockGeoNetworkReply::abort() +{} + +qint64 MockGeoNetworkReply::readData(char *data, qint64 maxlen) +{ + if (m_file) { + const qint64 read = m_file->read(data, maxlen); + if (read <= 0) + return -1; + return read; + } + return -1; +} + +qint64 MockGeoNetworkReply::writeData(const char *data, qint64 len) +{ + Q_UNUSED(data); + Q_UNUSED(len); + return -1; +} + +void MockGeoNetworkReply::setFile(QFile* file) +{ + delete m_file; + m_file = file; + if (m_file) + m_file->setParent(this); +} + +void MockGeoNetworkReply::complete() +{ + if (error() != QNetworkReply::NoError) + emit error(error()); + setFinished(true); + emit finished(); +} + +class MockGeoNetworkAccessManager : public QGeoNetworkAccessManager +{ +public: + MockGeoNetworkAccessManager(QObject* parent = 0); + QNetworkReply* get(const QNetworkRequest& request); + QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data); + + void setReply(MockGeoNetworkReply* reply); + +private: + MockGeoNetworkReply* m_reply; +}; + +MockGeoNetworkAccessManager::MockGeoNetworkAccessManager(QObject* parent) +: QGeoNetworkAccessManager(parent) +, m_reply(0) +{} + +QNetworkReply* MockGeoNetworkAccessManager::get(const QNetworkRequest& request) +{ + MockGeoNetworkReply* r = m_reply; + m_reply = 0; + if (r) { + r->setRequest(request); + r->setOperation(QNetworkAccessManager::GetOperation); + r->setParent(0); + } + + return r; +} + +QNetworkReply* MockGeoNetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data) +{ + Q_UNUSED(request); + Q_UNUSED(data); + QTest::qFail("Not implemented", __FILE__, __LINE__); + return new MockGeoNetworkReply(); +} + +void MockGeoNetworkAccessManager::setReply(MockGeoNetworkReply* reply) +{ + delete m_reply; + m_reply = reply; + if (m_reply) + m_reply->setParent(this); +} + +class tst_nokia_routing : public QObject +{ + Q_OBJECT + +public: + tst_nokia_routing(); + +private: + void calculateRoute(); + void loadReply(const QString& filename); + void onReply(QGeoRouteReply* reply); + void verifySaneRoute(const QGeoRoute& route); + + // Infrastructure slots +private Q_SLOTS: + void routingFinished(QGeoRouteReply* reply); + void routingError(QGeoRouteReply* reply, QGeoRouteReply::Error error, QString errorString); + + // Test slots +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void cleanup(); + void can_compute_route_for_all_supported_travel_modes(); + void can_compute_route_for_all_supported_travel_modes_data(); + void can_compute_route_for_all_supported_optimizations(); + void can_compute_route_for_all_supported_optimizations_data(); + void can_handle_multiple_routes_in_response(); + void can_handle_no_route_exists_case(); + void can_handle_invalid_server_responses(); + void can_handle_invalid_server_responses_data(); + void can_handle_additions_to_routing_xml(); + void foobar(); + void foobar_data(); + +private: + QGeoServiceProvider* m_geoServiceProvider; + MockGeoNetworkAccessManager* m_networkManager; + QGeoRoutingManager* m_routingManager; + QGeoRouteReply* m_reply; + MockGeoNetworkReply* m_replyUnowned; + QGeoRouteRequest m_dummyRequest; + bool m_calculationDone; + bool m_expectError; +}; + +tst_nokia_routing::tst_nokia_routing() +: m_geoServiceProvider(0) +, m_networkManager(0) +, m_routingManager(0) +, m_reply(0) +, m_replyUnowned() +, m_calculationDone(true) +, m_expectError(false) +{ +} + +void tst_nokia_routing::loadReply(const QString& filename) +{ + QFile* file = new QFile(QFINDTESTDATA(filename)); + if (!file->open(QIODevice::ReadOnly)) { + delete file; + file = 0; + qDebug() << filename; + QTest::qFail("Failed to open file", __FILE__, __LINE__); + } + + m_replyUnowned = new MockGeoNetworkReply(); + m_replyUnowned->setFile(file); + m_networkManager->setReply(m_replyUnowned); +} + +void tst_nokia_routing::calculateRoute() +{ + QVERIFY2(m_replyUnowned, "No reply set"); + m_calculationDone = false; + m_routingManager->calculateRoute(m_dummyRequest); + m_replyUnowned->complete(); + m_replyUnowned = 0; + QTRY_VERIFY_WITH_TIMEOUT(m_calculationDone, 100); +} + +void tst_nokia_routing::onReply(QGeoRouteReply* reply) +{ + QVERIFY(reply); + //QVERIFY(0 == m_reply); + m_reply = reply; + if (m_reply) + m_reply->setParent(0); + m_calculationDone = true; +} + +void tst_nokia_routing::verifySaneRoute(const QGeoRoute& route) +{ + QVERIFY(route.distance() > 0); + QVERIFY(route.travelTime() > 0); + QVERIFY(route.travelMode() != 0); + + const QGeoRectangle bounds = route.bounds(); + QVERIFY(bounds.width() > 0); + QVERIFY(bounds.height() > 0); + + const QList path = route.path(); + QVERIFY(path.size() >= 2); + + foreach (const QGeoCoordinate& coord, path) { + QVERIFY(coord.isValid()); + QVERIFY(bounds.contains(coord)); + } + + QGeoRouteSegment segment = route.firstRouteSegment(); + bool first = true, last = false; + + do { + const QGeoRouteSegment next = segment.nextRouteSegment(); + last = next.isValid(); + + QVERIFY(segment.isValid()); + QVERIFY(segment.distance() >= 0); + QVERIFY(segment.travelTime() >= 0); // times are rounded and thus may end up being zero + + const QList path = segment.path(); + foreach (const QGeoCoordinate& coord, path) { + QVERIFY(coord.isValid()); + if (!first && !last) { + QVERIFY(bounds.contains(coord)); // on pt and pedestrian + } + } + + const QGeoManeuver maneuver = segment.maneuver(); + + if (maneuver.isValid()) { + QVERIFY(!maneuver.instructionText().isEmpty()); + QVERIFY(maneuver.position().isValid()); + if (!first && !last) { + QVERIFY(bounds.contains(maneuver.position())); // on pt and pedestrian + } + } + + segment = next; + first = false; + } while (!last); +} + +void tst_nokia_routing::routingFinished(QGeoRouteReply* reply) +{ + onReply(reply); +} + +void tst_nokia_routing::routingError(QGeoRouteReply* reply, QGeoRouteReply::Error error, QString errorString) +{ + Q_UNUSED(error); + + if (!m_expectError) { + QFAIL(qPrintable(errorString)); + } else { + onReply(reply); + } +} + +void tst_nokia_routing::initTestCase() +{ + QStringList providers = QGeoServiceProvider::availableServiceProviders(); + QVERIFY(providers.contains(QStringLiteral("here"))); + + m_networkManager = new MockGeoNetworkAccessManager(); + + QVariantMap parameters; + parameters.insert(QStringLiteral("nam"), QVariant::fromValue(m_networkManager)); + parameters.insert(QStringLiteral("here.app_id"), "stub"); + parameters.insert(QStringLiteral("here.token"), "stub"); + + m_geoServiceProvider = new QGeoServiceProvider(QStringLiteral("here"), parameters); + QVERIFY(m_geoServiceProvider); + + m_routingManager = m_geoServiceProvider->routingManager(); + QVERIFY(m_routingManager); + + connect(m_routingManager, SIGNAL(finished(QGeoRouteReply*)), + this, SLOT(routingFinished(QGeoRouteReply*))); + connect(m_routingManager, SIGNAL(error(QGeoRouteReply*,QGeoRouteReply::Error,QString)), + this, SLOT(routingError(QGeoRouteReply*,QGeoRouteReply::Error,QString))); + + QList waypoints; + waypoints.push_back(QGeoCoordinate(1, 1)); + waypoints.push_back(QGeoCoordinate(2, 2)); + m_dummyRequest.setWaypoints(waypoints); +} + +void tst_nokia_routing::cleanupTestCase() +{ + delete m_geoServiceProvider; + + // network access manager will be deleted by plugin + + m_geoServiceProvider = 0; + m_networkManager = 0; + m_routingManager = 0; +} + +void tst_nokia_routing::cleanup() +{ + delete m_reply; + m_reply = 0; + m_replyUnowned = 0; + m_expectError = false; +} + +void tst_nokia_routing::can_compute_route_for_all_supported_travel_modes() +{ + QFETCH(int, travelMode); + QFETCH(QString, file); + QFETCH(qreal, distance); + QFETCH(int, duration); + + loadReply(file); + calculateRoute(); + + QList routes = m_reply->routes(); + QCOMPARE(1, routes.size()); + QGeoRoute& route = routes[0]; + QCOMPARE(travelMode, (int)route.travelMode()); + CHECK_CLOSE(distance, route.distance()); + QCOMPARE(duration, route.travelTime()); + verifySaneRoute(route); +} + +void tst_nokia_routing::can_compute_route_for_all_supported_travel_modes_data() +{ + QTest::addColumn("travelMode"); + QTest::addColumn("file"); + QTest::addColumn("distance"); + QTest::addColumn("duration"); + + QTest::newRow("Car") << (int)QGeoRouteRequest::CarTravel << QString("travelmode-car.xml") << (qreal)1271.0 << 243; + QTest::newRow("Pedestrian") << (int)QGeoRouteRequest::PedestrianTravel << QString("travelmode-pedestrian.xml") << (qreal)1107.0 << 798; + QTest::newRow("Public Transport") << (int)QGeoRouteRequest::PublicTransitTravel << QString("travelmode-public-transport.xml") << (qreal)1388.0 << 641; +} + +void tst_nokia_routing::can_compute_route_for_all_supported_optimizations() +{ + QFETCH(int, optimization); + QFETCH(QString, file); + QFETCH(qreal, distance); + QFETCH(int, duration); + m_dummyRequest.setRouteOptimization((QGeoRouteRequest::RouteOptimization)optimization); + loadReply(file); + calculateRoute(); + QList routes = m_reply->routes(); + QCOMPARE(1, routes.size()); + QGeoRoute& route = routes[0]; + CHECK_CLOSE(distance, route.distance()); + QCOMPARE(duration, route.travelTime()); + verifySaneRoute(route); +} + +void tst_nokia_routing::can_compute_route_for_all_supported_optimizations_data() +{ + QTest::addColumn("optimization"); + QTest::addColumn("file"); + QTest::addColumn("distance"); + QTest::addColumn("duration"); + + QTest::newRow("Shortest") << (int)QGeoRouteRequest::ShortestRoute << QString("optim-shortest.xml") << qreal(1177.0) << 309; + QTest::newRow("Fastest") << (int)QGeoRouteRequest::FastestRoute << QString("optim-fastest.xml") << qreal(1271.0) << 243; +} + +void tst_nokia_routing::can_handle_multiple_routes_in_response() +{ + loadReply(QStringLiteral("multiple-routes-in-response.xml")); + calculateRoute(); + QList routes = m_reply->routes(); + QCOMPARE(2, routes.size()); + + verifySaneRoute(routes[0]); + verifySaneRoute(routes[1]); +} + +void tst_nokia_routing::can_handle_no_route_exists_case() +{ + loadReply(QStringLiteral("error-no-route.xml")); + calculateRoute(); + QCOMPARE(QGeoRouteReply::NoError, m_reply->error()); + QList routes = m_reply->routes(); + QCOMPARE(0, routes.size()); +} + +void tst_nokia_routing::can_handle_additions_to_routing_xml() +{ + loadReply(QStringLiteral("littered-with-new-tags.xml")); + calculateRoute(); + QCOMPARE(QGeoRouteReply::NoError, m_reply->error()); + QList routes = m_reply->routes(); + QVERIFY(routes.size() > 0); +} + +void tst_nokia_routing::can_handle_invalid_server_responses() +{ + QFETCH(QString, file); + + m_expectError = true; + + loadReply(file); + calculateRoute(); + QCOMPARE(QGeoRouteReply::ParseError, m_reply->error()); +} + +void tst_nokia_routing::can_handle_invalid_server_responses_data() +{ + QTest::addColumn("file"); + + QTest::newRow("Trash") << QString("invalid-response-trash.xml"); + QTest::newRow("Half way through") << QString("invalid-response-half-way-through.xml"); + QTest::newRow("No tag") << QString("invalid-response-no-calculateroute-tag.xml"); +} + +void tst_nokia_routing::foobar() +{ + QFETCH(int, code); + + m_expectError = true; + m_replyUnowned = new MockGeoNetworkReply(); + m_replyUnowned->setError(static_cast(code), QStringLiteral("Test error")); + m_networkManager->setReply(m_replyUnowned); + calculateRoute(); + QCOMPARE(QGeoRouteReply::CommunicationError, m_reply->error()); +} + +void tst_nokia_routing::foobar_data() +{ + QTest::addColumn("code"); + + QTest::newRow("QNetworkReply::ConnectionRefusedError") << int(QNetworkReply::ConnectionRefusedError); + QTest::newRow("QNetworkReply::RemoteHostClosedError") << int(QNetworkReply::RemoteHostClosedError); + QTest::newRow("QNetworkReply::HostNotFoundError") << int(QNetworkReply::HostNotFoundError); + QTest::newRow("QNetworkReply::TimeoutError") << int(QNetworkReply::TimeoutError); + QTest::newRow("QNetworkReply::OperationCanceledError") << int(QNetworkReply::OperationCanceledError); + QTest::newRow("QNetworkReply::SslHandshakeFailedError") << int(QNetworkReply::SslHandshakeFailedError); + QTest::newRow("QNetworkReply::TemporaryNetworkFailureError") << int(QNetworkReply::TemporaryNetworkFailureError); + QTest::newRow("QNetworkReply::ProxyConnectionRefusedError") << int(QNetworkReply::ProxyConnectionRefusedError); + QTest::newRow("QNetworkReply::ProxyConnectionClosedError") << int(QNetworkReply::ProxyConnectionClosedError); + QTest::newRow("QNetworkReply::ProxyNotFoundError") << int(QNetworkReply::ProxyNotFoundError); + QTest::newRow("QNetworkReply::ProxyTimeoutError") << int(QNetworkReply::ProxyTimeoutError); + QTest::newRow("QNetworkReply::ProxyAuthenticationRequiredError") << int(QNetworkReply::ProxyAuthenticationRequiredError); + QTest::newRow("QNetworkReply::ContentAccessDenied") << int(QNetworkReply::ContentAccessDenied); + QTest::newRow("QNetworkReply::ContentOperationNotPermittedError") << int(QNetworkReply::ContentOperationNotPermittedError); + QTest::newRow("QNetworkReply::ContentNotFoundError") << int(QNetworkReply::ContentNotFoundError); + QTest::newRow("QNetworkReply::ContentReSendError") << int(QNetworkReply::ContentReSendError); + QTest::newRow("QNetworkReply::ProtocolUnknownError") << int(QNetworkReply::ProtocolUnknownError); + QTest::newRow("QNetworkReply::ProtocolInvalidOperationError") << int(QNetworkReply::ProtocolInvalidOperationError); + QTest::newRow("QNetworkReply::UnknownNetworkError") << int(QNetworkReply::UnknownNetworkError); + QTest::newRow("QNetworkReply::UnknownProxyError") << int(QNetworkReply::UnknownProxyError); + QTest::newRow("QNetworkReply::ProxyAuthenticationRequiredError") << int(QNetworkReply::ProxyAuthenticationRequiredError); + QTest::newRow("QNetworkReply::ProtocolFailure") << int(QNetworkReply::ProtocolFailure); +} + + +QTEST_MAIN(tst_nokia_routing) + +#include "tst_routing.moc" diff --git a/tests/auto/placemanager_utils/placemanager_utils.cpp b/tests/auto/placemanager_utils/placemanager_utils.cpp new file mode 100644 index 0000000..d5ba61f --- /dev/null +++ b/tests/auto/placemanager_utils/placemanager_utils.cpp @@ -0,0 +1,376 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "placemanager_utils.h" + +#include +#include +#include +#include +#include +#include +#include + +//constant for timeout to verify signals +const int PlaceManagerUtils::Timeout(10000); + +PlaceManagerUtils::PlaceManagerUtils(QObject *parent) + : QObject(parent), placeManager(0) +{ +} + +bool PlaceManagerUtils::doSavePlace(QPlaceManager *manager, + const QPlace &place, + QPlaceReply::Error expectedError, + QString *placeId) +{ + Q_ASSERT(manager); + QPlaceIdReply *saveReply = manager->savePlace(place); + bool isSuccessful = checkSignals(saveReply, expectedError, manager); + if (placeId != 0) { + *placeId = saveReply->id(); + } + + if (saveReply->id().isEmpty() && expectedError == QPlaceReply::NoError) { + qWarning("ID is empty in reply for save operation"); + qWarning() << "Error string = " << saveReply->errorString(); + isSuccessful = false; + } + + if (!isSuccessful) + qWarning() << "Error string = " << saveReply->errorString(); + + return isSuccessful; +} + +void PlaceManagerUtils::doSavePlaces(QPlaceManager *manager, QList &places) +{ + QPlaceIdReply *saveReply; + + foreach (QPlace place, places) { + saveReply = manager->savePlace(place); + QSignalSpy saveSpy(saveReply, SIGNAL(finished())); + QTRY_VERIFY_WITH_TIMEOUT(saveSpy.count() == 1, Timeout); + QCOMPARE(saveReply->error(), QPlaceReply::NoError); + saveSpy.clear(); + } +} + +void PlaceManagerUtils::doSavePlaces(QPlaceManager *manager, const QList &places) +{ + QPlaceIdReply *saveReply; + + static int count= 0; + foreach (QPlace *place, places) { + count++; + saveReply = manager->savePlace(*place); + QSignalSpy saveSpy(saveReply, SIGNAL(finished())); + QTRY_VERIFY_WITH_TIMEOUT(saveSpy.count() == 1, Timeout); + QCOMPARE(saveReply->error(), QPlaceReply::NoError); + place->setPlaceId(saveReply->id()); + saveSpy.clear(); + } +} + +bool PlaceManagerUtils::doSearch(QPlaceManager *manager, + const QPlaceSearchRequest &request, + QList *results, + QPlaceReply::Error expectedError) +{ + QPlaceSearchReply *searchReply= manager->search(request); + bool success = checkSignals(searchReply, expectedError, manager); + *results = searchReply->results(); + return success; +} + +bool PlaceManagerUtils::doSearch(QPlaceManager *manager, + const QPlaceSearchRequest &request, + QList *results, QPlaceReply::Error expectedError) +{ + bool success = false; + results->clear(); + QList searchResults; + success = doSearch(manager, request, &searchResults, expectedError); + foreach (const QPlaceSearchResult &searchResult, searchResults) { + if (searchResult.type() == QPlaceSearchResult::PlaceResult) { + QPlaceResult placeResult = searchResult; + results->append(placeResult.place()); + } + } + return success; +} + +bool PlaceManagerUtils::doSearchSuggestions(QPlaceManager *manager, + const QPlaceSearchRequest &request, + QStringList *results, + QPlaceReply::Error expectedError) +{ + QPlaceSearchSuggestionReply *reply = manager->searchSuggestions(request); + bool success = checkSignals(reply, expectedError, manager); + *results = reply->suggestions(); + + if (!success) + qDebug() << "Error string = " << reply->errorString(); + + return success; +} + +bool PlaceManagerUtils::doRemovePlace(QPlaceManager *manager, + const QPlace &place, + QPlaceReply::Error expectedError) +{ + QPlaceIdReply *removeReply = manager->removePlace(place.placeId()); + bool isSuccessful = false; + isSuccessful = checkSignals(removeReply, expectedError, manager) + && (removeReply->id() == place.placeId()); + + if (!isSuccessful) + qWarning() << "Place removal unsuccessful errorString = " << removeReply->errorString(); + + return isSuccessful; +} + +bool PlaceManagerUtils::doFetchDetails(QPlaceManager *manager, + QString placeId, QPlace *place, + QPlaceReply::Error expectedError) +{ + QPlaceDetailsReply *detailsReply = manager->getPlaceDetails(placeId); + bool success = checkSignals(detailsReply, expectedError, manager); + *place = detailsReply->place(); + + if (!success) + qDebug() << "Error string = " << detailsReply->errorString(); + + return success; +} + +bool PlaceManagerUtils::doInitializeCategories(QPlaceManager *manager, + QPlaceReply::Error expectedError) +{ + QPlaceReply *reply = manager->initializeCategories(); + bool success = checkSignals(reply, expectedError, manager); + + if (!success) + qDebug() << "Error string = " << reply->errorString(); + + delete reply; + return success; +} + +bool PlaceManagerUtils::doSaveCategory(QPlaceManager *manager, + const QPlaceCategory &category, + const QString &parentId, + QPlaceReply::Error expectedError, + QString *categoryId) +{ + QPlaceIdReply *idReply = manager->saveCategory(category, parentId); + bool isSuccessful = checkSignals(idReply, expectedError, manager) + && (idReply->error() == expectedError); + + if (categoryId != 0) + *categoryId = idReply->id(); + + if (!isSuccessful) + qDebug() << "Error string =" << idReply->errorString(); + return isSuccessful; +} + +bool PlaceManagerUtils::doRemoveCategory(QPlaceManager *manager, + const QPlaceCategory &category, + QPlaceReply::Error expectedError) +{ + QPlaceIdReply *idReply = manager->removeCategory(category.categoryId()); + + bool isSuccessful = checkSignals(idReply, expectedError, manager) && + (idReply->error() == expectedError); + return isSuccessful; +} + +bool PlaceManagerUtils::doFetchCategory(QPlaceManager *manager, + const QString &categoryId, + QPlaceCategory *category, + QPlaceReply::Error expectedError) +{ + Q_ASSERT(category); + QPlaceReply * catInitReply = manager->initializeCategories(); + bool isSuccessful = checkSignals(catInitReply, expectedError, manager); + *category = manager->category(categoryId); + + if (!isSuccessful) + qDebug() << "Error initializing categories, error string = " + << catInitReply->errorString(); + + if (category->categoryId() != categoryId) + isSuccessful = false; + return isSuccessful; +} + +bool PlaceManagerUtils::doFetchContent(QPlaceManager *manager, + const QPlaceContentRequest &request, + QPlaceContent::Collection *results, + QPlaceReply::Error expectedError) +{ + Q_ASSERT(results); + QPlaceContentReply *reply = manager->getPlaceContent(request); + bool isSuccessful = checkSignals(reply, expectedError, manager); + *results = reply->content(); + + if (!isSuccessful) + qDebug() << "Error during content fetch, error string = " + << reply->errorString(); + + return isSuccessful; +} + +bool PlaceManagerUtils::doMatch(QPlaceManager *manager, + const QPlaceMatchRequest &request, + QList *places, + QPlaceReply::Error expectedError) +{ + QPlaceMatchReply *reply = manager->matchingPlaces(request); + bool isSuccessful = checkSignals(reply, expectedError, manager) && + (reply->error() == expectedError); + *places = reply->places(); + if (!isSuccessful) + qDebug() << "Error for matching operation, error string = " + << reply->errorString(); + return isSuccessful; +} + +bool PlaceManagerUtils::checkSignals(QPlaceReply *reply, QPlaceReply::Error expectedError, + QPlaceManager *manager) +{ + Q_ASSERT(reply); + QSignalSpy finishedSpy(reply, SIGNAL(finished())); + QSignalSpy errorSpy(reply, SIGNAL(error(QPlaceReply::Error,QString))); + QSignalSpy managerFinishedSpy(manager, SIGNAL(finished(QPlaceReply*))); + QSignalSpy managerErrorSpy(manager,SIGNAL(error(QPlaceReply*,QPlaceReply::Error,QString))); + + if (expectedError != QPlaceReply::NoError) { + //check that we get an error signal from the reply + WAIT_UNTIL(errorSpy.count() == 1); + if (errorSpy.count() != 1) { + qWarning() << "Error signal for search operation not received"; + return false; + } + + //check that we get the correct error from the reply's signal + QPlaceReply::Error actualError = qvariant_cast(errorSpy.at(0).at(0)); + if (actualError != expectedError) { + qWarning() << "Actual error code in reply signal does not match expected error code"; + qWarning() << "Actual error code = " << actualError; + qWarning() << "Expected error coe =" << expectedError; + return false; + } + + //check that we get an error signal from the manager + WAIT_UNTIL(managerErrorSpy.count() == 1); + if (managerErrorSpy.count() !=1) { + qWarning() << "Error signal from manager for search operation not received"; + return false; + } + + //check that we get the correct reply instance in the error signal from the manager + if (qvariant_cast(managerErrorSpy.at(0).at(0)) != reply) { + qWarning() << "Reply instance in error signal from manager is incorrect"; + return false; + } + + //check that we get the correct error from the signal of the manager + actualError = qvariant_cast(managerErrorSpy.at(0).at(1)); + if (actualError != expectedError) { + qWarning() << "Actual error code from manager signal does not match expected error code"; + qWarning() << "Actual error code =" << actualError; + qWarning() << "Expected error code = " << expectedError; + return false; + } + } + + //check that we get a finished signal + WAIT_UNTIL(finishedSpy.count() == 1); + if (finishedSpy.count() !=1) { + qWarning() << "Finished signal from reply not received"; + return false; + } + + if (reply->error() != expectedError) { + qWarning() << "Actual error code does not match expected error code"; + qWarning() << "Actual error code: " << reply->error(); + qWarning() << "Expected error code" << expectedError; + return false; + } + + if (expectedError == QPlaceReply::NoError && !reply->errorString().isEmpty()) { + qWarning() << "Expected error was no error but error string was not empty"; + qWarning() << "Error string=" << reply->errorString(); + return false; + } + + //check that we get the finished signal from the manager + WAIT_UNTIL(managerFinishedSpy.count() == 1); + if (managerFinishedSpy.count() != 1) { + qWarning() << "Finished signal from manager not received"; + return false; + } + + //check that the reply instance in the finished signal from the manager is correct + if (qvariant_cast(managerFinishedSpy.at(0).at(0)) != reply) { + qWarning() << "Reply instance in finished signal from manager is incorrect"; + return false; + } + + return true; +} + +bool PlaceManagerUtils::compare(const QList &actualResults, + const QList &expectedResults) +{ + QSet actualIds; + foreach (const QPlace &place, actualResults) + actualIds.insert(place.placeId()); + + QSet expectedIds; + foreach (const QPlace &place, expectedResults) + expectedIds.insert(place.placeId()); + + bool isMatch = (actualIds == expectedIds); + if (actualResults.count() != expectedResults.count() || !isMatch) { + qWarning() << "comparison of results by name does not match"; + qWarning() << "actual result ids: " << actualIds; + qWarning() << "expected result ids : " << expectedIds; + return false; + } + + return isMatch; +} + +void PlaceManagerUtils::setVisibility(QList places, QLocation::Visibility visibility) +{ + foreach (QPlace *place, places) + place->setVisibility(visibility); +} diff --git a/tests/auto/placemanager_utils/placemanager_utils.h b/tests/auto/placemanager_utils/placemanager_utils.h new file mode 100644 index 0000000..982bd85 --- /dev/null +++ b/tests/auto/placemanager_utils/placemanager_utils.h @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PLACEMANAGER_UTILS_H +#define PLACEMANAGER_UTILS_H + +#include +#include +#include +#include + +#ifndef WAIT_UNTIL +#define WAIT_UNTIL(__expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 25000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + } while (0) +#endif + +QT_BEGIN_NAMESPACE + +class QPlaceManager; +class QPlace; +class QPlaceSearchResult; +class QPlaceSearchRequest; +class QPlaceCategory; +class QPlaceContentRequest; +class QPlaceMatchRequest; + +QT_END_NAMESPACE + +class PlaceManagerUtils : public QObject +{ + Q_OBJECT +public: + PlaceManagerUtils(QObject *parent = 0); + + static bool doSavePlace(QPlaceManager *manager, + const QPlace &place, + QPlaceReply::Error expectedError = QPlaceReply::NoError, + QString *placeId = 0); + + static void doSavePlaces(QPlaceManager *manager, QList &places); + + //sets the id for saved places + static void doSavePlaces(QPlaceManager *manager, const QList &places); + + static bool doSearch(QPlaceManager *manager, const QPlaceSearchRequest &request, + QList *results, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool doSearch(QPlaceManager *manager, const QPlaceSearchRequest &request, + QList *results, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool doSearchSuggestions(QPlaceManager *manager, + const QPlaceSearchRequest &request, + QStringList *results, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool doRemovePlace(QPlaceManager *manager, const QPlace &place, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool doFetchDetails(QPlaceManager *manager, + QString placeId, + QPlace *place, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool doInitializeCategories(QPlaceManager *manager, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool doSaveCategory(QPlaceManager *manager, + const QPlaceCategory &category, + const QString &parentId, + QPlaceReply::Error expectedError = QPlaceReply::NoError, + QString *categoryId = 0); + + static bool doRemoveCategory(QPlaceManager *manager, const QPlaceCategory &category, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool doFetchCategory(QPlaceManager *manager, + const QString &categoryId, + QPlaceCategory *category, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool doFetchContent(QPlaceManager *manager, + const QPlaceContentRequest &request, + QPlaceContent::Collection *results, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool doMatch(QPlaceManager *manager, + const QPlaceMatchRequest &request, + QList *places, + QPlaceReply::Error expectedError = QPlaceReply::NoError); + + static bool checkSignals(QPlaceReply *reply, QPlaceReply::Error expectedError, + QPlaceManager *manager); + + static bool compare(const QList &actualResults, + const QList &expectedResults); + + static void setVisibility(QListplaces, QLocation::Visibility visibility); + + static const int Timeout; + +protected: + bool doSavePlace(const QPlace &place, + QPlaceReply::Error expectedError = QPlaceReply::NoError, + QString *placeId = 0) { + return doSavePlace(placeManager, place, expectedError, placeId); + } + + void doSavePlaces(QList &places) { + return doSavePlaces(placeManager, places); + } + + void doSavePlaces(const QList &places) { + return doSavePlaces(placeManager, places); + } + + bool doRemovePlace(const QPlace &place, + QPlaceReply::Error expectedError = QPlaceReply::NoError) + { + return doRemovePlace(placeManager, place, expectedError); + } + + bool doSearch(const QPlaceSearchRequest &request, + QList *results, + QPlaceReply::Error expectedError = QPlaceReply::NoError) { + return doSearch(placeManager, request, results,expectedError); + } + + bool doSearchSuggestions(const QPlaceSearchRequest &request, + QStringList *results, + QPlaceReply::Error expectedError) { + return doSearchSuggestions(placeManager, request, results, expectedError); + } + + bool doFetchDetails(QString placeId, + QPlace *place, + QPlaceReply::Error expectedError = QPlaceReply::NoError) { + return doFetchDetails(placeManager, placeId, place, expectedError); + } + + bool doInitializeCategories(QPlaceReply::Error expectedError = QPlaceReply::NoError) { + return doInitializeCategories(placeManager, expectedError); + } + + bool doSaveCategory(const QPlaceCategory &category, + QPlaceReply::Error expectedError = QPlaceReply::NoError, + QString *categoryId = 0) { + return doSaveCategory(placeManager, category, QString(), + expectedError,categoryId); + } + + bool doSaveCategory(const QPlaceCategory &category, + const QString &parentId, + QPlaceReply::Error expectedError = QPlaceReply::NoError, + QString *categoryId = 0) { + return doSaveCategory(placeManager, category, parentId, + expectedError, categoryId); + } + + bool doRemoveCategory(const QPlaceCategory &category, + QPlaceReply::Error expectedError = QPlaceReply::NoError) + { + return doRemoveCategory(placeManager, category, expectedError); + } + + bool doFetchCategory(const QString &categoryId, + QPlaceCategory *category, + QPlaceReply::Error expectedError = QPlaceReply::NoError) { + return doFetchCategory(placeManager, categoryId, + category, expectedError); + } + + bool doFetchContent(const QPlaceContentRequest &request, + QPlaceContent::Collection *results, + QPlaceReply::Error expectedError = QPlaceReply::NoError) + { + return doFetchContent(placeManager, request, results, expectedError); + } + + bool doMatch(const QPlaceMatchRequest &request, + QList *places, + QPlaceReply::Error expectedError = QPlaceReply::NoError) { + return doMatch(placeManager, request, + places, expectedError); + } + + bool checkSignals(QPlaceReply *reply, QPlaceReply::Error expectedError) { + return checkSignals(reply, expectedError, placeManager); + } + + QPlaceManager *placeManager; +}; + +#endif + diff --git a/tests/auto/placesplugin_unsupported/placesplugin.json b/tests/auto/placesplugin_unsupported/placesplugin.json new file mode 100644 index 0000000..6749962 --- /dev/null +++ b/tests/auto/placesplugin_unsupported/placesplugin.json @@ -0,0 +1,8 @@ +{ + "Keys": ["test.places.unsupported"], + "Provider": "test.places.unsupported", + "Version": 1, + "Experimental": true, + "Features": [ + ] +} diff --git a/tests/auto/placesplugin_unsupported/placesplugin_unsupported.pro b/tests/auto/placesplugin_unsupported/placesplugin_unsupported.pro new file mode 100644 index 0000000..65c6a39 --- /dev/null +++ b/tests/auto/placesplugin_unsupported/placesplugin_unsupported.pro @@ -0,0 +1,14 @@ +TARGET = qtgeoservices_placesplugin_unsupported +QT += location + +PLUGIN_TYPE = geoservices +PLUGIN_CLASS_NAME = UnsupportedPlacesGeoServicePlugin +PLUGIN_EXTENDS = - +load(qt_plugin) + +HEADERS += qgeoserviceproviderplugin_test.h + +SOURCES += qgeoserviceproviderplugin_test.cpp + +OTHER_FILES += \ + placesplugin.json diff --git a/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.cpp b/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.cpp new file mode 100644 index 0000000..f94e52c --- /dev/null +++ b/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoserviceproviderplugin_test.h" + +#include +#include + +QGeoServiceProviderFactoryTest::QGeoServiceProviderFactoryTest() +{ +} + +QGeoServiceProviderFactoryTest::~QGeoServiceProviderFactoryTest() +{ +} + +QPlaceManagerEngine *QGeoServiceProviderFactoryTest::createPlaceManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const +{ + Q_UNUSED(error); + Q_UNUSED(errorString); + + return new QPlaceManagerEngine(parameters); +} diff --git a/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.h b/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.h new file mode 100644 index 0000000..11c30d2 --- /dev/null +++ b/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDER_TEST_H +#define QGEOSERVICEPROVIDER_TEST_H + +#include + +QT_USE_NAMESPACE + +class QGeoServiceProviderFactoryTest : public QObject, public QGeoServiceProviderFactory +{ + Q_OBJECT + Q_INTERFACES(QGeoServiceProviderFactory) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0" + FILE "placesplugin.json") + +public: + QGeoServiceProviderFactoryTest(); + ~QGeoServiceProviderFactoryTest(); + + QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; +}; + +#endif + + diff --git a/tests/auto/positionplugin/plugin.cpp b/tests/auto/positionplugin/plugin.cpp new file mode 100644 index 0000000..919549d --- /dev/null +++ b/tests/auto/positionplugin/plugin.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class DummySource : public QGeoPositionInfoSource +{ + Q_OBJECT + +public: + DummySource(QObject *parent=0); + ~DummySource(); + + void startUpdates(); + void stopUpdates(); + void requestUpdate(int timeout=5000); + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const; + PositioningMethods supportedPositioningMethods() const; + + void setUpdateInterval(int msec); + int minimumUpdateInterval() const; + Error error() const; + +private: + QTimer *timer; + QTimer *timeoutTimer; + QTimer *singleTimer; + QGeoPositionInfo lastPosition; + QDateTime lastUpdateTime; + +private slots: + void updatePosition(); + void doTimeout(); +}; + +DummySource::DummySource(QObject *parent) : + QGeoPositionInfoSource(parent), + timer(new QTimer(this)), + timeoutTimer(new QTimer(this)), + singleTimer(new QTimer(this)), + lastPosition(QGeoCoordinate(0,0), QDateTime::currentDateTime()) +{ + timer->setInterval(1000); + connect(timer, SIGNAL(timeout()), + this, SLOT(updatePosition())); + connect(singleTimer, SIGNAL(timeout()), + this, SLOT(updatePosition())); + connect(timeoutTimer, SIGNAL(timeout()), + this, SLOT(doTimeout())); +} + +QGeoPositionInfoSource::Error DummySource::error() const +{ + return QGeoPositionInfoSource::NoError; +} + + +void DummySource::setUpdateInterval(int msec) +{ + if (msec == 0) { + timer->setInterval(1000); + } else if (msec < 1000) { + msec = 1000; + timer->setInterval(msec); + } else { + timer->setInterval(msec); + } + + QGeoPositionInfoSource::setUpdateInterval(msec); +} + +int DummySource::minimumUpdateInterval() const +{ + return 1000; +} + +QGeoPositionInfo DummySource::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +{ + Q_UNUSED(fromSatellitePositioningMethodsOnly); + return lastPosition; +} + +QGeoPositionInfoSource::PositioningMethods DummySource::supportedPositioningMethods() const +{ + return QGeoPositionInfoSource::AllPositioningMethods; +} + +void DummySource::startUpdates() +{ + timer->start(); +} + +void DummySource::stopUpdates() +{ + timer->stop(); +} + +void DummySource::requestUpdate(int timeout) +{ + if (timeout == 0) + timeout = 5000; + if (timeout < 0) + timeout = 0; + + timeoutTimer->setInterval(timeout); + timeoutTimer->start(); + + if (timer->isActive()) { + timer->stop(); + timer->start(); + } + + singleTimer->setInterval(1000); + singleTimer->start(); +} + +DummySource::~DummySource() +{} + +void DummySource::updatePosition() +{ + timeoutTimer->stop(); + singleTimer->stop(); + + const QDateTime now = QDateTime::currentDateTime(); + + QGeoCoordinate coord(lastPosition.coordinate().latitude() + 0.1, + lastPosition.coordinate().longitude() + 0.1); + + QGeoPositionInfo info(coord, now); + info.setAttribute(QGeoPositionInfo::Direction, lastPosition.coordinate().azimuthTo(coord)); + if (lastUpdateTime.isValid()) { + double speed = lastPosition.coordinate().distanceTo(coord) / lastUpdateTime.msecsTo(now); + info.setAttribute(QGeoPositionInfo::GroundSpeed, 1000 * speed); + } + + lastUpdateTime = now; + lastPosition = info; + emit positionUpdated(info); +} + +void DummySource::doTimeout() +{ + timeoutTimer->stop(); + singleTimer->stop(); + emit updateTimeout(); +} + + +class QGeoPositionInfoSourceFactoryTest : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) + +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryTest::positionInfoSource(QObject *parent) +{ + return new DummySource(parent); +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryTest::satelliteInfoSource(QObject *parent) +{ + Q_UNUSED(parent) + // not implemented + return 0; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryTest::areaMonitor(QObject* parent) +{ + Q_UNUSED(parent) + return 0; +} + +#include "plugin.moc" diff --git a/tests/auto/positionplugin/plugin.json b/tests/auto/positionplugin/plugin.json new file mode 100644 index 0000000..68acade --- /dev/null +++ b/tests/auto/positionplugin/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["test.source"], + "Provider": "test.source", + "Position": true, + "Satellite": false, + "Monitor": false, + "Priority": 0, + "Testable": true +} diff --git a/tests/auto/positionplugin/positionplugin.pro b/tests/auto/positionplugin/positionplugin.pro new file mode 100644 index 0000000..dd04e7f --- /dev/null +++ b/tests/auto/positionplugin/positionplugin.pro @@ -0,0 +1,12 @@ +TARGET = qtposition_testplugin +QT += positioning + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = TestPositionPlugin +PLUGIN_EXTENDS = - +load(qt_plugin) + +SOURCES += plugin.cpp + +OTHER_FILES += \ + plugin.json diff --git a/tests/auto/positionplugintest/positionplugintest.pro b/tests/auto/positionplugintest/positionplugintest.pro new file mode 100644 index 0000000..4602be7 --- /dev/null +++ b/tests/auto/positionplugintest/positionplugintest.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_positionplugin + +SOURCES += tst_positionplugin.cpp + +CONFIG -= app_bundle + +QT += positioning testlib diff --git a/tests/auto/positionplugintest/tst_positionplugin.cpp b/tests/auto/positionplugintest/tst_positionplugin.cpp new file mode 100644 index 0000000..34d0509 --- /dev/null +++ b/tests/auto/positionplugintest/tst_positionplugin.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QGeoPositionInfo) + +class tst_PositionPlugin : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + + void availableSources(); + void create(); + void getUpdates(); +}; + +void tst_PositionPlugin::initTestCase() +{ + /* + * Set custom path since CI doesn't install test plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif + qRegisterMetaType(); +} + +void tst_PositionPlugin::availableSources() +{ + QVERIFY(QGeoPositionInfoSource::availableSources().contains("test.source")); + QVERIFY(!QGeoSatelliteInfoSource::availableSources().contains("test.source")); + QVERIFY(!QGeoAreaMonitorSource::availableSources().contains("test.source")); +} + +void tst_PositionPlugin::create() +{ + QGeoPositionInfoSource *src = 0; + src = QGeoPositionInfoSource::createSource("test.source", 0); + QVERIFY(src != 0); + + QVERIFY(src->minimumUpdateInterval() == 1000); + + src = QGeoPositionInfoSource::createSource("invalid source that will never exist", 0); + QVERIFY(src == 0); + + QGeoSatelliteInfoSource *ssrc = 0; + ssrc = QGeoSatelliteInfoSource::createSource("test.source", 0); + QVERIFY(ssrc == 0); +} + +void tst_PositionPlugin::getUpdates() +{ + QGeoPositionInfoSource *src = QGeoPositionInfoSource::createSource("test.source", 0); + src->setUpdateInterval(1000); + + QSignalSpy spy(src, SIGNAL(positionUpdated(QGeoPositionInfo))); + src->startUpdates(); + QTest::qWait(1500); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy[0].size(), 1); + + QGeoPositionInfo info = qvariant_cast(spy[0][0]); + QCOMPARE(info.coordinate().latitude(), 0.1); + QCOMPARE(info.coordinate().longitude(), 0.1); +} + + + +QTEST_GUILESS_MAIN(tst_PositionPlugin) +#include "tst_positionplugin.moc" diff --git a/tests/auto/qgeoaddress/qgeoaddress.pro b/tests/auto/qgeoaddress/qgeoaddress.pro new file mode 100644 index 0000000..e12b9e1 --- /dev/null +++ b/tests/auto/qgeoaddress/qgeoaddress.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeoaddress + +SOURCES += tst_qgeoaddress.cpp + +QT += positioning testlib diff --git a/tests/auto/qgeoaddress/tst_qgeoaddress.cpp b/tests/auto/qgeoaddress/tst_qgeoaddress.cpp new file mode 100644 index 0000000..7b012f1 --- /dev/null +++ b/tests/auto/qgeoaddress/tst_qgeoaddress.cpp @@ -0,0 +1,559 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QGeoAddress : public QObject +{ + Q_OBJECT + +public: + tst_QGeoAddress(); + +private Q_SLOTS: + void constructorTest(); + void textTest(); +//TODO: there are various field we don't have yet in QGeoAddress +// will need to either remove or enable these tests +// void additionalDataTest(); +// void alternativeAttributesTest(); + void cityTest(); + void countryCodeTest(); + void countryTest(); + void countyTest(); + void districtTest(); +// void floorTest(); +// void houseNumberTest(); +// void labelTest(); + void postalCodeTest(); + void stateTest(); + void streetTest(); +// void suiteTest(); + void generatedText(); + void generatedText_data(); + void operatorsTest(); + void emptyClearTest(); +}; + +tst_QGeoAddress::tst_QGeoAddress() +{ +} + +void tst_QGeoAddress::constructorTest() +{ + QGeoAddress testObj; + + testObj.setStreet("testId"); + QGeoAddress *testObjPtr = new QGeoAddress(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + delete testObjPtr; +} + +void tst_QGeoAddress::textTest() +{ + QGeoAddress address; + QVERIFY(address.text().isEmpty()); + address.setText(QStringLiteral("123 Fake Street\nSpringfield")); + QCOMPARE(address.text(), QStringLiteral("123 Fake Street\nSpringfield")); +} + +void tst_QGeoAddress::cityTest() +{ + QGeoAddress testObj; + QVERIFY2(testObj.city() == QString(), "Wrong default value"); + testObj.setCity("testText"); + QVERIFY2(testObj.city() == "testText", "Wrong value returned"); +} + +void tst_QGeoAddress::countryCodeTest() +{ + QGeoAddress testObj; + QVERIFY2(testObj.countryCode() == QString(), "Wrong default value"); + testObj.setCountryCode("testText"); + QVERIFY2(testObj.countryCode() == "testText", "Wrong value returned"); +} + +void tst_QGeoAddress::countryTest() +{ + QGeoAddress testObj; + QVERIFY2(testObj.country() == QString(), "Wrong default value"); + testObj.setCountry("testText"); + QVERIFY2(testObj.country() == "testText", "Wrong value returned"); +} + +void tst_QGeoAddress::countyTest() +{ + QGeoAddress testObj; + QVERIFY2(testObj.county() == QString(), "Wrong default value"); + testObj.setCounty("testText"); + QVERIFY2(testObj.county() == "testText", "Wrong value returned"); +} + +void tst_QGeoAddress::districtTest() +{ + QGeoAddress testObj; + QVERIFY2(testObj.district() == QString(), "Wrong default value"); + testObj.setDistrict("testText"); + QVERIFY2(testObj.district() == "testText", "Wrong value returned"); +} + +// TODO: currently don't have floor in QGeoAddress +//void tst_QGeoAddress::floorTest() +//{ +// QGeoAddress testObj; +// QVERIFY2(testObj.floor() == QString(), "Wrong default value"); +// testObj.setFloor("testText"); +// QVERIFY2(testObj.floor() == "testText", "Wrong value returned"); +//} + +//TODO: Atm not sure if we will have house number in API. +//void tst_QGeoAddress::houseNumberTest() +//{ +// QGeoAddress testObj; +// QVERIFY2(testObj.houseNumber() == QString(), "Wrong default value"); +// testObj.setHouseNumber("testText"); +// QVERIFY2(testObj.houseNumber() == "testText", "Wrong value returned"); +//} + +//void tst_QGeoAddress::labelTest() +//{ +// QGeoAddress testObj; +// QVERIFY2(testObj.label() == QString(), "Wrong default value"); +// testObj.setLabel("testText"); +// QVERIFY2(testObj.label() == "testText", "Wrong value returned"); +//} + +void tst_QGeoAddress::postalCodeTest() +{ + QGeoAddress testObj; + QVERIFY2(testObj.postalCode() == QString(), "Wrong default value"); + testObj.setPostalCode("testText"); + QVERIFY2(testObj.postalCode() == "testText", "Wrong value returned"); +} + +void tst_QGeoAddress::stateTest() +{ + QGeoAddress testObj; + QVERIFY2(testObj.state() == QString(), "Wrong default value"); + testObj.setState("testText"); + QVERIFY2(testObj.state() == "testText", "Wrong value returned"); +} + +void tst_QGeoAddress::streetTest() +{ + QGeoAddress testObj; + QVERIFY2(testObj.street() == QString(), "Wrong default value"); + testObj.setStreet("testText"); + QVERIFY2(testObj.street() == "testText", "Wrong value returned"); +} + +void tst_QGeoAddress::generatedText() +{ + QFETCH(QString, countryCode); + QFETCH(QString, expectedPostalCodeOnly); + QFETCH(QString, expectedFullAddress); + + QGeoAddress streetOnly; + streetOnly.setStreet("street"); + streetOnly.setCountryCode(countryCode); + + QCOMPARE(streetOnly.text(), QStringLiteral("street")); + + QGeoAddress cityOnly; + cityOnly.setCity("city"); + cityOnly.setCountryCode(countryCode); + if (countryCode == QLatin1String("CYM") || countryCode == QLatin1String("IRL")) + QCOMPARE(cityOnly.text(), QString()); + else + QCOMPARE(cityOnly.text(), QStringLiteral("city")); + + QGeoAddress postalCodeOnly; + postalCodeOnly.setPostalCode("postcode"); + postalCodeOnly.setCountryCode(countryCode); + QCOMPARE(postalCodeOnly.text(), expectedPostalCodeOnly); + + QGeoAddress fullAddress; + fullAddress.setStreet("street"); + fullAddress.setDistrict("district"); + fullAddress.setPostalCode("postcode"); + fullAddress.setCity("city"); + fullAddress.setState("state"); + fullAddress.setCountry("country"); + fullAddress.setCountryCode(countryCode); + + QCOMPARE(fullAddress.text(), expectedFullAddress); +} + +void tst_QGeoAddress::generatedText_data() +{ + QTest::addColumn("countryCode"); + QTest::addColumn("expectedPostalCodeOnly"); + QTest::addColumn("expectedFullAddress"); + + QTest::newRow("Albania") << QString::fromLatin1("ALB") + << QString::fromLatin1("postcode") /* postal code only */ + << QString::fromLatin1("street
" /* full address */ + "postcode, city
" + "country"); + + QTest::newRow("Andorra") << QString::fromLatin1("AND") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("United Arab Emirates") << QString::fromLatin1("ARE") + << QString() + << QString::fromLatin1("street
" + "district city
" + "country"); + QTest::newRow("Australia") << QString::fromLatin1("AUS") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district state postcode
" + "country"); + QTest::newRow("Austria") << QString::fromLatin1("AUT") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("Bahamas") << QString::fromLatin1("BHS") + << QString() + << QString::fromLatin1("street
" + "district city
" + "country"); + QTest::newRow("Bahrain") << QString::fromLatin1("BHR") + << QString() + << QString::fromLatin1("street
" + "district, city, state
" + "country"); + QTest::newRow("Brazil") << QString::fromLatin1("BRA") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district city-state postcode
" + "country"); + QTest::newRow("Brunei Darussalam") << QString::fromLatin1("BRN") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district city postcode
" + "country"); + QTest::newRow("Canada") << QString::fromLatin1("CAN") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city, state postcode
" + "country"); + QTest::newRow("China") << QString::fromLatin1("CHN") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street, city
" + "postcode state
" + "country"); + QTest::newRow("Chile") << QString::fromLatin1("CHL") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode district, city, state
" + "country"); + QTest::newRow("Cayman Islands") << QString::fromLatin1("CYM") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "state postcode
" + "country"); + QTest::newRow("France") << QString::fromLatin1("FRA") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + + QTest::newRow("United Kingdom") << QString::fromLatin1("GBR") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district, city, postcode
" + "country"); + QTest::newRow("Gibraltar") << QString::fromLatin1("GIB") + << QString() + << QString::fromLatin1("street
" + "city
" + "country"); + QTest::newRow("Guadeloupe") << QString::fromLatin1("GLP") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("French Guiana") << QString::fromLatin1("GUF") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("Hong Kong") << QString::fromLatin1("HKG") + << QString() + << QString::fromLatin1("street
" + "district
" + "city"); + QTest::newRow("India") << QString::fromLatin1("IND") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city postcode state
" + "country"); + QTest::newRow("Indonesia") << QString::fromLatin1("IDN") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city, postcode
" + "country"); + QTest::newRow("Ireland") << QString::fromLatin1("IRL") + << QString() + << QString::fromLatin1("street
" + "district, state
" + "country"); + QTest::newRow("Italy") << QString::fromLatin1("ITA") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("Jersey") << QString::fromLatin1("JEY") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city, postcode
" + "country"); + QTest::newRow("Jordan") << QString::fromLatin1("JOR") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district city postcode
" + "country"); + QTest::newRow("Kuwait") << QString::fromLatin1("KWT") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode, district, city
" + "country"); + QTest::newRow("Latvia") << QString::fromLatin1("LVA") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city, postcode
" + "country"); + QTest::newRow("Lebanon") << QString::fromLatin1("LBN") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district city postcode
" + "country"); + QTest::newRow("Luxembourg") << QString::fromLatin1("LUX") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("Malta") << QString::fromLatin1("MLT") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city postcode
" + "country"); + QTest::newRow("Monaco") << QString::fromLatin1("MCO") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("Mexico") << QString::fromLatin1("MEX") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district
" + "postcode city, state
" + "country"); + QTest::newRow("Martinique") << QString::fromLatin1("MTQ") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode, city
" + "country"); + QTest::newRow("Malaysia") << QString::fromLatin1("MYS") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "state
" + "country"); + QTest::newRow("New Zealand") << QString::fromLatin1("NZL") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district city postcode
" + "country"); + QTest::newRow("Oman") << QString::fromLatin1("OMN") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district, postcode, city, country"); + QTest::newRow("Puerto Rico") << QString::fromLatin1("PRI") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "district, city, state, postcode
" + "country"); + QTest::newRow("Qatar") << QString::fromLatin1("QAT") + << QString() + << QString::fromLatin1("street
" + "district city, country"); + QTest::newRow("Reunion") << QString::fromLatin1("REU") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("Russian Federation") << QString::fromLatin1("RUS") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("Saudi Arabia") << QString::fromLatin1("SAU") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street district
" + "city postcode
" + "country"); + QTest::newRow("Singapore") << QString::fromLatin1("SGP") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city postcode
" + "country"); + QTest::newRow("Marino") << QString::fromLatin1("SMR") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("Taiwan") << QString::fromLatin1("TWN") + << QString() + << QString::fromLatin1("street, district, city
" + "country"); + QTest::newRow("Thailand") << QString::fromLatin1("THA") + << QString("postcode") + << QString::fromLatin1("street
" + "district, city postcode
" + "country"); + QTest::newRow("Turkey") << QString::fromLatin1("TUR") + << QString("postcode") + << QString::fromLatin1("street
" + "postcode district, city
" + "country"); + QTest::newRow("Ukraine") << QString::fromLatin1("UKR") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city postcode
" + "country"); + QTest::newRow("United States") << QString::fromLatin1("USA") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city, state postcode
" + "country"); + QTest::newRow("Virgin Islands, US") << QString::fromLatin1("VIR") + << QString("postcode") + << QString::fromLatin1("street
" + "city, state postcode
" + "country"); + QTest::newRow("Vatican City State") << QString::fromLatin1("VAT") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); + QTest::newRow("Venezuela") << QString::fromLatin1("VEN") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "city postcode, state
" + "country"); + QTest::newRow("South Africa") << QString::fromLatin1("ZAF") + << QString() + << QString::fromLatin1("street
" + "district, city
" + "country"); + QTest::newRow("Finland") << QString::fromLatin1("FIN") + << QString::fromLatin1("postcode") + << QString::fromLatin1("street
" + "postcode city
" + "country"); +} + +// TODO: curenlty we don't have suite in QGeoAddress +// will need to either remove or enable +//void tst_QGeoAddress::suiteTest() +//{ +// QGeoAddress testObj; +// QVERIFY2(testObj.suite() == QString(), "Wrong default value"); +// testObj.setSuite("testText"); +// QVERIFY2(testObj.suite() == "testText", "Wrong value returned"); +//} + +void tst_QGeoAddress::operatorsTest() +{ + QGeoAddress testObj; + testObj.setStreet("testValue"); + QGeoAddress testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setCountry("testValue2"); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +void tst_QGeoAddress::emptyClearTest() +{ + QGeoAddress testObj; + QVERIFY(testObj.isEmpty()); + + testObj.setCountry(QStringLiteral("country")); + QVERIFY(!testObj.isEmpty()); + testObj.clear(); + + testObj.setCountryCode(QStringLiteral("countryCode")); + QVERIFY(!testObj.isEmpty()); + testObj.clear(); + + testObj.setState(QStringLiteral("state")); + QVERIFY(!testObj.isEmpty()); + testObj.clear(); + + testObj.setCounty(QStringLiteral("county")); + QVERIFY(!testObj.isEmpty()); + testObj.clear(); + + testObj.setCity(QStringLiteral("city")); + QVERIFY(!testObj.isEmpty()); + testObj.clear(); + + testObj.setDistrict(QStringLiteral("district")); + QVERIFY(!testObj.isEmpty()); + testObj.clear(); + + testObj.setPostalCode(QStringLiteral("postalCode")); + QVERIFY(!testObj.isEmpty()); + testObj.clear(); + + testObj.setStreet(QStringLiteral("street")); + QVERIFY(!testObj.isEmpty()); + testObj.clear(); + + testObj.setText(QStringLiteral("formatted address")); + QVERIFY(!testObj.isEmpty()); + testObj.clear(); + + QVERIFY(testObj.isEmpty()); +} + +QTEST_APPLESS_MAIN(tst_QGeoAddress) + +#include "tst_qgeoaddress.moc" diff --git a/tests/auto/qgeoareamonitor/logfilepositionsource.cpp b/tests/auto/qgeoareamonitor/logfilepositionsource.cpp new file mode 100644 index 0000000..a613d6e --- /dev/null +++ b/tests/auto/qgeoareamonitor/logfilepositionsource.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "logfilepositionsource.h" + +LogFilePositionSource::LogFilePositionSource(QObject *parent) + : QGeoPositionInfoSource(parent), + logFile(new QFile(this)), + timer(new QTimer(this)) +{ + connect(timer, SIGNAL(timeout()), this, SLOT(readNextPosition())); + + logFile->setFileName(QFINDTESTDATA("simplelog.txt")); + if (!logFile->open(QIODevice::ReadOnly)) + qWarning() << "Error: cannot open source file" << logFile->fileName(); +} + +QGeoPositionInfo LogFilePositionSource::lastKnownPosition(bool /*fromSatellitePositioningMethodsOnly*/) const +{ + return lastPosition; +} + +LogFilePositionSource::PositioningMethods LogFilePositionSource::supportedPositioningMethods() const +{ + return AllPositioningMethods; +} + +int LogFilePositionSource::minimumUpdateInterval() const +{ + return 200; +} + +void LogFilePositionSource::startUpdates() +{ + int interval = updateInterval(); + if (interval < minimumUpdateInterval()) + interval = minimumUpdateInterval(); + + timer->start(interval); +} + +void LogFilePositionSource::stopUpdates() +{ + timer->stop(); +} + +void LogFilePositionSource::requestUpdate(int /*timeout*/) +{ + // For simplicity, ignore timeout - assume that if data is not available + // now, no data will be added to the file later + if (logFile->canReadLine()) + readNextPosition(); + else + emit updateTimeout(); +} + +void LogFilePositionSource::readNextPosition() +{ + QByteArray line = logFile->readLine().trimmed(); + if (!line.isEmpty()) { + QList data = line.split(' '); + double latitude; + double longitude; + bool hasLatitude = false; + bool hasLongitude = false; + QDateTime timestamp = QDateTime::fromString(QString(data.value(0)), Qt::ISODate); + latitude = data.value(1).toDouble(&hasLatitude); + longitude = data.value(2).toDouble(&hasLongitude); + + if (hasLatitude && hasLongitude && timestamp.isValid()) { + QGeoCoordinate coordinate(latitude, longitude); + QGeoPositionInfo info(coordinate, timestamp); + if (info.isValid()) { + lastPosition = info; + emit positionUpdated(info); + } + } + } +} + +QGeoPositionInfoSource::Error LogFilePositionSource::error() const +{ + return QGeoPositionInfoSource::NoError; +} diff --git a/tests/auto/qgeoareamonitor/logfilepositionsource.h b/tests/auto/qgeoareamonitor/logfilepositionsource.h new file mode 100644 index 0000000..3768d75 --- /dev/null +++ b/tests/auto/qgeoareamonitor/logfilepositionsource.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LOGFILEPOSITIONSOURCE_H +#define LOGFILEPOSITIONSOURCE_H + +#include + +QT_BEGIN_NAMESPACE +class QFile; +class QTimer; +QT_END_NAMESPACE + +class LogFilePositionSource : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + LogFilePositionSource(QObject *parent = 0); + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + + PositioningMethods supportedPositioningMethods() const; + int minimumUpdateInterval() const; + Error error() const; + +public slots: + virtual void startUpdates(); + virtual void stopUpdates(); + + virtual void requestUpdate(int timeout = 5000); + +private slots: + void readNextPosition(); + +private: + QFile *logFile; + QTimer *timer; + QGeoPositionInfo lastPosition; +}; + +#endif diff --git a/tests/auto/qgeoareamonitor/qgeoareamonitor.pro b/tests/auto/qgeoareamonitor/qgeoareamonitor.pro new file mode 100644 index 0000000..d084df6 --- /dev/null +++ b/tests/auto/qgeoareamonitor/qgeoareamonitor.pro @@ -0,0 +1,14 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeoareamonitor + +SOURCES += tst_qgeoareamonitor.cpp \ + logfilepositionsource.cpp + +HEADERS += logfilepositionsource.h + +OTHER_FILES += *.txt + +CONFIG -= app_bundle + +QT += positioning testlib diff --git a/tests/auto/qgeoareamonitor/simplelog.txt b/tests/auto/qgeoareamonitor/simplelog.txt new file mode 100644 index 0000000..5a14fb8 --- /dev/null +++ b/tests/auto/qgeoareamonitor/simplelog.txt @@ -0,0 +1,87 @@ +2009-08-24T22:24:34 -27.54 153.090718 +2009-08-24T22:24:35 -27.55 153.090718 +2009-08-24T22:24:36 -27.56 153.090718 +2009-08-24T22:24:37 -27.57 153.090718 +2009-08-24T22:24:38 -27.58 153.090783 +2009-08-24T22:24:39 -27.59 153.090845 +2009-08-24T22:24:40 -27.60 153.090908 +2009-08-24T22:24:41 -27.61 153.090971 +2009-08-24T22:24:42 -27.62 153.091036 +2009-08-24T22:24:43 -27.63 153.091102 +2009-08-24T22:24:44 -27.64 153.091167 +2009-08-24T22:24:45 -27.65 153.091232 +2009-08-24T22:24:46 -27.65 153.091298 +2009-08-24T22:24:47 -27.65 153.091366 +2009-08-24T22:24:48 -27.65 153.091435 +2009-08-24T22:24:49 -27.66 153.091507 +2009-08-24T22:24:50 -27.67 153.091581 +2009-08-24T22:24:51 -27.68 153.091654 +2009-08-24T22:24:52 -27.69 153.091729 +2009-08-24T22:24:53 -27.70 153.091800 +2009-08-24T22:24:54 -27.71 153.091870 +2009-08-24T22:24:55 -27.72 153.091940 +2009-08-24T22:24:56 -27.73 153.092010 +2009-08-24T22:24:57 -27.74 153.092078 +2009-08-24T22:24:58 -27.75 153.092144 +2009-08-24T22:24:59 -27.78 153.092218 +2009-08-24T22:25:00 -27.79 153.092308 +2009-08-24T22:25:01 -27.80 153.092415 +2009-08-24T22:25:02 -27.81 153.092530 +2009-08-24T22:25:03 -27.82 153.092648 +2009-08-24T22:25:04 -27.83 153.092763 +2009-08-24T22:25:05 -27.84 153.092879 +2009-08-24T22:25:06 -27.85 153.092990 +2009-08-24T22:25:07 -27.84 153.093099 +2009-08-24T22:25:08 -27.83 153.093204 +2009-08-24T22:25:09 -27.82 153.093303 +2009-08-24T22:25:10 -27.81 153.093396 +2009-08-24T22:25:11 -27.80 153.093484 +2009-08-24T22:25:12 -27.79 153.093568 +2009-08-24T22:25:13 -27.78 153.093647 +2009-08-24T22:25:14 -27.77 153.093727 +2009-08-24T22:25:15 -27.76 153.093810 +2009-08-24T22:25:16 -27.75 153.093896 +2009-08-24T22:25:17 -27.74 153.093984 +2009-08-24T22:25:18 -27.72 153.094074 +2009-08-24T22:25:19 -27.70 153.094168 +2009-08-24T22:25:20 -27.71 153.094267 +2009-08-24T22:25:21 -27.69 153.094370 +2009-08-24T22:25:22 -27.68 153.094474 +2009-08-24T22:25:23 -27.67 153.094581 +2009-08-24T22:25:24 -27.66 153.094688 +2009-08-24T22:25:25 -27.65 153.094796 +2009-08-24T22:25:26 -27.64 153.094905 +2009-08-24T22:25:27 -27.63 153.095012 +2009-08-24T22:25:28 -27.62 153.095121 +2009-08-24T22:25:29 -27.61 153.095231 +2009-08-24T22:25:30 -27.60 153.095340 +2009-08-24T22:25:31 -27.59 153.095449 +2009-08-24T22:25:32 -27.58 153.095558 +2009-08-24T22:25:33 -27.57 153.095667 +2009-08-24T22:25:34 -27.56 153.095776 +2009-08-24T22:25:35 -27.55 153.095885 +2009-08-24T22:25:36 -27.54 153.095995 +2009-08-24T22:25:37 -27.53 153.096109 +2009-08-24T22:25:38 -27.52 153.096226 +2009-08-24T22:25:39 -27.51 153.096337 +2009-08-24T22:25:40 -27.50 153.096441 +2009-08-24T22:25:41 -27.49 153.096537 +2009-08-24T22:25:42 -27.48 153.096628 +2009-08-24T22:25:43 -27.47 153.096714 +2009-08-24T22:25:44 -27.46 153.096795 +2009-08-24T22:25:45 -27.45 153.096847 +2009-08-24T22:25:46 -27.44 153.096855 +2009-08-24T22:25:47 -27.43 153.096873 +2009-08-24T22:25:48 -27.42 153.096875 +2009-08-24T22:25:49 -27.41 153.096878 +2009-08-24T22:25:50 -27.40 153.096880 +2009-08-24T22:25:51 -27.39 153.096880 +2009-08-24T22:25:52 -27.38 153.096881 +2009-08-24T22:25:53 -27.37 153.096882 +2009-08-24T22:25:54 -27.36 153.096883 +2009-08-24T22:25:55 -27.35 153.096883 +2009-08-24T22:25:56 -27.34 153.096883 +2009-08-24T22:25:57 -27.33 153.096890 +2009-08-24T22:25:58 -27.32 153.096919 +2009-08-24T22:25:59 -27.31 153.096985 +2009-08-24T22:26:00 -27.30 153.097060 diff --git a/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp b/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp new file mode 100644 index 0000000..5526198 --- /dev/null +++ b/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp @@ -0,0 +1,760 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "logfilepositionsource.h" + + +QT_USE_NAMESPACE +#define UPDATE_INTERVAL 200 + +Q_DECLARE_METATYPE(QGeoPositionInfo) +Q_DECLARE_METATYPE(QGeoAreaMonitorInfo) + +QString tst_qgeoareamonitorinfo_debug; + +void tst_qgeoareamonitorinfo_messageHandler(QtMsgType type, + const QMessageLogContext &, + const QString &msg) +{ + switch (type) { + case QtDebugMsg : + tst_qgeoareamonitorinfo_debug = msg; + break; + default: + break; + } +} + +class tst_QGeoAreaMonitorSource : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { + /* + * Set custom path since CI doesn't install plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif + qRegisterMetaType(); + qRegisterMetaType(); + } + + void init() + { + } + + void cleanup() + { + QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(obj != 0); + QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll")); + + QList list = obj->activeMonitors(); + if (list.count() > 0) { + //cleanup installed monitors + foreach (const QGeoAreaMonitorInfo& info, list) { + QVERIFY(obj->stopMonitoring(info)); + } + } + QVERIFY(obj->activeMonitors().count() == 0); + } + + void cleanupTestCase() + { + } + + void tst_monitor() + { + QGeoAreaMonitorInfo defaultMonitor; + QVERIFY(defaultMonitor.name().isEmpty()); + QVERIFY(!defaultMonitor.identifier().isEmpty()); + QCOMPARE(defaultMonitor.isPersistent(), false); + QVERIFY(!defaultMonitor.area().isValid()); + QVERIFY(!defaultMonitor.isValid()); + QCOMPARE(defaultMonitor.expiration(), QDateTime()); + QCOMPARE(defaultMonitor.notificationParameters(), QVariantMap()); + + QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(obj != 0); + QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll")); + QVERIFY(!obj->startMonitoring(defaultMonitor)); + QCOMPARE(obj->activeMonitors().count(), 0); + QVERIFY(!obj->requestUpdate(defaultMonitor, + SIGNAL(areaEntered(QGeoMonitorInfo,QGeoAreaPositionInfo)))); + delete obj; + + //copy constructor based + QGeoAreaMonitorInfo copy(defaultMonitor); + QVERIFY(copy.name().isEmpty()); + QCOMPARE(copy.identifier(), defaultMonitor.identifier()); + QVERIFY(copy == defaultMonitor); + QVERIFY(!(copy != defaultMonitor)); + QCOMPARE(copy.isPersistent(), false); + + copy.setName(QString("my name")); + QCOMPARE(copy.name(), QString("my name")); + + + QDateTime now = QDateTime::currentDateTime().addSecs(1000); //little bit in the future + copy.setExpiration(now); + QVERIFY(copy != defaultMonitor); + QCOMPARE(copy.expiration(), now); + + QCOMPARE(copy.isPersistent(), defaultMonitor.isPersistent()); + copy.setPersistent(true); + QCOMPARE(copy.isPersistent(), true); + QCOMPARE(defaultMonitor.isPersistent(), false); + copy.setPersistent(false); + + QVERIFY(copy.area() == defaultMonitor.area()); + QVERIFY(!copy.area().isValid()); + copy.setArea(QGeoCircle(QGeoCoordinate(1, 2), 4)); + QVERIFY(copy.area().isValid()); + QVERIFY(copy.area() != defaultMonitor.area()); + QVERIFY(copy.area().contains(QGeoCoordinate(1, 2))); + + QVERIFY(copy.notificationParameters().isEmpty()); + QVariantMap map; + map.insert(QString("MyKey"), QVariant(123)); + copy.setNotificationParameters(map); + QVERIFY(!copy.notificationParameters().isEmpty()); + QCOMPARE(copy.notificationParameters().value(QString("MyKey")).toInt(), 123); + QCOMPARE(defaultMonitor.notificationParameters().value(QString("MyKey")).toInt(), 0); + + QCOMPARE(defaultMonitor.identifier(), copy.identifier()); + + //assignment operator based + QGeoAreaMonitorInfo assignmentCopy; + assignmentCopy = copy; + QVERIFY(copy == assignmentCopy); + QVERIFY(assignmentCopy != defaultMonitor); + + QVERIFY(assignmentCopy.area().contains(QGeoCoordinate(1, 2))); + QCOMPARE(assignmentCopy.expiration(), now); + QCOMPARE(assignmentCopy.isPersistent(), false); + QCOMPARE(assignmentCopy.notificationParameters().value(QString("MyKey")).toInt(), 123); + QCOMPARE(defaultMonitor.identifier(), assignmentCopy.identifier()); + QCOMPARE(assignmentCopy.name(), QString("my name")); + + //validity checks for requestUpdate() + obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(obj != 0); + QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll")); + QCOMPARE(obj->activeMonitors().count(), 0); + //reference -> should work + QVERIFY(obj->requestUpdate(copy, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)))); + QCOMPARE(obj->activeMonitors().count(), 1); + //replaces areaEntered single shot + QVERIFY(obj->requestUpdate(copy, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo)))); + QCOMPARE(obj->activeMonitors().count(), 1); + //replaces areaExited single shot + QVERIFY(obj->startMonitoring(copy)); + QCOMPARE(obj->activeMonitors().count(), 1); + + + //invalid signal + QVERIFY(!obj->requestUpdate(copy, 0)); + QCOMPARE(obj->activeMonitors().count(), 1); + + //signal that doesn't exist + QVERIFY(!obj->requestUpdate(copy, SIGNAL(areaEntered(QGeoMonitor)))); + QCOMPARE(obj->activeMonitors().count(), 1); + + QVERIFY(!obj->requestUpdate(copy, "SIGNAL(areaEntered(QGeoMonitor))")); + QCOMPARE(obj->activeMonitors().count(), 1); + + //ensure that we cannot add a persistent monitor to a source + //that doesn't support persistence + QGeoAreaMonitorInfo persistenceMonitor(copy); + persistenceMonitor.setPersistent(obj->supportedAreaMonitorFeatures() & QGeoAreaMonitorSource::PersistentAreaMonitorFeature); + persistenceMonitor.setPersistent(!persistenceMonitor.isPersistent()); + + QVERIFY(!obj->requestUpdate(persistenceMonitor, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)))); + QCOMPARE(obj->activeMonitors().count(), 1); + QVERIFY(!obj->startMonitoring(persistenceMonitor)); + QCOMPARE(obj->activeMonitors().count(), 1); + + //ensure that persistence was only reason for rejection + persistenceMonitor.setPersistent(!persistenceMonitor.isPersistent()); + QVERIFY(obj->startMonitoring(persistenceMonitor)); + //persistenceMonitor is copy of already added monitor + //the last call was an update + QCOMPARE(obj->activeMonitors().count(), 1); + + delete obj; + } + + void tst_monitorValid() + { + QGeoAreaMonitorInfo mon; + QVERIFY(!mon.isValid()); + QCOMPARE(mon.name(), QString()); + QCOMPARE(mon.area().isValid(), false); + + QGeoAreaMonitorInfo mon2 = mon; + QVERIFY(!mon2.isValid()); + + QGeoShape invalidShape; + QGeoCircle emptyCircle(QGeoCoordinate(0,1), 0); + QGeoCircle validCircle(QGeoCoordinate(0,1), 1); + + //all invalid since no name set yet + mon2.setArea(invalidShape); + QVERIFY(mon2.area() == invalidShape); + QVERIFY(!mon2.isValid()); + + mon2.setArea(emptyCircle); + QVERIFY(mon2.area() == emptyCircle); + QVERIFY(!mon2.isValid()); + + mon2.setArea(validCircle); + QVERIFY(mon2.area() == validCircle); + QVERIFY(!mon2.isValid()); + + //valid since name and non-empy shape has been set + QGeoAreaMonitorInfo validMonitor("TestMonitor"); + QVERIFY(validMonitor.name() == QString("TestMonitor")); + QVERIFY(!validMonitor.isValid()); + + validMonitor.setArea(invalidShape); + QVERIFY(validMonitor.area() == invalidShape); + QVERIFY(!validMonitor.isValid()); + + validMonitor.setArea(emptyCircle); + QVERIFY(validMonitor.area() == emptyCircle); + QVERIFY(!validMonitor.isValid()); + + validMonitor.setArea(validCircle); + QVERIFY(validCircle == validMonitor.area()); + QVERIFY(validMonitor.isValid()); + } + + void tst_monitorStreaming() + { + QByteArray container; + QDataStream stream(&container, QIODevice::ReadWrite); + + QGeoAreaMonitorInfo monitor("someName"); + monitor.setArea(QGeoCircle(QGeoCoordinate(1,3), 5.4)); + QVERIFY(monitor.isValid()); + QCOMPARE(monitor.name(), QString("someName")); + + QGeoAreaMonitorInfo target; + QVERIFY(!target.isValid()); + QVERIFY(target.name().isEmpty()); + + QVERIFY(target != monitor); + + stream << monitor; + stream.device()->seek(0); + stream >> target; + + QVERIFY(target == monitor); + QVERIFY(target.isValid()); + QCOMPARE(target.name(), QString("someName")); + QVERIFY(target.area() == QGeoCircle(QGeoCoordinate(1,3), 5.4)); + } + + void tst_createDefaultSource() + { + QObject* parent = new QObject; + QGeoAreaMonitorSource* obj = QGeoAreaMonitorSource::createDefaultSource(parent); + QVERIFY(obj != 0); + QVERIFY(obj->parent() == parent); + delete obj; + + const QStringList monitors = QGeoAreaMonitorSource::availableSources(); + QVERIFY(!monitors.isEmpty()); + QVERIFY(monitors.contains(QStringLiteral("positionpoll"))); + + obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), parent); + QVERIFY(obj != 0); + QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll")); + delete parent; + + obj = QGeoAreaMonitorSource::createSource(QStringLiteral("randomNonExistingName"), 0); + QVERIFY(obj == 0); + } + + void tst_activeMonitors() + { + QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(obj != 0); + QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll")); + + LogFilePositionSource *source = new LogFilePositionSource(this); + source->setUpdateInterval(UPDATE_INTERVAL); + obj->setPositionInfoSource(source); + QCOMPARE(obj->positionInfoSource(), source); + + + QVERIFY(obj->activeMonitors().isEmpty()); + + QGeoAreaMonitorInfo mon("Monitor_Circle"); + mon.setArea(QGeoCircle(QGeoCoordinate(1,1), 1000)); + QVERIFY(obj->startMonitoring(mon)); + + QGeoAreaMonitorInfo mon2("Monitor_rectangle_below"); + QGeoRectangle r_below(QGeoCoordinate(1,1),2,2); + mon2.setArea(r_below); + QVERIFY(obj->startMonitoring(mon2)); + + QGeoAreaMonitorInfo mon3("Monitor_rectangle_above"); + QGeoRectangle r_above(QGeoCoordinate(2,1),2,2); + mon3.setArea(r_above); + QVERIFY(obj->startMonitoring(mon3)); + + QList results = obj->activeMonitors(); + QCOMPARE(results.count(), 3); + foreach (const QGeoAreaMonitorInfo& info, results) { + QVERIFY(info == mon || info == mon2 || info == mon3); + } + + results = obj->activeMonitors(QGeoShape()); + QCOMPARE(results.count(), 0); + + results = obj->activeMonitors(QGeoRectangle(QGeoCoordinate(1,1),0.2, 0.2)); + QCOMPARE(results.count(), 2); + foreach (const QGeoAreaMonitorInfo& info, results) { + QVERIFY(info == mon || info == mon2); + } + + results = obj->activeMonitors(QGeoCircle(QGeoCoordinate(1,1),1000)); + QCOMPARE(results.count(), 2); + foreach (const QGeoAreaMonitorInfo& info, results) { + QVERIFY(info == mon || info == mon2); + } + + results = obj->activeMonitors(QGeoCircle(QGeoCoordinate(2,1),1000)); + QCOMPARE(results.count(), 1); + foreach (const QGeoAreaMonitorInfo& info, results) { + QVERIFY(info == mon3); + } + + //same as above except that we use a different monitor source object instance + //all monitor objects of same type share same active monitors + QGeoAreaMonitorSource *secondObj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(secondObj != 0); + QCOMPARE(secondObj->sourceName(), QStringLiteral("positionpoll")); + + results = secondObj->activeMonitors(); + QCOMPARE(results.count(), 3); + foreach (const QGeoAreaMonitorInfo& info, results) { + QVERIFY(info == mon || info == mon2 || info == mon3); + } + + results = secondObj->activeMonitors(QGeoShape()); + QCOMPARE(results.count(), 0); + + results = secondObj->activeMonitors(QGeoRectangle(QGeoCoordinate(1,1),0.2, 0.2)); + QCOMPARE(results.count(), 2); + foreach (const QGeoAreaMonitorInfo& info, results) { + QVERIFY(info == mon || info == mon2); + } + + results = secondObj->activeMonitors(QGeoCircle(QGeoCoordinate(1,1),1000)); + QCOMPARE(results.count(), 2); + foreach (const QGeoAreaMonitorInfo& info, results) { + QVERIFY(info == mon || info == mon2); + } + + results = secondObj->activeMonitors(QGeoCircle(QGeoCoordinate(2,1),1000)); + QCOMPARE(results.count(), 1); + foreach (const QGeoAreaMonitorInfo& info, results) { + QVERIFY(info == mon3); + } + + delete obj; + delete secondObj; + } + + void tst_testExpiryTimeout() + { + QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(obj != 0); + QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll")); + + QGeoAreaMonitorSource *secondObj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(secondObj != 0); + QCOMPARE(secondObj->sourceName(), QStringLiteral("positionpoll")); + + LogFilePositionSource *source = new LogFilePositionSource(this); + source->setUpdateInterval(UPDATE_INTERVAL); + obj->setPositionInfoSource(source); + + //Singleton pattern behind QGeoAreaMonitorSource ensures same position info source + QCOMPARE(obj->positionInfoSource(), source); + QCOMPARE(secondObj->positionInfoSource(), source); + + QSignalSpy expirySpy(obj, SIGNAL(monitorExpired(QGeoAreaMonitorInfo))); + QSignalSpy expirySpy2(secondObj, SIGNAL(monitorExpired(QGeoAreaMonitorInfo))); + + QDateTime now = QDateTime::currentDateTime(); + + const int monitorCount = 4; + for (int i = 1; i <= monitorCount; i++) { + QGeoAreaMonitorInfo mon(QString::number(i)); + mon.setArea(QGeoRectangle(QGeoCoordinate(i,i), i, i)); + mon.setExpiration(now.addSecs(i*5)); + QVERIFY(mon.isValid()); + QVERIFY(obj->startMonitoring(mon)); + } + + + + QCOMPARE(obj->activeMonitors().count(), monitorCount); + QCOMPARE(secondObj->activeMonitors().count(), monitorCount); + + QGeoAreaMonitorInfo info("InvalidExpiry"); + info.setArea(QGeoRectangle(QGeoCoordinate(10,10), 1, 1 )); + QVERIFY(info.isValid()); + info.setExpiration(now.addSecs(-1000)); + QVERIFY(info.expiration() < now); + QVERIFY(!obj->startMonitoring(info)); + QCOMPARE(obj->activeMonitors().count(), monitorCount); + QVERIFY(!obj->requestUpdate(info, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)))); + QCOMPARE(obj->activeMonitors().count(), monitorCount); + + for (int i = 1; i <= monitorCount; i++) { + QTRY_VERIFY_WITH_TIMEOUT(expirySpy.count() == 1, 7000); //each expiry within 5 s + QGeoAreaMonitorInfo mon = expirySpy.takeFirst().at(0).value(); + QCOMPARE(obj->activeMonitors().count(), monitorCount-i); + QCOMPARE(mon.name(), QString::number(i)); + } + + QCOMPARE(expirySpy2.count(), monitorCount); + QCOMPARE(secondObj->activeMonitors().count(), 0); //all monitors expired + for (int i = 1; i <= monitorCount; i++) { + QGeoAreaMonitorInfo mon = expirySpy2.takeFirst().at(0).value(); + QCOMPARE(mon.name(), QString::number(i)); + } + + delete obj; + delete secondObj; + } + + void tst_enteredExitedSignal() + { + QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(obj != 0); + QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll")); + obj->setObjectName("firstObject"); + QSignalSpy enteredSpy(obj, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo))); + QSignalSpy exitedSpy(obj, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo))); + + LogFilePositionSource *source = new LogFilePositionSource(this); + source->setUpdateInterval(UPDATE_INTERVAL); + obj->setPositionInfoSource(source); + QCOMPARE(obj->positionInfoSource(), source); + + QGeoAreaMonitorSource *secondObj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(secondObj != 0); + QCOMPARE(secondObj->sourceName(), QStringLiteral("positionpoll")); + QSignalSpy enteredSpy2(secondObj, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo))); + QSignalSpy exitedSpy2(secondObj, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo))); + secondObj->setObjectName("secondObject"); + + QGeoAreaMonitorInfo infoRectangle("Rectangle"); + infoRectangle.setArea(QGeoRectangle(QGeoCoordinate(-27.65, 153.093), 0.2, 0.2)); + QVERIFY(infoRectangle.isValid()); + QVERIFY(obj->startMonitoring(infoRectangle)); + + QGeoAreaMonitorInfo infoCircle("Circle"); + infoCircle.setArea(QGeoCircle(QGeoCoordinate(-27.70, 153.093),10000)); + QVERIFY(infoCircle.isValid()); + QVERIFY(obj->startMonitoring(infoCircle)); + + QGeoAreaMonitorInfo singleShot_enter("SingleShot_on_Entered"); + singleShot_enter.setArea(QGeoRectangle(QGeoCoordinate(-27.67, 153.093), 0.2, 0.2)); + QVERIFY(singleShot_enter.isValid()); + QVERIFY(obj->requestUpdate(singleShot_enter, + SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)))); + + QGeoAreaMonitorInfo singleShot_exit("SingleShot_on_Exited"); + singleShot_exit.setArea(QGeoRectangle(QGeoCoordinate(-27.70, 153.093), 0.2, 0.2)); + QVERIFY(singleShot_exit.isValid()); + QVERIFY(obj->requestUpdate(singleShot_exit, + SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo)))); + + QVERIFY(obj->activeMonitors().count() == 4); //all monitors active + QVERIFY(secondObj->activeMonitors().count() == 4); //all monitors active + + static const int Number_Of_Entered_Events = 6; + static const int Number_Of_Exited_Events = 5; + //takes 87 (lines)*200(timeout)/1000 seconds to finish + QTRY_VERIFY_WITH_TIMEOUT(enteredSpy.count() == Number_Of_Entered_Events, 20000); + QTRY_VERIFY_WITH_TIMEOUT(exitedSpy.count() == Number_Of_Exited_Events, 20000); + QCOMPARE(enteredSpy.count(), Number_Of_Entered_Events); + QCOMPARE(exitedSpy.count(), Number_Of_Exited_Events); + + QList monitorsInExpectedEnteredEventOrder; + monitorsInExpectedEnteredEventOrder << infoRectangle << singleShot_enter << singleShot_exit + << infoCircle << infoCircle << infoRectangle; + + QList monitorsInExpectedExitedEventOrder; + monitorsInExpectedExitedEventOrder << infoRectangle << infoCircle + << singleShot_exit << infoCircle << infoRectangle; + + QList enteredEventCoordinateOrder; + enteredEventCoordinateOrder << QGeoCoordinate(-27.55, 153.090718) //infoRectangle + << QGeoCoordinate(-27.57, 153.090718) //singleshot_enter + << QGeoCoordinate(-27.60, 153.090908) //singleshot_exit + << QGeoCoordinate(-27.62, 153.091036) //infoCircle + << QGeoCoordinate(-27.78, 153.093647) //infoCircle + << QGeoCoordinate(-27.75, 153.093896);//infoRectangle + QCOMPARE(enteredEventCoordinateOrder.count(), Number_Of_Entered_Events); + QCOMPARE(monitorsInExpectedEnteredEventOrder.count(), Number_Of_Entered_Events); + + QList exitedEventCoordinateOrder; + exitedEventCoordinateOrder << QGeoCoordinate(-27.78, 153.092218) //infoRectangle + << QGeoCoordinate(-27.79, 153.092308) //infoCircle + << QGeoCoordinate(-27.81, 153.092530) //singleshot_exit + << QGeoCoordinate(-27.61, 153.095231) //infoCircle + << QGeoCoordinate(-27.54, 153.095995);//infoCircle + QCOMPARE(exitedEventCoordinateOrder.count(), Number_Of_Exited_Events); + QCOMPARE(monitorsInExpectedExitedEventOrder.count(), Number_Of_Exited_Events); + + //verify that both sources got the same signals + for (int i = 0; i < Number_Of_Entered_Events; i++) { + //first source + QGeoAreaMonitorInfo monInfo = enteredSpy.first().at(0).value(); + QGeoPositionInfo posInfo = enteredSpy.takeFirst().at(1).value(); + QVERIFY2(monInfo == monitorsInExpectedEnteredEventOrder.at(i), + qPrintable(QString::number(i) + ": " + monInfo.name())); + QVERIFY2(posInfo.coordinate() == enteredEventCoordinateOrder.at(i), + qPrintable(QString::number(i) + ". posInfo")); + + //reset info objects to avoid comparing the same + monInfo = QGeoAreaMonitorInfo(); + posInfo = QGeoPositionInfo(); + + //second source + monInfo = enteredSpy2.first().at(0).value(); + posInfo = enteredSpy2.takeFirst().at(1).value(); + QVERIFY2(monInfo == monitorsInExpectedEnteredEventOrder.at(i), + qPrintable(QString::number(i) + ": " + monInfo.name())); + QVERIFY2(posInfo.coordinate() == enteredEventCoordinateOrder.at(i), + qPrintable(QString::number(i) + ". posInfo")); + } + + for (int i = 0; i < Number_Of_Exited_Events; i++) { + //first source + QGeoAreaMonitorInfo monInfo = exitedSpy.first().at(0).value(); + QGeoPositionInfo posInfo = exitedSpy.takeFirst().at(1).value(); + QVERIFY2(monInfo == monitorsInExpectedExitedEventOrder.at(i), + qPrintable(QString::number(i) + ": " + monInfo.name())); + QVERIFY2(posInfo.coordinate() == exitedEventCoordinateOrder.at(i), + qPrintable(QString::number(i) + ". posInfo")); + + //reset info objects to avoid comparing the same + monInfo = QGeoAreaMonitorInfo(); + posInfo = QGeoPositionInfo(); + + //second source + monInfo = exitedSpy2.first().at(0).value(); + posInfo = exitedSpy2.takeFirst().at(1).value(); + QVERIFY2(monInfo == monitorsInExpectedExitedEventOrder.at(i), + qPrintable(QString::number(i) + ": " + monInfo.name())); + QVERIFY2(posInfo.coordinate() == exitedEventCoordinateOrder.at(i), + qPrintable(QString::number(i) + ". posInfo")); + } + + QCOMPARE(obj->activeMonitors().count(), 2); //single shot monitors have been removed + QCOMPARE(secondObj->activeMonitors().count(), 2); + + delete obj; + delete secondObj; + } + + void tst_swapOfPositionSource() + { + QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(obj != 0); + QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll")); + obj->setObjectName("firstObject"); + QSignalSpy enteredSpy(obj, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo))); + QSignalSpy exitedSpy(obj, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo))); + + QGeoAreaMonitorSource *obj2 = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0); + QVERIFY(obj2 != 0); + QCOMPARE(obj2->sourceName(), QStringLiteral("positionpoll")); + obj2->setObjectName("secondObject"); + QSignalSpy enteredSpy2(obj2, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo))); + QSignalSpy exitedSpy2(obj2, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo))); + + LogFilePositionSource *source = new LogFilePositionSource(this); + source->setUpdateInterval(UPDATE_INTERVAL); + source->setObjectName("FirstLogFileSource"); + + LogFilePositionSource *source2 = new LogFilePositionSource(this); + source2->setUpdateInterval(UPDATE_INTERVAL); + source2->setObjectName("SecondLogFileSource"); + + obj->setPositionInfoSource(source); + QCOMPARE(obj->positionInfoSource(), obj2->positionInfoSource()); + QCOMPARE(obj2->positionInfoSource(), source); + + QGeoAreaMonitorInfo infoRectangle("Rectangle"); + infoRectangle.setArea(QGeoRectangle(QGeoCoordinate(-27.70, 153.092), 0.2, 0.2)); + QVERIFY(infoRectangle.isValid()); + QVERIFY(obj->startMonitoring(infoRectangle)); + + QCOMPARE(obj->activeMonitors().count(), 1); + QCOMPARE(obj2->activeMonitors().count(), 1); + + QGeoCoordinate firstBorder(-27.6, 153.090908); + QGeoCoordinate secondBorder(-27.81, 153.092530); + + /***********************************/ + //1. trigger events on source (until areaExit + QTRY_VERIFY_WITH_TIMEOUT(exitedSpy.count() == 1, 20000); + QCOMPARE(enteredSpy.count(), enteredSpy2.count()); + QCOMPARE(exitedSpy.count(), exitedSpy2.count()); + + //compare entered event + QVERIFY(enteredSpy.first().at(0).value() == + enteredSpy2.first().at(0).value()); + QGeoPositionInfo info = enteredSpy.takeFirst().at(1).value(); + QVERIFY(info == enteredSpy2.takeFirst().at(1).value()); + QVERIFY(info.coordinate() == firstBorder); + //compare exit event + QVERIFY(exitedSpy.first().at(0).value() == + exitedSpy2.first().at(0).value()); + info = exitedSpy.takeFirst().at(1).value(); + QVERIFY(info == exitedSpy2.takeFirst().at(1).value()); + QVERIFY(info.coordinate() == secondBorder); + + QCOMPARE(exitedSpy.count(), 0); + QCOMPARE(enteredSpy.count(), 0); + QCOMPARE(exitedSpy2.count(), 0); + QCOMPARE(enteredSpy2.count(), 0); + + /***********************************/ + //2. change position source -> which restarts at beginning again + obj2->setPositionInfoSource(source2); + QCOMPARE(obj->positionInfoSource(), obj2->positionInfoSource()); + QCOMPARE(obj2->positionInfoSource(), source2); + + QTRY_VERIFY_WITH_TIMEOUT(exitedSpy.count() == 1, 20000); + QCOMPARE(enteredSpy.count(), enteredSpy2.count()); + QCOMPARE(exitedSpy.count(), exitedSpy2.count()); + + //compare entered event + QVERIFY(enteredSpy.first().at(0).value() == + enteredSpy2.first().at(0).value()); + info = enteredSpy.takeFirst().at(1).value(); + QVERIFY(info == enteredSpy2.takeFirst().at(1).value()); + QVERIFY(info.coordinate() == firstBorder); + //compare exit event + QVERIFY(exitedSpy.first().at(0).value() == + exitedSpy2.first().at(0).value()); + info = exitedSpy.takeFirst().at(1).value(); + QVERIFY(info == exitedSpy2.takeFirst().at(1).value()); + QVERIFY(info.coordinate() == secondBorder); + + + //obj was deleted when setting new source + delete obj2; + } + + void debug_data() + { + QTest::addColumn("info"); + QTest::addColumn("nextValue"); + QTest::addColumn("debugString"); + + QGeoAreaMonitorInfo info; + QTest::newRow("uninitialized") << info << 45 + << QString("QGeoAreaMonitorInfo(\"\", QGeoShape(Unknown), " + "persistent: false, expiry: QDateTime( Qt::TimeSpec(LocalTime))) 45"); + + info.setArea(QGeoRectangle()); + info.setPersistent(true); + info.setName("RectangleAreaMonitor"); + QTest::newRow("Rectangle Test") << info << 45 + << QString("QGeoAreaMonitorInfo(\"RectangleAreaMonitor\", QGeoShape(Rectangle), " + "persistent: true, expiry: QDateTime( Qt::TimeSpec(LocalTime))) 45"); + + info = QGeoAreaMonitorInfo(); + info.setArea(QGeoCircle()); + info.setPersistent(false); + info.setName("CircleAreaMonitor"); + QVariantMap map; + map.insert(QString("foobarKey"), QVariant(45)); //should be ignored + info.setNotificationParameters(map); + QTest::newRow("Circle Test") << info << 45 + << QString("QGeoAreaMonitorInfo(\"CircleAreaMonitor\", QGeoShape(Circle), " + "persistent: false, expiry: QDateTime( Qt::TimeSpec(LocalTime))) 45"); + + // we ignore any further QDateTime related changes to avoid depending on QDateTime related + // failures in case its QDebug string changes + } + + void debug() + { + QFETCH(QGeoAreaMonitorInfo, info); + QFETCH(int, nextValue); + QFETCH(QString, debugString); + + qInstallMessageHandler(tst_qgeoareamonitorinfo_messageHandler); + qDebug() << info << nextValue; + qInstallMessageHandler(0); + QCOMPARE(tst_qgeoareamonitorinfo_debug, debugString); + } +}; + + +QTEST_GUILESS_MAIN(tst_QGeoAreaMonitorSource) +#include "tst_qgeoareamonitor.moc" diff --git a/tests/auto/qgeocameracapabilities/qgeocameracapabilities.pro b/tests/auto/qgeocameracapabilities/qgeocameracapabilities.pro new file mode 100644 index 0000000..f629a15 --- /dev/null +++ b/tests/auto/qgeocameracapabilities/qgeocameracapabilities.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeocameracapabilities + +INCLUDEPATH += ../../../src/location/maps + +SOURCES += tst_qgeocameracapabilities.cpp + +QT += location positioning-private testlib diff --git a/tests/auto/qgeocameracapabilities/tst_qgeocameracapabilities.cpp b/tests/auto/qgeocameracapabilities/tst_qgeocameracapabilities.cpp new file mode 100644 index 0000000..5475542 --- /dev/null +++ b/tests/auto/qgeocameracapabilities/tst_qgeocameracapabilities.cpp @@ -0,0 +1,297 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "qgeocameracapabilities_p.h" +#include "qgeotiledmap_p.h" + +QT_USE_NAMESPACE + +class tst_QGeoCameraCapabilities : public QObject +{ + Q_OBJECT + +public: + tst_QGeoCameraCapabilities(); + +private: + void populateGeoCameraCapabilitiesData(); + +private Q_SLOTS: + void constructorTest_data(); + void constructorTest(); + void minimumZoomLevelTest(); + void maximumZoomLevelTest(); + void supportsBearingTest(); + void supportsRollingTest(); + void supportsTiltingTest(); + void minimumTiltTest(); + void maximumTiltTest(); + void operatorsTest_data(); + void operatorsTest(); + void isValidTest(); +}; + +tst_QGeoCameraCapabilities::tst_QGeoCameraCapabilities() +{ +} + +void tst_QGeoCameraCapabilities::populateGeoCameraCapabilitiesData(){ + QTest::addColumn("minimumZoomLevel"); + QTest::addColumn("maximumZoomLevel"); + QTest::addColumn("minimumTilt"); + QTest::addColumn("maximumTilt"); + QTest::addColumn("bearingSupport"); + QTest::addColumn("rollingSupport"); + QTest::addColumn("tiltingSupport"); + QTest::newRow("zeros") << 0.0 << 0.0 << 0.0 << 0.0 << false << false << false; + QTest::newRow("valid") << 1.0 << 2.0 << 0.5 << 1.5 << true << true << true; + QTest::newRow("negative values") << 0.0 << 0.5 << -0.5 << -0.1 << true << true << true; +} + +void tst_QGeoCameraCapabilities::constructorTest_data(){ + populateGeoCameraCapabilitiesData(); +} + +void tst_QGeoCameraCapabilities::constructorTest() +{ + QFETCH(double, minimumZoomLevel); + QFETCH(double, maximumZoomLevel); + QFETCH(double, minimumTilt); + QFETCH(double, maximumTilt); + QFETCH(bool, bearingSupport); + QFETCH(bool, rollingSupport); + QFETCH(bool, tiltingSupport); + + // contructor test with default values + QGeoCameraCapabilities cameraCapabilities; + QGeoCameraCapabilities cameraCapabilities2(cameraCapabilities); + QCOMPARE(cameraCapabilities.minimumZoomLevel(), cameraCapabilities2.minimumZoomLevel()); + QCOMPARE(cameraCapabilities.maximumZoomLevel(), cameraCapabilities2.maximumZoomLevel()); + QVERIFY2(cameraCapabilities.supportsBearing() == cameraCapabilities2.supportsBearing(), "Copy constructor failed for bearing support"); + QVERIFY2(cameraCapabilities.supportsRolling() == cameraCapabilities2.supportsRolling(), "Copy constructor failed for rolling support "); + QVERIFY2(cameraCapabilities.supportsTilting() == cameraCapabilities2.supportsTilting(), "Copy constructor failed for tilting support"); + QCOMPARE(cameraCapabilities.minimumTilt(), cameraCapabilities2.minimumTilt()); + QCOMPARE(cameraCapabilities.maximumTilt(), cameraCapabilities2.maximumTilt()); + + // constructor test after setting values + cameraCapabilities.setMinimumZoomLevel(minimumZoomLevel); + cameraCapabilities.setMaximumZoomLevel(maximumZoomLevel); + cameraCapabilities.setMinimumTilt(minimumTilt); + cameraCapabilities.setMaximumTilt(maximumTilt); + cameraCapabilities.setSupportsBearing(bearingSupport); + cameraCapabilities.setSupportsRolling(rollingSupport); + cameraCapabilities.setSupportsTilting(tiltingSupport); + + QGeoCameraCapabilities cameraCapabilities3(cameraCapabilities); + // test the correctness of the constructor copy + QCOMPARE(cameraCapabilities3.minimumZoomLevel(), minimumZoomLevel); + QCOMPARE(cameraCapabilities3.maximumZoomLevel(), maximumZoomLevel); + QCOMPARE(cameraCapabilities3.minimumTilt(), minimumTilt); + QCOMPARE(cameraCapabilities3.maximumTilt(), maximumTilt); + QVERIFY2(cameraCapabilities3.supportsBearing() == bearingSupport, "Copy constructor failed for bearing support"); + QVERIFY2(cameraCapabilities3.supportsRolling() == rollingSupport, "Copy constructor failed for rolling support "); + QVERIFY2(cameraCapabilities3.supportsTilting() == tiltingSupport, "Copy constructor failed for tilting support"); + // verify that values have not changed after a constructor copy + QCOMPARE(cameraCapabilities.minimumZoomLevel(), cameraCapabilities3.minimumZoomLevel()); + QCOMPARE(cameraCapabilities.maximumZoomLevel(), cameraCapabilities3.maximumZoomLevel()); + QVERIFY2(cameraCapabilities.supportsBearing() == cameraCapabilities3.supportsBearing(), "Copy constructor failed for bearing support"); + QVERIFY2(cameraCapabilities.supportsRolling() == cameraCapabilities3.supportsRolling(), "Copy constructor failed for rolling support "); + QVERIFY2(cameraCapabilities.supportsTilting() == cameraCapabilities3.supportsTilting(), "Copy constructor failed for tilting support"); + QCOMPARE(cameraCapabilities.minimumTilt(), cameraCapabilities3.minimumTilt()); + QCOMPARE(cameraCapabilities.maximumTilt(), cameraCapabilities3.maximumTilt()); +} + +void tst_QGeoCameraCapabilities::minimumZoomLevelTest() +{ + QGeoCameraCapabilities cameraCapabilities; + cameraCapabilities.setMinimumZoomLevel(1.5); + QCOMPARE(cameraCapabilities.minimumZoomLevel(), 1.5); + + QGeoCameraCapabilities cameraCapabilities2 = cameraCapabilities; + QCOMPARE(cameraCapabilities2.minimumZoomLevel(), 1.5); + cameraCapabilities.setMinimumZoomLevel(2.5); + QCOMPARE(cameraCapabilities2.minimumZoomLevel(), 1.5); +} + +void tst_QGeoCameraCapabilities::maximumZoomLevelTest() +{ + QGeoCameraCapabilities cameraCapabilities; + cameraCapabilities.setMaximumZoomLevel(3.5); + QCOMPARE(cameraCapabilities.maximumZoomLevel(), 3.5); + + QGeoCameraCapabilities cameraCapabilities2 = cameraCapabilities; + QCOMPARE(cameraCapabilities2.maximumZoomLevel(), 3.5); + cameraCapabilities.setMaximumZoomLevel(4.5); + QCOMPARE(cameraCapabilities2.maximumZoomLevel(), 3.5); +} + +void tst_QGeoCameraCapabilities::supportsBearingTest(){ + QGeoCameraCapabilities cameraCapabilities; + QVERIFY(!cameraCapabilities.supportsBearing()); + cameraCapabilities.setSupportsBearing(true); + QVERIFY2(cameraCapabilities.supportsBearing(), "Camera capabilities should support bearing"); + + QGeoCameraCapabilities cameraCapabilities2 = cameraCapabilities; + QVERIFY(cameraCapabilities2.supportsBearing()); + cameraCapabilities.setSupportsBearing(false); + QVERIFY2(cameraCapabilities2.supportsBearing(), "Camera capabilities should support bearing"); +} + +void tst_QGeoCameraCapabilities::supportsRollingTest(){ + QGeoCameraCapabilities cameraCapabilities; + QVERIFY(!cameraCapabilities.supportsRolling()); + cameraCapabilities.setSupportsRolling(true); + QVERIFY2(cameraCapabilities.supportsRolling(), "Camera capabilities should support rolling"); + + QGeoCameraCapabilities cameraCapabilities2 = cameraCapabilities; + QVERIFY(cameraCapabilities2.supportsRolling()); + cameraCapabilities.setSupportsRolling(false); + QVERIFY2(cameraCapabilities2.supportsRolling(), "Camera capabilities should support rolling"); +} + +void tst_QGeoCameraCapabilities::supportsTiltingTest(){ + QGeoCameraCapabilities cameraCapabilities; + QVERIFY(!cameraCapabilities.supportsTilting()); + cameraCapabilities.setSupportsTilting(true); + QVERIFY2(cameraCapabilities.supportsTilting(), "Camera capabilities should support tilting"); + + QGeoCameraCapabilities cameraCapabilities2 = cameraCapabilities; + QVERIFY(cameraCapabilities2.supportsTilting()); + cameraCapabilities.setSupportsTilting(false); + QVERIFY2(cameraCapabilities2.supportsTilting(), "Camera capabilities should support tilting"); +} + +void tst_QGeoCameraCapabilities::minimumTiltTest(){ + QGeoCameraCapabilities cameraCapabilities; + QCOMPARE(cameraCapabilities.minimumTilt(),0.0); + cameraCapabilities.setMinimumTilt(0.5); + QCOMPARE(cameraCapabilities.minimumTilt(),0.5); + + QGeoCameraCapabilities cameraCapabilities2 = cameraCapabilities; + QCOMPARE(cameraCapabilities2.minimumTilt(), 0.5); + cameraCapabilities.setMinimumTilt(1.5); + QCOMPARE(cameraCapabilities2.minimumTilt(), 0.5); +} + +void tst_QGeoCameraCapabilities::maximumTiltTest(){ + QGeoCameraCapabilities cameraCapabilities; + QCOMPARE(cameraCapabilities.maximumTilt(),0.0); + cameraCapabilities.setMaximumTilt(1.5); + QCOMPARE(cameraCapabilities.maximumTilt(),1.5); + + QGeoCameraCapabilities cameraCapabilities2 = cameraCapabilities; + QCOMPARE(cameraCapabilities2.maximumTilt(), 1.5); + cameraCapabilities.setMaximumTilt(2.5); + QCOMPARE(cameraCapabilities2.maximumTilt(), 1.5); +} + +void tst_QGeoCameraCapabilities::operatorsTest_data(){ + populateGeoCameraCapabilitiesData(); +} + +void tst_QGeoCameraCapabilities::operatorsTest(){ + + QFETCH(double, minimumZoomLevel); + QFETCH(double, maximumZoomLevel); + QFETCH(double, minimumTilt); + QFETCH(double, maximumTilt); + QFETCH(bool, bearingSupport); + QFETCH(bool, rollingSupport); + QFETCH(bool, tiltingSupport); + + QGeoCameraCapabilities cameraCapabilities; + cameraCapabilities.setMinimumZoomLevel(minimumZoomLevel); + cameraCapabilities.setMaximumZoomLevel(maximumZoomLevel); + cameraCapabilities.setMinimumTilt(minimumTilt); + cameraCapabilities.setMaximumTilt(maximumTilt); + cameraCapabilities.setSupportsBearing(bearingSupport); + cameraCapabilities.setSupportsRolling(rollingSupport); + cameraCapabilities.setSupportsTilting(tiltingSupport); + QGeoCameraCapabilities cameraCapabilities2; + cameraCapabilities2 = cameraCapabilities; + // test the correctness of the assignment + QCOMPARE(cameraCapabilities2.minimumZoomLevel(), minimumZoomLevel); + QCOMPARE(cameraCapabilities2.maximumZoomLevel(), maximumZoomLevel); + QCOMPARE(cameraCapabilities2.minimumTilt(), minimumTilt); + QCOMPARE(cameraCapabilities2.maximumTilt(), maximumTilt); + QVERIFY2(cameraCapabilities2.supportsBearing() == bearingSupport, "Copy constructor failed for bearing support"); + QVERIFY2(cameraCapabilities2.supportsRolling() == rollingSupport, "Copy constructor failed for rolling support "); + QVERIFY2(cameraCapabilities2.supportsTilting() == tiltingSupport, "Copy constructor failed for tilting support"); + // verify that values have not changed after a constructor copy + QCOMPARE(cameraCapabilities.minimumZoomLevel(), cameraCapabilities2.minimumZoomLevel()); + QCOMPARE(cameraCapabilities.maximumZoomLevel(), cameraCapabilities2.maximumZoomLevel()); + QVERIFY2(cameraCapabilities.supportsBearing() == cameraCapabilities2.supportsBearing(), "Copy constructor failed for bearing support"); + QVERIFY2(cameraCapabilities.supportsRolling() == cameraCapabilities2.supportsRolling(), "Copy constructor failed for rolling support "); + QVERIFY2(cameraCapabilities.supportsTilting() == cameraCapabilities2.supportsTilting(), "Copy constructor failed for tilting support"); + QCOMPARE(cameraCapabilities.minimumTilt(), cameraCapabilities2.minimumTilt()); + QCOMPARE(cameraCapabilities.maximumTilt(), cameraCapabilities2.maximumTilt()); +} + +void tst_QGeoCameraCapabilities::isValidTest(){ + QGeoCameraCapabilities cameraCapabilities; + QVERIFY2(!cameraCapabilities.isValid(), "Camera capabilities should default to invalid"); + cameraCapabilities.setSupportsBearing(true); + QVERIFY2(cameraCapabilities.isValid(), "Camera capabilities should be valid"); + + QGeoCameraCapabilities cameraCapabilities2; + QVERIFY2(!cameraCapabilities2.isValid(), "Camera capabilities should default to invalid"); + cameraCapabilities2.setSupportsRolling(true); + QVERIFY2(cameraCapabilities2.isValid(), "Camera capabilities should be valid"); + + QGeoCameraCapabilities cameraCapabilities3; + QVERIFY2(!cameraCapabilities3.isValid(), "Camera capabilities should default to invalid"); + cameraCapabilities3.setSupportsTilting(true); + QVERIFY2(cameraCapabilities3.isValid(), "Camera capabilities should be valid"); + + QGeoCameraCapabilities cameraCapabilities4; + QVERIFY2(!cameraCapabilities4.isValid(), "Camera capabilities should default to invalid"); + cameraCapabilities4.setMinimumZoomLevel(1.0); + QVERIFY2(cameraCapabilities4.isValid(), "Camera capabilities should be valid"); + + QGeoCameraCapabilities cameraCapabilities5; + QVERIFY2(!cameraCapabilities5.isValid(), "Camera capabilities should default to invalid"); + cameraCapabilities5.setMaximumZoomLevel(1.5); + QVERIFY2(cameraCapabilities5.isValid(), "Camera capabilities should be valid"); + + QGeoCameraCapabilities cameraCapabilities6; + QVERIFY2(!cameraCapabilities6.isValid(), "Camera capabilities should default to invalid"); + cameraCapabilities6.setMinimumTilt(0.2); + QVERIFY2(cameraCapabilities6.isValid(), "Camera capabilities should be valid"); + + QGeoCameraCapabilities cameraCapabilities7; + QVERIFY2(!cameraCapabilities7.isValid(), "Camera capabilities should default to invalid"); + cameraCapabilities7.setMaximumTilt(0.8); + QVERIFY2(cameraCapabilities7.isValid(), "Camera capabilities should be valid"); +} + +QTEST_APPLESS_MAIN(tst_QGeoCameraCapabilities) + +#include "tst_qgeocameracapabilities.moc" diff --git a/tests/auto/qgeocameradata/qgeocameradata.pro b/tests/auto/qgeocameradata/qgeocameradata.pro new file mode 100644 index 0000000..f2d6d5d --- /dev/null +++ b/tests/auto/qgeocameradata/qgeocameradata.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeocameradata + +INCLUDEPATH += ../../../src/location/maps + +SOURCES += tst_qgeocameradata.cpp + +QT += location positioning-private testlib diff --git a/tests/auto/qgeocameradata/tst_qgeocameradata.cpp b/tests/auto/qgeocameradata/tst_qgeocameradata.cpp new file mode 100644 index 0000000..be75acf --- /dev/null +++ b/tests/auto/qgeocameradata/tst_qgeocameradata.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "qgeocameradata_p.h" + +QT_USE_NAMESPACE + +class tst_QGeoCameraData : public QObject +{ + Q_OBJECT + +public: + tst_QGeoCameraData(); + +private: + void populateCameraData(); + +private Q_SLOTS: + void constructorTest_data(); + void constructorTest(); + void centerTest(); + void bearingTest(); + void tiltTest(); + void rollTest(); + void zoomLevelTest(); + void operatorsTest_data(); + void operatorsTest(); +}; + +tst_QGeoCameraData::tst_QGeoCameraData() +{ +} + + +void tst_QGeoCameraData::populateCameraData() +{ + QTest::addColumn("center"); + QTest::addColumn("bearing"); + QTest::addColumn("tilt"); + QTest::addColumn("roll"); + QTest::addColumn("zoomLevel"); + QTest::newRow("zeros") << QGeoCoordinate() << 0.0 << 0.0 << 0.0 << 0.0; + QTest::newRow("valid") << QGeoCoordinate(10.0,20.5,30.8) << 0.1 << 0.2 << 0.3 << 2.0; + QTest::newRow("negative values") << QGeoCoordinate(-50,-20,100) << -0.1 << -0.2 << -0.3 << 1.0; +} + +void tst_QGeoCameraData::constructorTest_data(){ + populateCameraData(); +} + +void tst_QGeoCameraData::constructorTest() +{ + QFETCH(QGeoCoordinate, center); + QFETCH(double, bearing); + QFETCH(double, tilt); + QFETCH(double, roll); + QFETCH(double, zoomLevel); + + // constructor test with default values + QGeoCameraData cameraData; + QGeoCameraData cameraData2(cameraData); + QCOMPARE(cameraData.center(), cameraData2.center()); + QCOMPARE(cameraData.bearing(), cameraData2.bearing()); + QCOMPARE(cameraData.tilt(), cameraData2.tilt()); + QCOMPARE(cameraData.roll(), cameraData2.roll()); + QCOMPARE(cameraData.zoomLevel(), cameraData2.zoomLevel()); + + // constructor test after setting values + cameraData.setCenter(center); + cameraData.setBearing(bearing); + cameraData.setTilt(tilt); + cameraData.setRoll(roll); + cameraData.setZoomLevel(zoomLevel); + QGeoCameraData cameraData3(cameraData); + // test the correctness of the constructor copy + QCOMPARE(cameraData3.center(), center); + QCOMPARE(cameraData3.bearing(), bearing); + QCOMPARE(cameraData3.tilt(), tilt); + QCOMPARE(cameraData3.roll(), roll); + QCOMPARE(cameraData3.zoomLevel(), zoomLevel); + // verify that values have not changed after a constructor copy + QCOMPARE(cameraData.center(), cameraData3.center()); + QCOMPARE(cameraData.bearing(), cameraData3.bearing()); + QCOMPARE(cameraData.tilt(), cameraData3.tilt()); + QCOMPARE(cameraData.roll(), cameraData3.roll()); + QCOMPARE(cameraData.zoomLevel(), cameraData3.zoomLevel()); +} + + +void tst_QGeoCameraData::centerTest() +{ + QGeoCameraData cameraData; //center currently default to (-27.5, 153) + cameraData.setCenter(QGeoCoordinate(10.0,20.4,30.8)); + QCOMPARE(cameraData.center(),QGeoCoordinate(10.0,20.4,30.8)); +} + +void tst_QGeoCameraData::bearingTest(){ + QGeoCameraData cameraData; + QCOMPARE(cameraData.bearing(),0.0); + cameraData.setBearing(0.1); + QCOMPARE(cameraData.bearing(),0.1); + + QGeoCameraData cameraData2 = cameraData; + QCOMPARE(cameraData2.bearing(),0.1); + cameraData.setBearing(0.2); + QCOMPARE(cameraData2.bearing(),0.1); +} + +void tst_QGeoCameraData::tiltTest(){ + QGeoCameraData cameraData; + QCOMPARE(cameraData.tilt(),0.0); + cameraData.setTilt(0.4); + QCOMPARE(cameraData.tilt(),0.4); + + QGeoCameraData cameraData2 = cameraData; + QCOMPARE(cameraData2.tilt(),0.4); + cameraData.setTilt(0.5); + QCOMPARE(cameraData2.tilt(),0.4); +} + +void tst_QGeoCameraData::rollTest(){ + QGeoCameraData cameraData; + QCOMPARE(cameraData.roll(),0.0); + cameraData.setRoll(0.5); + QCOMPARE(cameraData.roll(),0.5); + + QGeoCameraData cameraData2 = cameraData; + QCOMPARE(cameraData2.roll(),0.5); + cameraData.setRoll(0.6); + QCOMPARE(cameraData2.roll(),0.5); +} + +void tst_QGeoCameraData::zoomLevelTest(){ + QGeoCameraData cameraData; //zoom level currently defaults to 9.0 + cameraData.setZoomLevel(8.0); + QCOMPARE(cameraData.zoomLevel(),8.0); + + QGeoCameraData cameraData2 = cameraData; + QCOMPARE(cameraData2.zoomLevel(),8.0); + cameraData.setZoomLevel(9.0); + QCOMPARE(cameraData2.zoomLevel(),8.0); +} + +void tst_QGeoCameraData::operatorsTest_data(){ + populateCameraData(); +} + +void tst_QGeoCameraData::operatorsTest(){ + QGeoCameraData cameraData; + QGeoCameraData cameraData2; + QVERIFY2(cameraData == cameraData2, "Camera data with default values are not copied correctly"); + + QFETCH(QGeoCoordinate, center); + QFETCH(double, bearing); + QFETCH(double, tilt); + QFETCH(double, roll); + QFETCH(double, zoomLevel); + cameraData.setCenter(center); + cameraData.setBearing(bearing); + cameraData.setTilt(tilt); + cameraData.setRoll(roll); + cameraData.setZoomLevel(zoomLevel); + + QGeoCameraData cameraData3; + cameraData3 = cameraData; + QVERIFY2(cameraData == cameraData3, "Camera data not copied correctly"); + + // test QGeoCameraData pairs where they differ in one field + QGeoCameraData cameraData4; + cameraData4 = cameraData; + cameraData4.setCenter(QGeoCoordinate(10.0,20.0,30.0)); + QVERIFY2(cameraData != cameraData4, "Camera data should be different"); + QGeoCameraData cameraData5; + cameraData5 = cameraData; + cameraData5.setBearing(bearing+1.0); + QVERIFY2(cameraData != cameraData5, "Camera data should be different"); + QGeoCameraData cameraData6; + cameraData6 = cameraData; + cameraData6.setTilt(tilt+0.1); + QVERIFY2(cameraData != cameraData6, "Camera data should be different"); + QGeoCameraData cameraData7; + cameraData7 = cameraData; + cameraData7.setRoll(roll+0.1); + QVERIFY2(cameraData != cameraData7, "Camera data should be different"); + QGeoCameraData cameraData8; + cameraData8 = cameraData; + cameraData8.setZoomLevel(zoomLevel+1.0); + QVERIFY2(cameraData != cameraData8, "Camera data should be different"); +} + +QTEST_APPLESS_MAIN(tst_QGeoCameraData) + +#include "tst_qgeocameradata.moc" diff --git a/tests/auto/qgeocameratiles/qgeocameratiles.pro b/tests/auto/qgeocameratiles/qgeocameratiles.pro new file mode 100644 index 0000000..816e424 --- /dev/null +++ b/tests/auto/qgeocameratiles/qgeocameratiles.pro @@ -0,0 +1,8 @@ +CONFIG += testcase +TARGET = tst_qgeocameratiles + +INCLUDEPATH += ../../../src/location/maps + +SOURCES += tst_qgeocameratiles.cpp + +QT += location positioning-private testlib diff --git a/tests/auto/qgeocameratiles/tst_qgeocameratiles.cpp b/tests/auto/qgeocameratiles/tst_qgeocameratiles.cpp new file mode 100644 index 0000000..8d9cec3 --- /dev/null +++ b/tests/auto/qgeocameratiles/tst_qgeocameratiles.cpp @@ -0,0 +1,1806 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location/maps + +#include "qgeotilespec_p.h" +#include "qgeocameratiles_p.h" +#include "qgeocameradata_p.h" +#include "qgeomaptype_p.h" + +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +struct PositionTestInfo { + QString xyString; + QString zoomString; + QString wString; + QString hString; + double x; + double y; + double zoom; + double w; + double h; +}; + +class tst_QGeoCameraTiles : public QObject +{ + Q_OBJECT + +private: + + void row(const PositionTestInfo &pti, int xOffset, int yOffset, int tileX, int tileY, int tileW, int tileH); + void test_group(const PositionTestInfo &pti, QList &xVals, QList &wVals, QList &yVals, QList &hVals); + +private slots: + + void tilesPlugin(); + void tilesMapType(); + void tilesPositions(); + void tilesPositions_data(); +}; + +void tst_QGeoCameraTiles::row(const PositionTestInfo &pti, int xOffset, int yOffset, int tileX, int tileY, int tileW, int tileH) +{ + double step = 1 / (qPow(2.0, 4.0) * 4); + + QString row = pti.xyString; + row += QStringLiteral(" - "); + row += pti.zoomString; + row += QStringLiteral(" - ("); + row += QString::number(xOffset); + row += QStringLiteral(","); + row += QString::number(yOffset); + row += QStringLiteral(") - "); + row += pti.wString; + row += QStringLiteral(" x "); + row += pti.hString; + + QList xRow; + QList yRow; + + for (int y = 0; y < tileH; ++y) { + for (int x = 0; x < tileW; ++x) { + if (tileX + x < 16) + xRow << tileX + x; + else + xRow << tileX + x - 16; + yRow << tileY + y; + } + } + + QTest::newRow(qPrintable(row)) + << pti.x + step * xOffset << pti.y + step * yOffset + << pti.zoom << pti.w << pti.h + << xRow + << yRow; +} + +void tst_QGeoCameraTiles::test_group(const PositionTestInfo &pti, QList &xVals, QList &wVals, QList &yVals, QList &hVals) +{ + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + row(pti, x, y, xVals.at(x), yVals.at(y), wVals.at(x), hVals.at(y)); + } + } +} + +void tst_QGeoCameraTiles::tilesPlugin() +{ + QGeoCameraData camera; + camera.setZoomLevel(4.0); + camera.setCenter(QGeoCoordinate(0.0, 0.0)); + + QGeoCameraTiles ct; + ct.setTileSize(16); + ct.setCameraData(camera); + ct.setScreenSize(QSize(32, 32)); + ct.setMapType(QGeoMapType(QGeoMapType::StreetMap, "street map", "street map", false, false, 1)); + + QSet tiles1 = ct.createTiles(); + + ct.setPluginString("pluginA"); + + QSet tiles2 = ct.createTiles(); + + typedef QSet::const_iterator iter; + iter i1 = tiles1.constBegin(); + iter end1 = tiles1.constEnd(); + + QSet tiles2_check; + + for (; i1 != end1; ++i1) { + QGeoTileSpec tile = *i1; + tiles2_check.insert(QGeoTileSpec("pluginA", tile.mapId(), tile.zoom(), tile.x(), tile.y())); + } + + QCOMPARE(tiles2, tiles2_check); + + ct.setPluginString("pluginB"); + + QSet tiles3 = ct.createTiles(); + + iter i2 = tiles2.constBegin(); + iter end2 = tiles2.constEnd(); + + QSet tiles3_check; + + for (; i2 != end2; ++i2) { + QGeoTileSpec tile = *i2; + tiles3_check.insert(QGeoTileSpec("pluginB", tile.mapId(), tile.zoom(), tile.x(), tile.y())); + } + + QCOMPARE(tiles3, tiles3_check); +} + +void tst_QGeoCameraTiles::tilesMapType() +{ + QGeoCameraData camera; + camera.setZoomLevel(4.0); + camera.setCenter(QGeoCoordinate(0.0, 0.0)); + + QGeoCameraTiles ct; + ct.setTileSize(16); + ct.setCameraData(camera); + ct.setScreenSize(QSize(32, 32)); + ct.setPluginString("pluginA"); + + QSet tiles1 = ct.createTiles(); + + QGeoMapType mapType1 = QGeoMapType(QGeoMapType::StreetMap, "street map", "street map", false, false, 1); + ct.setMapType(mapType1); + + QSet tiles2 = ct.createTiles(); + + typedef QSet::const_iterator iter; + iter i1 = tiles1.constBegin(); + iter end1 = tiles1.constEnd(); + + QSet tiles2_check; + + for (; i1 != end1; ++i1) { + QGeoTileSpec tile = *i1; + tiles2_check.insert(QGeoTileSpec(tile.plugin(), mapType1.mapId(), tile.zoom(), tile.x(), tile.y())); + } + + QCOMPARE(tiles2, tiles2_check); + + QGeoMapType mapType2 = QGeoMapType(QGeoMapType::StreetMap, "satellite map", "satellite map", false, false, 2); + ct.setMapType(mapType2); + + QSet tiles3 = ct.createTiles(); + + iter i2 = tiles2.constBegin(); + iter end2 = tiles2.constEnd(); + + QSet tiles3_check; + + for (; i2 != end2; ++i2) { + QGeoTileSpec tile = *i2; + tiles3_check.insert(QGeoTileSpec(tile.plugin(), mapType2.mapId(), tile.zoom(), tile.x(), tile.y())); + } + + QCOMPARE(tiles3, tiles3_check); +} + +void tst_QGeoCameraTiles::tilesPositions() +{ + QFETCH(double, mercatorX); + QFETCH(double, mercatorY); + QFETCH(double, zoom); + QFETCH(double, width); + QFETCH(double, height); + QFETCH(QList , tilesX); + QFETCH(QList , tilesY); + + QGeoCameraData camera; + camera.setZoomLevel(zoom); + camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D(mercatorX, mercatorY))); + + QGeoCameraTiles ct; + ct.setTileSize(16); + ct.setCameraData(camera); + ct.setScreenSize(QSize(qCeil(width), qCeil(height))); + + QSet tiles; + + QVERIFY2(tilesX.size() == tilesY.size(), "tilesX and tilesY have different size"); + + for (int i = 0; i < tilesX.size(); ++i) + tiles.insert(QGeoTileSpec("", 0, static_cast(qFloor(zoom)), tilesX.at(i), tilesY.at(i))); + + QCOMPARE(ct.createTiles(), tiles); +} + +void tst_QGeoCameraTiles::tilesPositions_data() +{ + QTest::addColumn("mercatorX"); + QTest::addColumn("mercatorY"); + QTest::addColumn("zoom"); + QTest::addColumn("width"); + QTest::addColumn("height"); + QTest::addColumn >("tilesX"); + QTest::addColumn >("tilesY"); + + int t = 16; + + PositionTestInfo pti; + + /* + This test sets up various viewports onto a 16x16 map, + and checks which tiles are visible against those that + are expected to be visible. + + The tests are run in 5 groups, corresponding to where + the viewport is centered on the map. + + The groups are named as follows, with the tile in + which the viewport is centered listed in parenthesis: + - mid (8, 8) + - top (8, 0) + - bottom (8, 15) + - left (0, 8) + - right (15, 8) + + For each of these groups a number of tests are run, + which involve modifying various parameters. + + If "t" is the width of a tile, the width and height + of the viewport take on values including: + - (t - 1) + - t + - (t + 1) + - (2t - 1) + - 2t + - (2t + 1) + + The viewport is also offset by fractions of a tile + in both the x and y directions. The offsets are in + quarters of a tile. + + The diagrams below present a justification for our + test expectations. + + The diagrams show variations in viewport width and + x offset into the target tile , although can easily + be taken to be the variations in viewport height and + y offset into the target tile. + + The symbols have the following meanings: + "+" - tile boundaries + "*" - viewport boundary + "T" - boundary of tile the viewport is centered on + "O" - same as "T" but coincident with the viewport boundary + + Whenever the viewport boundary is coincident with a tile boundary, + the tiles on both sides of the boundary are expected to be fetched. + + Those tiles are needed in case we perform bilinear antialiasing, + provide us with at least a pixel width of tolerance for errors in + other parts of the code or the system. There is a decent chance + that some or all of those extra tiles will need to be fetched before + long, so getting them into the cache sooner rather than later is + likely to be beneficial on average. + + The tests are carried out per viewport height / width. + + Lists are created of the first tile along an axis that is expected to + be in the viewport and for the number of tiles along an axis that + are expected to be in the viewport. + + These lists are used for both the x and y axes, although alternative + lists are created for the x axis when the viewport spans the dateline + and for the y axis when the viewport is clipped by the top or bottom of + the map. + + These 5 areas are checked at an integral zoom level to see that the + expected visible tiles match the actual visible tiles generated by + the code under test. + + After that a fractional zoom level is set and the width and height of + the viewport are scaled such that the same tiles should be visible, + and the tests are repeated. + */ + + // TODO + // nail down semantics, modify tests and code to suite + // add corners of the map + + /* + width = t - 1 + */ + + QList mid_tm1x; + QList mid_tm1w; + QList top_tm1x; + QList top_tm1w; + QList bottom_tm1x; + QList bottom_tm1w; + QList left_tm1x; + QList left_tm1w; + QList right_tm1x; + QList right_tm1w; + + pti.w = t - 1; + pti.h = t - 1; + pti.wString = QStringLiteral("(1T - 1)"); + pti.hString = QStringLiteral("(1T - 1)"); + + /* + + offset = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * *+* * + + + + + + * + * + + + + + + + + + + +*+ T T*T T T + + + + + + + + + + + * T * T + + + + + * *T* * T + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 2 tiles + */ + + mid_tm1x << 7; + mid_tm1w << 2; + + top_tm1x << 0; + top_tm1w << 1; + + bottom_tm1x << 14; + bottom_tm1w << 2; + + left_tm1x << 15; + left_tm1w << 2; + + right_tm1x << 14; + right_tm1w << 2; + + /* + offset = 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *+* * * + + + + + + *+ * + + + + + + + + + + + +*T T T*T T + + + + + + + + + + + *T * T + + + + + *T* * * T + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 2 tiles + */ + + mid_tm1x << 7; + mid_tm1w << 2; + + top_tm1x << 0; + top_tm1w << 1; + + bottom_tm1x << 14; + bottom_tm1w << 2; + + left_tm1x << 15; + left_tm1w << 2; + + right_tm1x << 14; + right_tm1w << 2; + + /* + offset = 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +* * * *+ + + + + + +* *+ + + + + + + + + + + + T*T T T*T + + + + + + + + + + + T* *T + + + + + T* * * *T + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T + Covers: 1 tile + */ + + mid_tm1x << 8; + mid_tm1w << 1; + + top_tm1x << 0; + top_tm1w << 1; + + bottom_tm1x << 15; + bottom_tm1w << 1; + + left_tm1x << 0; + left_tm1w << 1; + + right_tm1x << 15; + right_tm1w << 1; + + /* + offset = 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * *+* + + + + + + * +* + + + + + + + + + + + T T*T T T*+ + + + + + + + + + + T * T* + + + + + T * * *T* + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T + Covers: 2 tiles + */ + + mid_tm1x << 8; + mid_tm1w << 2; + + top_tm1x << 0; + top_tm1w << 2; + + bottom_tm1x << 15; + bottom_tm1w << 1; + + left_tm1x << 0; + left_tm1w << 2; + + right_tm1x << 15; + right_tm1w << 2; + + /* + offset = 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * *+* * + + + + + + * + * + + + + + + + + + + + T T T*T T +*+ + + + + + + + + + T * T * + + + + + T * *T* * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T + Covers: 2 tiles + */ + + mid_tm1x << 8; + mid_tm1w << 2; + + top_tm1x << 0; + top_tm1w << 2; + + bottom_tm1x << 15; + bottom_tm1w << 1; + + left_tm1x << 0; + left_tm1w << 2; + + right_tm1x << 15; + right_tm1w << 2; + + pti.zoom = 4.0; + pti.zoomString = QStringLiteral("int zoom"); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_tm1x, mid_tm1w, mid_tm1x, mid_tm1w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_tm1x, mid_tm1w, top_tm1x, top_tm1w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_tm1x, mid_tm1w, bottom_tm1x, bottom_tm1w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_tm1x, left_tm1w, mid_tm1x, mid_tm1w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_tm1x, right_tm1w, mid_tm1x, mid_tm1w); + + pti.zoom = 4.5; + pti.zoomString = QStringLiteral("frac zoom"); + pti.w = pti.w * qPow(2.0, 0.5); + pti.h = pti.h * qPow(2.0, 0.5); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_tm1x, mid_tm1w, mid_tm1x, mid_tm1w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_tm1x, mid_tm1w, top_tm1x, top_tm1w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_tm1x, mid_tm1w, bottom_tm1x, bottom_tm1w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_tm1x, left_tm1w, mid_tm1x, mid_tm1w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_tm1x, right_tm1w, mid_tm1x, mid_tm1w); + + /* + width = t + */ + + QList mid_tx; + QList mid_tw; + QList top_tx; + QList top_tw; + QList bottom_tx; + QList bottom_tw; + QList left_tx; + QList left_tw; + QList right_tx; + QList right_tw; + + pti.w = t; + pti.h = t; + pti.wString = QStringLiteral("1T"); + pti.hString = QStringLiteral("1T"); + + /* + + offset = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * + + + + + + * + * + + + + + + + + + + * + T T O T T + + + + + + + + + + + * T * T + + + + + * * O * * T + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 2 tiles + */ + + mid_tx << 7; + mid_tw << 2; + + top_tx << 0; + top_tw << 1; + + bottom_tx << 14; + bottom_tw << 2; + + left_tx << 15; + left_tw << 2; + + right_tx << 14; + right_tw << 2; + + /* + offset = 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * + + + + + + * + * + + + + + + + + + + + * T T T O T + + + + + + + + + + + * T * T + + + + + * O * * * T + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 2 tiles + */ + + mid_tx << 7; + mid_tw << 2; + + top_tx << 0; + top_tw << 1; + + bottom_tx << 14; + bottom_tw << 2; + + left_tx << 15; + left_tw << 2; + + right_tx << 14; + right_tw << 2; + + /* + offset = 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * + + + + + * * + + + + + + + + + + + O T T T O + + + + + + + + + + + O O + + + + + O * * * O + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_tx << 7; + mid_tw << 3; + + top_tx << 0; + top_tw << 2; + + bottom_tx << 14; + bottom_tw << 2; + + left_tx << 15; + left_tw << 3; + + right_tx << 14; + right_tw << 3; + + /* + offset = 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * + + + + + + * * + + + + + + + + + + + T O T T T * + + + + + + + + + + T * T * + + + + + T * * * O * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T + Covers: 2 tiles + */ + + mid_tx << 8; + mid_tw << 2; + + top_tx << 0; + top_tw << 2; + + bottom_tx << 15; + bottom_tw << 1; + + left_tx << 0; + left_tw << 2; + + right_tx << 15; + right_tw << 2; + + /* + offset = 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * + + + + + + * + * + + + + + + + + + + + T T O T T + * + + + + + + + + + T * T * + + + + + T * * O * * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T + Covers: 2 tiles + */ + + mid_tx << 8; + mid_tw << 2; + + top_tx << 0; + top_tw << 2; + + bottom_tx << 15; + bottom_tw << 1; + + left_tx << 0; + left_tw << 2; + + right_tx << 15; + right_tw << 2; + + pti.zoom = 4.0; + pti.zoomString = QStringLiteral("int zoom"); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_tx, mid_tw, mid_tx, mid_tw); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_tx, mid_tw, top_tx, top_tw); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_tx, mid_tw, bottom_tx, bottom_tw); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_tx, left_tw, mid_tx, mid_tw); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_tx, right_tw, mid_tx, mid_tw); + + pti.zoom = 4.5; + pti.zoomString = QStringLiteral("frac zoom"); + pti.w = pti.w * qPow(2.0, 0.5); + pti.h = pti.h * qPow(2.0, 0.5); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_tx, mid_tw, mid_tx, mid_tw); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_tx, mid_tw, top_tx, top_tw); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_tx, mid_tw, bottom_tx, bottom_tw); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_tx, left_tw, mid_tx, mid_tw); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_tx, right_tw, mid_tx, mid_tw); + + /* + width = t + 1 + */ + + QList mid_tp1x; + QList mid_tp1w; + QList top_tp1x; + QList top_tp1w; + QList bottom_tp1x; + QList bottom_tp1w; + QList left_tp1x; + QList left_tp1w; + QList right_tp1x; + QList right_tp1w; + + pti.w = t + 1; + pti.h = t + 1; + pti.wString = QStringLiteral("(1T + 1)"); + pti.hString = QStringLiteral("(1T + 1)"); + + /* + + offset = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * *+* * * + + + + + + * + * + + + + + + + + + +*+ + T T T*T T + + + + + + + + + + + * T * T + + + + + * * *T* * * T + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 2 tiles + */ + + mid_tp1x << 7; + mid_tp1w << 2; + + top_tp1x << 0; + top_tp1w << 1; + + bottom_tp1x << 14; + bottom_tp1w << 2; + + left_tp1x << 15; + left_tp1w << 2; + + right_tp1x << 14; + right_tp1w << 2; + + /* + offset = 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * *+* * * *+ + + + + + * + *+ + + + + + + + + + +*+ T T T T*T + + + + + + + + + + + * T *T + + + + + * *T* * * *T + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 2 tiles + */ + + mid_tp1x << 7; + mid_tp1w << 2; + + top_tp1x << 0; + top_tp1w << 1; + + bottom_tp1x << 14; + bottom_tp1w << 2; + + left_tp1x << 15; + left_tp1w << 2; + + right_tp1x << 14; + right_tp1w << 2; + + /* + offset = 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *+* * * *+* + + + + + *+ +* + + + + + + + + + + +*T T T T T*+ + + + + + + + + + + *T T* + + + + + *T* * * *T* + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_tp1x << 7; + mid_tp1w << 3; + + top_tp1x << 0; + top_tp1w << 2; + + bottom_tp1x << 14; + bottom_tp1w << 2; + + left_tp1x << 15; + left_tp1w << 3; + + right_tp1x << 14; + right_tp1w << 3; + + /* + offset = 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +* * * *+* * + + + + + +* + * + + + + + + + + + + + T*T T T T +*+ + + + + + + + + + T* T * + + + + + T* * * *T* * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T + Covers: 2 tiles + */ + + mid_tp1x << 8; + mid_tp1w << 2; + + top_tp1x << 0; + top_tp1w << 2; + + bottom_tp1x << 15; + bottom_tp1w << 1; + + left_tp1x << 0; + left_tp1w << 2; + + right_tp1x << 15; + right_tp1w << 2; + + /* + offset = 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * *+* * * + + + + + + * + * + + + + + + + + + + + T T*T T T + +*+ + + + + + + + + T * T * + + + + + T * * *T* * * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T + Covers: 2 tiles + */ + + mid_tp1x << 8; + mid_tp1w << 2; + + top_tp1x << 0; + top_tp1w << 2; + + bottom_tp1x << 15; + bottom_tp1w << 1; + + left_tp1x << 0; + left_tp1w << 2; + + right_tp1x << 15; + right_tp1w << 2; + + pti.zoom = 4.0; + pti.zoomString = QStringLiteral("int zoom"); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_tp1x, mid_tp1w, mid_tp1x, mid_tp1w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_tp1x, mid_tp1w, top_tp1x, top_tp1w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_tp1x, mid_tp1w, bottom_tp1x, bottom_tp1w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_tp1x, left_tp1w, mid_tp1x, mid_tp1w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_tp1x, right_tp1w, mid_tp1x, mid_tp1w); + + pti.zoom = 4.5; + pti.zoomString = QStringLiteral("frac zoom"); + pti.w = pti.w * qPow(2.0, 0.5); + pti.h = pti.h * qPow(2.0, 0.5); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_tp1x, mid_tp1w, mid_tp1x, mid_tp1w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_tp1x, mid_tp1w, top_tp1x, top_tp1w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_tp1x, mid_tp1w, bottom_tp1x, bottom_tp1w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_tp1x, left_tp1w, mid_tp1x, mid_tp1w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_tp1x, right_tp1w, mid_tp1x, mid_tp1w); + + /* + width = 2t - 1 + */ + + QList mid_t2m1x; + QList mid_t2m1w; + QList top_t2m1x; + QList top_t2m1w; + QList bottom_t2m1x; + QList bottom_t2m1w; + QList left_t2m1x; + QList left_t2m1w; + QList right_t2m1x; + QList right_t2m1w; + + pti.w = 2 * t - 1; + pti.h = 2 * t - 1; + pti.wString = QStringLiteral("(2T - 1)"); + pti.hString = QStringLiteral("(2T - 1)"); + + /* + offset = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +* * * *+* * * *+ + + + + +* + *+ + + + + + + + +*+ + + T T T T*T + + + + + + + + + + +* T *T + + + + +* * * *T* * * *T + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 2 tiles + */ + + mid_t2m1x << 7; + mid_t2m1w << 2; + + top_t2m1x << 0; + top_t2m1w << 1; + + bottom_t2m1x << 14; + bottom_t2m1w << 2; + + left_t2m1x << 15; + left_t2m1w << 2; + + right_t2m1x << 14; + right_t2m1w << 2; + + /* + offset = 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * *+* * * *+* + + + + + * + +* + + + + + + + + +*+ + T T T T T*+ + + + + + + + + + + * T T* + + + + + * * *T* * * *T* + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_t2m1x << 7; + mid_t2m1w << 3; + + top_t2m1x << 0; + top_t2m1w << 2; + + bottom_t2m1x << 14; + bottom_t2m1w << 2; + + left_t2m1x << 15; + left_t2m1w << 3; + + right_t2m1x << 14; + right_t2m1w << 3; + + /* + offset = 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * *+* * * *+* * + + + + + * + + * + + + + + + + + + +*+ T T T T T +*+ + + + + + + + + + * T T * + + + + + * *T* * * *T* * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_t2m1x << 7; + mid_t2m1w << 3; + + top_t2m1x << 0; + top_t2m1w << 2; + + bottom_t2m1x << 14; + bottom_t2m1w << 2; + + left_t2m1x << 15; + left_t2m1w << 3; + + right_t2m1x << 14; + right_t2m1w << 3; + + /* + offset = 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *+* * * *+* * * + + + + + *+ + * + + + + + + + + + + +*T T T T T + +*+ + + + + + + + + *T T * + + + + + *T* * * *T* * * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_t2m1x << 7; + mid_t2m1w << 3; + + top_t2m1x << 0; + top_t2m1w << 2; + + bottom_t2m1x << 14; + bottom_t2m1w << 2; + + left_t2m1x << 15; + left_t2m1w << 3; + + right_t2m1x << 14; + right_t2m1w << 3; + + /* + offset = 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +* * * *+* * * *+ + + + + +* + *+ + + + + + + + + + + T*T T T T + + +*+ + + + + + + + T* T *+ + + + + T* * * *T* * * *+ + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T + Covers: 2 tiles + */ + + mid_t2m1x << 8; + mid_t2m1w << 2; + + top_t2m1x << 0; + top_t2m1w << 2; + + bottom_t2m1x << 15; + bottom_t2m1w << 1; + + left_t2m1x << 0; + left_t2m1w << 2; + + right_t2m1x << 15; + right_t2m1w << 2; + + pti.zoom = 4.0; + pti.zoomString = QStringLiteral("int zoom"); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_t2m1x, mid_t2m1w, mid_t2m1x, mid_t2m1w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_t2m1x, mid_t2m1w, top_t2m1x, top_t2m1w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_t2m1x, mid_t2m1w, bottom_t2m1x, bottom_t2m1w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_t2m1x, left_t2m1w, mid_t2m1x, mid_t2m1w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_t2m1x, right_t2m1w, mid_t2m1x, mid_t2m1w); + + pti.zoom = 4.5; + pti.zoomString = QStringLiteral("frac zoom"); + pti.w = pti.w * qPow(2.0, 0.5); + pti.h = pti.h * qPow(2.0, 0.5); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_t2m1x, mid_t2m1w, mid_t2m1x, mid_t2m1w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_t2m1x, mid_t2m1w, top_t2m1x, top_t2m1w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_t2m1x, mid_t2m1w, bottom_t2m1x, bottom_t2m1w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_t2m1x, left_t2m1w, mid_t2m1x, mid_t2m1w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_t2m1x, right_t2m1w, mid_t2m1x, mid_t2m1w); + + /* + width = 2t + */ + + + QList mid_t2x; + QList mid_t2w; + QList top_t2x; + QList top_t2w; + QList bottom_t2x; + QList bottom_t2w; + QList left_t2x; + QList left_t2w; + QList right_t2x; + QList right_t2w; + + pti.w = 2 * t; + pti.h = 2 * t; + pti.wString = QStringLiteral("2T"); + pti.hString = QStringLiteral("2T"); + + /* + + offset = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * * * * * + + + + * + * + + + + + + + * + + + T T T T O + + + + + + + + + + * T O + + + + * * * * O * * * O + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 2 + Covers: 4 tiles + */ + + mid_t2x << 6; + mid_t2w << 4; + + top_t2x << 0; + top_t2w << 2; + + bottom_t2x << 13; + bottom_t2w << 3; + + left_t2x << 14; + left_t2w << 4; + + right_t2x << 13; + right_t2w << 4; + + /* + offset = 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * * * * * + + + + + * + * + + + + + + + + * + + T T T T T * + + + + + + + + + + * T T * + + + + + * * * O * * * O * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_t2x << 7; + mid_t2w << 3; + + top_t2x << 0; + top_t2w << 2; + + bottom_t2x << 14; + bottom_t2w << 2; + + left_t2x << 15; + left_t2w << 3; + + right_t2x << 14; + right_t2w << 3; + + /* + offset = 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * * * * * + + + + + * + * + + + + + + + + + * + T T T T T + * + + + + + + + + + * T T * + + + + + * * O * * * O * * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_t2x << 7; + mid_t2w << 3; + + top_t2x << 0; + top_t2w << 2; + + bottom_t2x << 14; + bottom_t2w << 2; + + left_t2x << 15; + left_t2w << 3; + + right_t2x << 14; + right_t2w << 3; + + /* + offset = 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * * * * * + + + + + * + * + + + + + + + + + + * T T T T T + + * + + + + + + + + * T T * + + + + + * O * * * O * * * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_t2x << 7; + mid_t2w << 3; + + top_t2x << 0; + top_t2w << 2; + + bottom_t2x << 14; + bottom_t2w << 2; + + left_t2x << 15; + left_t2w << 3; + + right_t2x << 14; + right_t2w << 3; + + /* + offset = 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * * * * * * * + + + + * * + + + + + + + + + + O T T T T + + + * + + + + + + + O T * + + + + O * * * O * * * * + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 4 tiles + */ + + mid_t2x << 7; + mid_t2w << 4; + + top_t2x << 0; + top_t2w << 3; + + bottom_t2x << 14; + bottom_t2w << 2; + + left_t2x << 15; + left_t2w << 4; + + right_t2x << 14; + right_t2w << 4; + + pti.zoom = 4.0; + pti.zoomString = QStringLiteral("int zoom"); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_t2x, mid_t2w, mid_t2x, mid_t2w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_t2x, mid_t2w, top_t2x, top_t2w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_t2x, mid_t2w, bottom_t2x, bottom_t2w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_t2x, left_t2w, mid_t2x, mid_t2w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_t2x, right_t2w, mid_t2x, mid_t2w); + + pti.zoom = 4.5; + pti.zoomString = QStringLiteral("frac zoom"); + pti.w = pti.w * qPow(2.0, 0.5); + pti.h = pti.h * qPow(2.0, 0.5); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_t2x, mid_t2w, mid_t2x, mid_t2w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_t2x, mid_t2w, top_t2x, top_t2w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_t2x, mid_t2w, bottom_t2x, bottom_t2w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_t2x, left_t2w, mid_t2x, mid_t2w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_t2x, right_t2w, mid_t2x, mid_t2w); + + /* + width = 2t + 1 + */ + + QList mid_t2p1x; + QList mid_t2p1w; + QList top_t2p1x; + QList top_t2p1w; + QList bottom_t2p1x; + QList bottom_t2p1w; + QList left_t2p1x; + QList left_t2p1w; + QList right_t2p1x; + QList right_t2p1w; + + pti.w = 2 * t + 1; + pti.h = 2 * t + 1; + pti.wString = QStringLiteral("(2T + 1)"); + pti.hString = QStringLiteral("(2T + 1)"); + + /* + + offset = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *+* * * *+* * * *+* + + + + *+ + +* + + + + + + +*+ + + + T T T T T*+ + + + + + + + + + *+ T T* + + + + *+* * * *T* * * *T* + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 2 + Covers: 4 tiles + */ + + mid_t2p1x << 6; + mid_t2p1w << 4; + + top_t2p1x << 0; + top_t2p1w << 2; + + bottom_t2p1x << 13; + bottom_t2p1w << 3; + + left_t2p1x << 14; + left_t2p1w << 4; + + right_t2p1x << 13; + right_t2p1w << 4; + + /* + offset = 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +* * * *+* * * *+* * + + + + +* + + * + + + + + + + +*+ + + T T T T T +*+ + + + + + + + + +* T T * + + + + +* * * *T* * * *T* * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_t2p1x << 7; + mid_t2p1w << 3; + + top_t2p1x << 0; + top_t2p1w << 2; + + bottom_t2p1x << 14; + bottom_t2p1w << 2; + + left_t2p1x << 15; + left_t2p1w << 3; + + right_t2p1x << 14; + right_t2p1w << 3; + + /* + offset = 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * *+* * * *+* * * + + + + + * + + * + + + + + + + + +*+ + T T T T T + +*+ + + + + + + + + * T T * + + + + + * * *T* * * *T* * * + + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_t2p1x << 7; + mid_t2p1w << 3; + + top_t2p1x << 0; + top_t2p1w << 2; + + bottom_t2p1x << 14; + bottom_t2p1w << 2; + + left_t2p1x << 15; + left_t2p1w << 3; + + right_t2p1x << 14; + right_t2p1w << 3; + + /* + offset = 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * *+* * * *+* * * *+ + + + + * + + *+ + + + + + + + + +*+ T T T T T + + +*+ + + + + + + + * T T *+ + + + + * *T* * * *T* * * *+ + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 3 tiles + */ + + mid_t2p1x << 7; + mid_t2p1w << 3; + + top_t2p1x << 0; + top_t2p1w << 2; + + bottom_t2p1x << 14; + bottom_t2p1w << 2; + + left_t2p1x << 15; + left_t2p1w << 3; + + right_t2p1x << 14; + right_t2p1w << 3; + + /* + offset = 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *+* * * *+* * * *+* + + + + *+ + +* + + + + + + + + + +*T T T T T + + + +*+ + + + + + + *T T +* + + + + *T* * * *T* * * *+* + + + + T T + + + + + + + + + + + T T T T T + + + + + + + + + + Starts at: T - 1 + Covers: 4 tiles + */ + + mid_t2p1x << 7; + mid_t2p1w << 4; + + top_t2p1x << 0; + top_t2p1w << 3; + + bottom_t2p1x << 14; + bottom_t2p1w << 2; + + left_t2p1x << 15; + left_t2p1w << 4; + + right_t2p1x << 14; + right_t2p1w << 4; + + pti.zoom = 4.0; + pti.zoomString = QStringLiteral("int zoom"); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_t2p1x, mid_t2p1w, mid_t2p1x, mid_t2p1w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_t2p1x, mid_t2p1w, top_t2p1x, top_t2p1w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_t2p1x, mid_t2p1w, bottom_t2p1x, bottom_t2p1w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_t2p1x, left_t2p1w, mid_t2p1x, mid_t2p1w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_t2p1x, right_t2p1w, mid_t2p1x, mid_t2p1w); + + pti.zoom = 4.5; + pti.zoomString = QStringLiteral("frac zoom"); + pti.w = pti.w * qPow(2.0, 0.5); + pti.h = pti.h * qPow(2.0, 0.5); + + pti.x = 0.5; + pti.y = 0.5; + pti.xyString = QStringLiteral("middle"); + + test_group(pti, mid_t2p1x, mid_t2p1w, mid_t2p1x, mid_t2p1w); + + pti.x = 0.5; + pti.y = 0.0; + pti.xyString = QStringLiteral("top"); + + test_group(pti, mid_t2p1x, mid_t2p1w, top_t2p1x, top_t2p1w); + + pti.x = 0.5; + pti.y = 15.0 / 16.0; + pti.xyString = QStringLiteral("bottom"); + + test_group(pti, mid_t2p1x, mid_t2p1w, bottom_t2p1x, bottom_t2p1w); + + pti.x = 0.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("left"); + + test_group(pti, left_t2p1x, left_t2p1w, mid_t2p1x, mid_t2p1w); + + pti.x = 15.0 / 16.0; + pti.y = 0.5; + pti.xyString = QStringLiteral("right"); + + test_group(pti, right_t2p1x, right_t2p1w, mid_t2p1x, mid_t2p1w); +} + +QTEST_GUILESS_MAIN(tst_QGeoCameraTiles) +#include "tst_qgeocameratiles.moc" diff --git a/tests/auto/qgeocircle/qgeocircle.pro b/tests/auto/qgeocircle/qgeocircle.pro new file mode 100644 index 0000000..eb56a7f --- /dev/null +++ b/tests/auto/qgeocircle/qgeocircle.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeocircle + +SOURCES += \ + tst_qgeocircle.cpp + +QT += positioning testlib diff --git a/tests/auto/qgeocircle/tst_qgeocircle.cpp b/tests/auto/qgeocircle/tst_qgeocircle.cpp new file mode 100644 index 0000000..01fbed6 --- /dev/null +++ b/tests/auto/qgeocircle/tst_qgeocircle.cpp @@ -0,0 +1,417 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QGeoCircle : public QObject +{ + Q_OBJECT + +private slots: + void defaultConstructor(); + void centerRadiusConstructor(); + void assignment(); + + void comparison(); + void type(); + + void radius(); + void center(); + + void translate_data(); + void translate(); + + void valid_data(); + void valid(); + + void empty_data(); + void empty(); + + void contains_data(); + void contains(); + + void extendShape(); + void extendShape_data(); + + void areaComparison(); + void areaComparison_data(); + + void boxComparison(); + void boxComparison_data(); +}; + +void tst_QGeoCircle::defaultConstructor() +{ + QGeoCircle c; + QVERIFY(!c.center().isValid()); + QCOMPARE(c.radius(), qreal(-1.0)); +} + +void tst_QGeoCircle::centerRadiusConstructor() +{ + QGeoCircle c(QGeoCoordinate(1,1), qreal(50.0)); + QCOMPARE(c.center(), QGeoCoordinate(1,1)); + QCOMPARE(c.radius(), qreal(50.0)); +} + +void tst_QGeoCircle::assignment() +{ + QGeoCircle c1 = QGeoCircle(QGeoCoordinate(10.0, 0.0), 20.0); + QGeoCircle c2 = QGeoCircle(QGeoCoordinate(20.0, 0.0), 30.0); + + QVERIFY(c1 != c2); + + c2 = c1; + QCOMPARE(c2.center(), QGeoCoordinate(10.0, 0.0)); + QCOMPARE(c2.radius(), 20.0); + QCOMPARE(c1, c2); + + c2.setCenter(QGeoCoordinate(30.0, 0.0)); + c2.setRadius(15.0); + QCOMPARE(c1.center(), QGeoCoordinate(10.0, 0.0)); + QCOMPARE(c1.radius(), 20.0); + + // Assign c1 to an area + QGeoShape area = c1; + QCOMPARE(area.type(), c1.type()); + QVERIFY(area == c1); + + // Assign the area back to a bounding circle + QGeoCircle ca = area; + QCOMPARE(ca.center(), c1.center()); + QCOMPARE(ca.radius(), c1.radius()); + + // Check that the copy is not modified when modifying the original. + c1.setCenter(QGeoCoordinate(15.0, 15.0)); + QVERIFY(ca.center() != c1.center()); + QVERIFY(ca != c1); +} + +void tst_QGeoCircle::comparison() +{ + QGeoCircle c1(QGeoCoordinate(1,1), qreal(50.0)); + QGeoCircle c2(QGeoCoordinate(1,1), qreal(50.0)); + QGeoCircle c3(QGeoCoordinate(1,1), qreal(35.0)); + QGeoCircle c4(QGeoCoordinate(1,2), qreal(50.0)); + + QVERIFY(c1 == c2); + QVERIFY(!(c1 != c2)); + + QVERIFY(!(c1 == c3)); + QVERIFY(c1 != c3); + + QVERIFY(!(c1 == c4)); + QVERIFY(c1 != c4); + + QVERIFY(!(c2 == c3)); + QVERIFY(c2 != c3); + + QGeoRectangle b1(QGeoCoordinate(20,20),QGeoCoordinate(10,30)); + QVERIFY(!(c1 == b1)); + QVERIFY(c1 != b1); + + QGeoShape *c2Ptr = &c2; + QVERIFY(c1 == *c2Ptr); + QVERIFY(!(c1 != *c2Ptr)); + + QGeoShape *c3Ptr = &c3; + QVERIFY(!(c1 == *c3Ptr)); + QVERIFY(c1 != *c3Ptr); +} + +void tst_QGeoCircle::type() +{ + QGeoCircle c; + QCOMPARE(c.type(), QGeoShape::CircleType); +} + +void tst_QGeoCircle::radius() +{ + QGeoCircle c; + c.setRadius(1.0); + QCOMPARE(c.radius(), qreal(1.0)); + c.setRadius(5.0); + QCOMPARE(c.radius(), qreal(5.0)); +} + +void tst_QGeoCircle::center() +{ + QGeoCircle c; + c.setCenter(QGeoCoordinate(1,1)); + QCOMPARE(c.center(), QGeoCoordinate(1,1)); + + QGeoShape shape = c; + QCOMPARE(shape.center(), c.center()); + + c.setCenter(QGeoCoordinate(5,10)); + QCOMPARE(c.center(), QGeoCoordinate(5,10)); +} + +void tst_QGeoCircle::translate_data() +{ + QTest::addColumn("center"); + QTest::addColumn("radius"); + QTest::addColumn("lat"); + QTest::addColumn("lon"); + QTest::addColumn("newCenter"); + + QTest::newRow("from 0,0") << QGeoCoordinate(0,0) << qreal(10.0) << + 5.0 << 5.0 << QGeoCoordinate(5.0, 5.0); + QTest::newRow("across 0,0") << QGeoCoordinate(-2, -2) << qreal(20.0) << + 5.0 << 5.0 << QGeoCoordinate(3.0, 3.0); + QTest::newRow("backwards across 0,0") << QGeoCoordinate(5,5) << qreal(50.0) + << -13.0 << 5.0 + << QGeoCoordinate(-8.0, 10.0); +} + +void tst_QGeoCircle::translate() +{ + QFETCH(QGeoCoordinate, center); + QFETCH(qreal, radius); + QFETCH(double, lat); + QFETCH(double, lon); + QFETCH(QGeoCoordinate, newCenter); + + QGeoCircle c(center, radius); + QGeoCircle d = c; + + c.translate(lat, lon); + + QCOMPARE(c.radius(), radius); + QCOMPARE(c.center(), newCenter); + + c = d.translated(lat, lon); + d.setRadius(1.0); + + QCOMPARE(c.radius(), radius); + QCOMPARE(d.center(), center); + QCOMPARE(c.center(), newCenter); +} + +void tst_QGeoCircle::valid_data() +{ + QTest::addColumn("center"); + QTest::addColumn("radius"); + QTest::addColumn("valid"); + + QTest::newRow("default") << QGeoCoordinate() << qreal(-1.0) << false; + QTest::newRow("empty coord") << QGeoCoordinate() << qreal(5.0) << false; + QTest::newRow("NaN coord") << QGeoCoordinate(500, 500) << qreal(5.0) << false; + QTest::newRow("bad radius") << QGeoCoordinate(10, 10) << qreal(-5.0) << false; + QTest::newRow("NaN radius") << QGeoCoordinate(10, 10) << qreal(qQNaN()) << false; + QTest::newRow("zero radius") << QGeoCoordinate(10, 10) << qreal(0.0) << true; + QTest::newRow("good") << QGeoCoordinate(10, 10) << qreal(5.0) << true; +} + +void tst_QGeoCircle::valid() +{ + QFETCH(QGeoCoordinate, center); + QFETCH(qreal, radius); + QFETCH(bool, valid); + + QGeoCircle c(center, radius); + QCOMPARE(c.isValid(), valid); + + QGeoShape area = c; + QCOMPARE(c.isValid(), valid); +} + +void tst_QGeoCircle::empty_data() +{ + QTest::addColumn("center"); + QTest::addColumn("radius"); + QTest::addColumn("empty"); + + QTest::newRow("default") << QGeoCoordinate() << qreal(-1.0) << true; + QTest::newRow("empty coord") << QGeoCoordinate() << qreal(5.0) << true; + QTest::newRow("NaN coord") << QGeoCoordinate(500, 500) << qreal(5.0) << true; + QTest::newRow("bad radius") << QGeoCoordinate(10, 10) << qreal(-5.0) << true; + QTest::newRow("NaN radius") << QGeoCoordinate(10, 10) << qreal(qQNaN()) << true; + QTest::newRow("zero radius") << QGeoCoordinate(10, 10) << qreal(0.0) << true; + QTest::newRow("good") << QGeoCoordinate(10, 10) << qreal(5.0) << false; +} + +void tst_QGeoCircle::empty() +{ + QFETCH(QGeoCoordinate, center); + QFETCH(qreal, radius); + QFETCH(bool, empty); + + QGeoCircle c(center, radius); + QCOMPARE(c.isEmpty(), empty); + + QGeoShape area = c; + QCOMPARE(area.isEmpty(), empty); +} + +void tst_QGeoCircle::contains_data() +{ + QTest::addColumn("center"); + QTest::addColumn("radius"); + QTest::addColumn("probe"); + QTest::addColumn("result"); + + QTest::newRow("own centre") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(1,1) << true; + QTest::newRow("over the hills") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(30, 40) << false; + QTest::newRow("at 0.5*radius") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(1.00015374,1.00015274) << true; + QTest::newRow("at 0.99*radius") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(1.00077538, 0.99955527) << true; + QTest::newRow("at 1.01*radius") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(1.00071413, 0.99943423) << false; +} + +void tst_QGeoCircle::contains() +{ + QFETCH(QGeoCoordinate, center); + QFETCH(qreal, radius); + QFETCH(QGeoCoordinate, probe); + QFETCH(bool, result); + + QGeoCircle c(center, radius); + QCOMPARE(c.contains(probe), result); + + QGeoShape area = c; + QCOMPARE(area.contains(probe), result); +} + +void tst_QGeoCircle::extendShape() +{ + QFETCH(QGeoCircle, circle); + QFETCH(QGeoCoordinate, coord); + QFETCH(bool, containsFirst); + QFETCH(bool, containsExtended); + + QCOMPARE(circle.contains(coord), containsFirst); + circle.extendShape(coord); + QCOMPARE(circle.contains(coord), containsExtended); + +} + +void tst_QGeoCircle::extendShape_data() +{ + QTest::addColumn("circle"); + QTest::addColumn("coord"); + QTest::addColumn("containsFirst"); + QTest::addColumn("containsExtended"); + + QGeoCoordinate co1(20.0, 20.0); + + QTest::newRow("own center") + << QGeoCircle(co1, 100) + << QGeoCoordinate(20.0, 20.0) + << true + << true; + QTest::newRow("inside") + << QGeoCircle(co1, 100) + << QGeoCoordinate(20.0001, 20.0001) + << true + << true; + QTest::newRow("far away") + << QGeoCircle(co1, 100) + << QGeoCoordinate(50.0001, 50.0001) + << false + << true; + QTest::newRow("invalid circle") + << QGeoCircle() + << QGeoCoordinate(20.0, 20.0) + << false + << false; + QTest::newRow("invalid coordinate") + << QGeoCircle(co1, 100) + << QGeoCoordinate(99.0, 190.0) + << false + << false; +} + +void tst_QGeoCircle::areaComparison_data() +{ + QTest::addColumn("area"); + QTest::addColumn("circle"); + QTest::addColumn("equal"); + + QGeoCircle c1(QGeoCoordinate(10.0, 0.0), 10.0); + QGeoCircle c2(QGeoCoordinate(20.0, 10.0), 20.0); + QGeoRectangle b(QGeoCoordinate(10.0, 0.0), QGeoCoordinate(0.0, 10.0)); + + QTest::newRow("default constructed") << QGeoShape() << QGeoCircle() << false; + QTest::newRow("c1 c1") << QGeoShape(c1) << c1 << true; + QTest::newRow("c1 c2") << QGeoShape(c1) << c2 << false; + QTest::newRow("c2 c1") << QGeoShape(c2) << c1 << false; + QTest::newRow("c2 c2") << QGeoShape(c2) << c2 << true; + QTest::newRow("b c1") << QGeoShape(b) << c1 << false; +} + +void tst_QGeoCircle::areaComparison() +{ + QFETCH(QGeoShape, area); + QFETCH(QGeoCircle, circle); + QFETCH(bool, equal); + + QCOMPARE((area == circle), equal); + QCOMPARE((area != circle), !equal); + + QCOMPARE((circle == area), equal); + QCOMPARE((circle != area), !equal); +} + +void tst_QGeoCircle::boxComparison_data() +{ + QTest::addColumn("box"); + QTest::addColumn("circle"); + QTest::addColumn("equal"); + + QGeoCircle c(QGeoCoordinate(10.0, 0.0), 10.0); + QGeoRectangle b(QGeoCoordinate(10.0, 0.0), QGeoCoordinate(0.0, 10.0)); + + QTest::newRow("default constructed") << QGeoRectangle() << QGeoCircle() << false; + QTest::newRow("b c") << b << c << false; +} + +void tst_QGeoCircle::boxComparison() +{ + QFETCH(QGeoRectangle, box); + QFETCH(QGeoCircle, circle); + QFETCH(bool, equal); + + QCOMPARE((box == circle), equal); + QCOMPARE((box != circle), !equal); + + QCOMPARE((circle == box), equal); + QCOMPARE((circle != box), !equal); +} + +QTEST_MAIN(tst_QGeoCircle) +#include "tst_qgeocircle.moc" diff --git a/tests/auto/qgeocodereply/qgeocodereply.pro b/tests/auto/qgeocodereply/qgeocodereply.pro new file mode 100644 index 0000000..dea3d4c --- /dev/null +++ b/tests/auto/qgeocodereply/qgeocodereply.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeocodereply + +HEADERS += ../utils/qlocationtestutils_p.h \ + tst_qgeocodereply.h +SOURCES += tst_qgeocodereply.cpp \ + ../utils/qlocationtestutils.cpp + +QT += location testlib diff --git a/tests/auto/qgeocodereply/tst_qgeocodereply.cpp b/tests/auto/qgeocodereply/tst_qgeocodereply.cpp new file mode 100644 index 0000000..bd47666 --- /dev/null +++ b/tests/auto/qgeocodereply/tst_qgeocodereply.cpp @@ -0,0 +1,275 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tst_qgeocodereply.h" + +QT_USE_NAMESPACE + +void tst_QGeoCodeReply::initTestCase() +{ + + reply = new SubGeocodeReply(); +} + +void tst_QGeoCodeReply::cleanupTestCase() +{ + + delete reply; + delete qgeolocation; +} + +void tst_QGeoCodeReply::init() +{ + qRegisterMetaType(); + signalerror = new QSignalSpy(reply, SIGNAL(error(QGeoCodeReply::Error,QString))); + signalfinished = new QSignalSpy(reply, SIGNAL(finished())); +} + +void tst_QGeoCodeReply::cleanup() +{ + delete signalerror; + delete signalfinished; +} + +void tst_QGeoCodeReply::constructor() +{ + QVERIFY(!reply->isFinished()); + + QCOMPARE(reply->limit(),-1); + QCOMPARE(reply->offset(),0); + QCOMPARE(reply->error(),QGeoCodeReply::NoError); + + QVERIFY( signalerror->isValid() ); + QVERIFY( signalfinished->isValid() ); + + QCOMPARE(signalerror->count(),0); + QCOMPARE(signalfinished->count(),0); +} + +void tst_QGeoCodeReply::constructor_error() +{ + QFETCH(QGeoCodeReply::Error,error); + QFETCH(QString,msg); + + QVERIFY( signalerror->isValid() ); + QVERIFY( signalfinished->isValid() ); + + QGeoCodeReply *qgeocodereplycopy = new QGeoCodeReply (error,msg,0); + + QCOMPARE(signalerror->count(),0); + QCOMPARE(signalfinished->count(),0); + + QCOMPARE (qgeocodereplycopy->error(),error); + QCOMPARE (qgeocodereplycopy->errorString(),msg); + + delete qgeocodereplycopy; +} + +void tst_QGeoCodeReply::constructor_error_data() +{ + QTest::addColumn("error"); + QTest::addColumn("msg"); + + QTest::newRow("error1") << QGeoCodeReply::NoError << "No error."; + QTest::newRow("error2") << QGeoCodeReply::EngineNotSetError << "Engine Not Set Error."; + QTest::newRow("error3") << QGeoCodeReply::CommunicationError << "Communication Error."; + QTest::newRow("error4") << QGeoCodeReply::ParseError << "Parse Error."; + QTest::newRow("error5") << QGeoCodeReply::UnsupportedOptionError << "Unsupported Option Error."; + QTest::newRow("error6") << QGeoCodeReply::UnknownError << "Unknown Error."; + +} + +void tst_QGeoCodeReply::destructor() +{ + QGeoCodeReply *qgeocodereplycopy; + QFETCH(QGeoCodeReply::Error,error); + QFETCH(QString,msg); + + qgeocodereplycopy = new QGeoCodeReply (error,msg,0); + delete qgeocodereplycopy; +} + +void tst_QGeoCodeReply::destructor_data() +{ + tst_QGeoCodeReply::constructor_error_data(); +} + +void tst_QGeoCodeReply::abort() +{ + QVERIFY( signalerror->isValid() ); + QVERIFY( signalfinished->isValid() ); + + QCOMPARE(signalerror->count(),0); + QCOMPARE (signalfinished->count(),0); + + reply->callSetFinished(true); + reply->abort(); + + QCOMPARE(signalerror->count(),0); + QCOMPARE (signalfinished->count(),1); + + reply->abort(); + reply->callSetFinished(false); + reply->abort(); + + QCOMPARE(signalerror->count(),0); + QCOMPARE (signalfinished->count(),2); +} + +void tst_QGeoCodeReply::error() +{ + QFETCH(QGeoCodeReply::Error,error); + QFETCH(QString,msg); + + QVERIFY( signalerror->isValid() ); + QVERIFY( signalfinished->isValid() ); + QCOMPARE(signalerror->count(),0); + + reply->callSetError(error,msg); + + QCOMPARE(signalerror->count(),1); + QCOMPARE(signalfinished->count(),1); + QCOMPARE(reply->errorString(),msg); + QCOMPARE(reply->error(),error); + + +} + +void tst_QGeoCodeReply::error_data() +{ + QTest::addColumn("error"); + QTest::addColumn("msg"); + + QTest::newRow("error1") << QGeoCodeReply::NoError << "No error."; + QTest::newRow("error2") << QGeoCodeReply::EngineNotSetError << "Engine Not Set Error."; + QTest::newRow("error3") << QGeoCodeReply::CommunicationError << "Communication Error."; + QTest::newRow("error4") << QGeoCodeReply::ParseError << "Parse Error."; + QTest::newRow("error5") << QGeoCodeReply::UnsupportedOptionError << "Unsupported Option Error."; + QTest::newRow("error6") << QGeoCodeReply::UnknownError << "Unknown Error."; +} + +void tst_QGeoCodeReply::finished() +{ + QVERIFY( signalerror->isValid() ); + QVERIFY( signalfinished->isValid() ); + + QCOMPARE(signalerror->count(),0); + QCOMPARE (signalfinished->count(),0); + + reply->callSetFinished(true); + QVERIFY(reply->isFinished()); + QCOMPARE(signalerror->count(),0); + QCOMPARE (signalfinished->count(),1); + + reply->callSetFinished(false); + + QVERIFY(!reply->isFinished()); + QCOMPARE(signalerror->count(),0); + QCOMPARE (signalfinished->count(),1); + + reply->callSetFinished(true); + + QVERIFY(reply->isFinished()); + QCOMPARE(signalerror->count(),0); + QCOMPARE (signalfinished->count(),2); +} + + + +void tst_QGeoCodeReply::limit() +{ + int limit =30; + reply->callSetLimit(limit); + QCOMPARE(reply->limit(),limit); +} + +void tst_QGeoCodeReply::offset() +{ + int offset = 2; + reply->callSetOffset(offset); + QCOMPARE(reply->offset(),offset); +} + +void tst_QGeoCodeReply::locations() +{ + QList geolocations; + geolocations = reply->locations(); + + QCOMPARE(geolocations.size(),0); + + QGeoAddress *qgeoaddress = new QGeoAddress (); + qgeoaddress->setCity("Berlin"); + + QGeoCoordinate *qgeocoordinate = new QGeoCoordinate (12.12 , 54.43); + + qgeolocation = new QGeoLocation (); + qgeolocation->setAddress(*qgeoaddress); + qgeolocation->setCoordinate(*qgeocoordinate); + + reply->callAddLocation(*qgeolocation); + + geolocations = reply->locations(); + QCOMPARE(geolocations.size(),1); + QCOMPARE(geolocations.at(0),*qgeolocation); + + QGeoLocation *qgeolocationcopy = new QGeoLocation (*qgeolocation); + + QList qgeolocations; + qgeolocations.append(*qgeolocation); + qgeolocations.append(*qgeolocationcopy); + + reply->callSetLocations(qgeolocations); + + geolocations = reply->locations(); + + QCOMPARE(geolocations.size(),qgeolocations.size()); + for (int i = 0 ; i < geolocations.size(); i++) + { + QCOMPARE(geolocations.at(i),qgeolocations.at(i)); + } + + delete qgeoaddress; + delete qgeocoordinate; + delete qgeolocationcopy; +} + +void tst_QGeoCodeReply::viewport() +{ + QGeoCoordinate *qgeocoordinate = new QGeoCoordinate (12.12 , 54.43); + + qgeoboundingbox = new QGeoRectangle (*qgeocoordinate, 0.5 , 0.5); + + reply->callSetViewport(*qgeoboundingbox); + + QCOMPARE (reply->viewport(), static_cast(*qgeoboundingbox)); + + delete qgeocoordinate; + delete qgeoboundingbox; +} + +QTEST_MAIN(tst_QGeoCodeReply); diff --git a/tests/auto/qgeocodereply/tst_qgeocodereply.h b/tests/auto/qgeocodereply/tst_qgeocodereply.h new file mode 100644 index 0000000..3db16da --- /dev/null +++ b/tests/auto/qgeocodereply/tst_qgeocodereply.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_QGEOCODEREPLY_H +#define TST_QGEOCODEREPLY_H + +#include +#include +#include +#include +#include + +#include "../utils/qlocationtestutils_p.h" + +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE +class SubGeocodeReply : public QGeoCodeReply +{ + Q_OBJECT +public: + SubGeocodeReply() : QGeoCodeReply() {} + + void callAddLocation ( const QGeoLocation & location ) {addLocation(location);} + void callSetError ( Error error, const QString & errorString ) {setError(error, errorString);} + void callSetFinished ( bool finished ) {setFinished(finished);} + void callSetLimit ( int limit ) {setLimit(limit);} + void callSetOffset ( int offset ) {setOffset(offset);} + void callSetLocations ( const QList & locations ) {setLocations(locations);} + void callSetViewport ( const QGeoShape &viewport ) {setViewport(viewport);} + +}; + +class tst_QGeoCodeReply :public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + //Start Unit Test for QGeoCodeReply +private slots: + void constructor(); + void constructor_error(); + void constructor_error_data(); + void destructor(); + void destructor_data(); + void abort(); + void error(); + void error_data(); + void finished(); + void limit(); + void offset(); + void locations(); + void viewport(); + + //End Unit Test for QGeoCodeReply + + + +private: + QSignalSpy *signalerror; + QSignalSpy *signalfinished; + SubGeocodeReply* reply; + QGeoLocation *qgeolocation; + QGeoRectangle *qgeoboundingbox; +}; + +Q_DECLARE_METATYPE(QList); +Q_DECLARE_METATYPE(QGeoCodeReply::Error); + +#endif // TST_QGEOCODEREPLY_H + diff --git a/tests/auto/qgeocodingmanager/qgeocodingmanager.pro b/tests/auto/qgeocodingmanager/qgeocodingmanager.pro new file mode 100644 index 0000000..373f1ff --- /dev/null +++ b/tests/auto/qgeocodingmanager/qgeocodingmanager.pro @@ -0,0 +1,12 @@ +CONFIG += testcase +TARGET = tst_qgeocodingmanager + +HEADERS += ../utils/qlocationtestutils_p.h \ + tst_qgeocodingmanager.h + +SOURCES += tst_qgeocodingmanager.cpp \ + ../utils/qlocationtestutils.cpp + +CONFIG -= app_bundle + +QT += location testlib diff --git a/tests/auto/qgeocodingmanager/tst_qgeocodingmanager.cpp b/tests/auto/qgeocodingmanager/tst_qgeocodingmanager.cpp new file mode 100644 index 0000000..581b3c4 --- /dev/null +++ b/tests/auto/qgeocodingmanager/tst_qgeocodingmanager.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include "tst_qgeocodingmanager.h" + +QT_USE_NAMESPACE + + +void tst_QGeoCodingManager::initTestCase() +{ + /* + * Set custom path since CI doesn't install test plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif + tst_QGeoCodingManager::loadGeocodingManager(); +} + +void tst_QGeoCodingManager::cleanupTestCase() +{ + delete qgeoserviceprovider; +} + +void tst_QGeoCodingManager::init() +{ + qRegisterMetaType(); + qRegisterMetaType(); + + signalerror = new QSignalSpy(qgeocodingmanager, SIGNAL(error(QGeoCodeReply*,QGeoCodeReply::Error,QString))); + signalfinished = new QSignalSpy(qgeocodingmanager, SIGNAL(finished(QGeoCodeReply*))); + QVERIFY( signalerror->isValid() ); + QVERIFY( signalfinished->isValid() ); +} + +void tst_QGeoCodingManager::cleanup() +{ + delete signalerror; + delete signalfinished; +} + +void tst_QGeoCodingManager::loadGeocodingManager() +{ + QStringList providers = QGeoServiceProvider::availableServiceProviders(); + QVERIFY(providers.contains("geocode.test.plugin")); + + qgeoserviceprovider = new QGeoServiceProvider("geocode.test.plugin"); + QVERIFY(qgeoserviceprovider); + QCOMPARE(qgeoserviceprovider->error(), QGeoServiceProvider::NotSupportedError); + + qgeoserviceprovider->setAllowExperimental(true); + QCOMPARE(qgeoserviceprovider->error(), QGeoServiceProvider::NoError); + QCOMPARE(qgeoserviceprovider->geocodingFeatures(), + QGeoServiceProvider::OfflineGeocodingFeature + | QGeoServiceProvider::ReverseGeocodingFeature); + + qgeocodingmanager = qgeoserviceprovider->geocodingManager(); + QVERIFY(qgeocodingmanager); +} + +void tst_QGeoCodingManager::locale() +{ + QLocale *german = new QLocale (QLocale::German, QLocale::Germany); + QLocale *english = new QLocale (QLocale::C, QLocale::AnyCountry); + + //Default Locale from the Search Engine + QCOMPARE(qgeocodingmanager->locale(),*german); + + qgeocodingmanager->setLocale(*english); + + QCOMPARE(qgeocodingmanager->locale(),*english); + + QVERIFY(qgeocodingmanager->locale() != *german); + + delete german; + delete english; +} + +void tst_QGeoCodingManager::name() +{ + QString name = "geocode.test.plugin"; + QCOMPARE(qgeocodingmanager->managerName(),name); +} + +void tst_QGeoCodingManager::version() +{ + int version=100; + QCOMPARE(qgeocodingmanager->managerVersion(),version); + +} + +void tst_QGeoCodingManager::search() +{ + QCOMPARE(signalerror->count(),0); + QCOMPARE(signalfinished->count(),0); + + QString search = "Berlin. Invaliendenstrasse"; + int limit = 10; + int offset = 2; + + QGeoCodeReply * reply = qgeocodingmanager->geocode(search, limit,offset); + + QCOMPARE(reply->errorString(),search); + QCOMPARE(signalfinished->count(),1); + QCOMPARE(signalerror->count(),0); + + delete reply; +} + +void tst_QGeoCodingManager::geocode() +{ + QCOMPARE(signalerror->count(),0); + QCOMPARE(signalfinished->count(),0); + + QGeoAddress *address = new QGeoAddress (); + QString city = "Berlin"; + address->setCity(city); + + QGeoCodeReply *reply = qgeocodingmanager->geocode(*address); + + QCOMPARE(reply->errorString(),city); + QCOMPARE(signalfinished->count(),1); + QCOMPARE(signalerror->count(),0); + + delete address; + delete reply; +} + +void tst_QGeoCodingManager::reverseGeocode() +{ + QCOMPARE(signalerror->count(), 0); + QCOMPARE(signalfinished->count(), 0); + + QGeoCoordinate *coordinate = new QGeoCoordinate(34.34, 56.65); + + QGeoCodeReply *reply = qgeocodingmanager->reverseGeocode(*coordinate); + + QCOMPARE(reply->errorString(), coordinate->toString()); + QCOMPARE(signalfinished->count(), 1); + QCOMPARE(signalerror->count(), 0); + + delete coordinate; + delete reply; + + +} + + +QTEST_GUILESS_MAIN(tst_QGeoCodingManager) + diff --git a/tests/auto/qgeocodingmanager/tst_qgeocodingmanager.h b/tests/auto/qgeocodingmanager/tst_qgeocodingmanager.h new file mode 100644 index 0000000..97dba3e --- /dev/null +++ b/tests/auto/qgeocodingmanager/tst_qgeocodingmanager.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#ifndef TST_QGEOCODINGMANAGER_H +#define TST_QGEOCODINGMANAGER_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +QT_USE_NAMESPACE + +class tst_QGeoCodingManager: public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + void locale(); + void name(); + void version(); + void search(); + void geocode(); + void reverseGeocode(); + +private: + QGeoServiceProvider *qgeoserviceprovider; + QGeoCodingManager *qgeocodingmanager; + QSignalSpy *signalerror; + QSignalSpy *signalfinished; + void loadGeocodingManager(); + +}; +Q_DECLARE_METATYPE(QGeoCodeReply*); +Q_DECLARE_METATYPE(QGeoCodeReply::Error); + +#endif + diff --git a/tests/auto/qgeocodingmanagerplugins/geocoding_plugin.json b/tests/auto/qgeocodingmanagerplugins/geocoding_plugin.json new file mode 100644 index 0000000..9ac9353 --- /dev/null +++ b/tests/auto/qgeocodingmanagerplugins/geocoding_plugin.json @@ -0,0 +1,10 @@ +{ + "Keys": ["geocode.test.plugin"], + "Provider": "geocode.test.plugin", + "Version": 100, + "Experimental": true, + "Features": [ + "OfflineGeocodingFeature", + "ReverseGeocodingFeature" + ] +} diff --git a/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerengine_test.h b/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerengine_test.h new file mode 100644 index 0000000..6d88764 --- /dev/null +++ b/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerengine_test.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCODINGMANAGERENGINE_TEST_H +#define QGEOCODINGMANAGERENGINE_TEST_H + +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class GeocodeReplyTest : public QGeoCodeReply +{ + Q_OBJECT +public: + GeocodeReplyTest(QObject *parent = 0) : QGeoCodeReply(parent) {} + + void callAddLocation ( const QGeoLocation & location ) {addLocation(location);} + void callSetError ( Error error, const QString & errorString ) {setError(error, errorString);} + void callSetFinished ( bool finished ) {setFinished(finished);} + void callSetLimit ( int limit ) {setLimit(limit);} + void callSetOffset ( int offset ) {setOffset(offset);} + void callSetLocations ( const QList & locations ) {setLocations(locations);} + void callSetViewport ( const QGeoShape &viewport ) {setViewport(viewport);} + +}; + +class QGeoCodingManagerEngineTest: public QGeoCodingManagerEngine + +{ +Q_OBJECT +public: + QGeoCodingManagerEngineTest(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) : + QGeoCodingManagerEngine(parameters) + { + Q_UNUSED(error) + Q_UNUSED(errorString) + setLocale(QLocale(QLocale::German, QLocale::Germany)); + } + + QGeoCodeReply* geocode(const QString &searchString, int limit, int offset, const QGeoShape &bounds) + { + GeocodeReplyTest *geocodereply = new GeocodeReplyTest(); + geocodereply->callSetLimit(limit); + geocodereply->callSetOffset(offset); + geocodereply->callSetViewport(bounds); + geocodereply->callSetError(QGeoCodeReply::NoError,searchString); + geocodereply->callSetFinished(true); + emit(this->finished(geocodereply)); + + return static_cast(geocodereply); + } + + QGeoCodeReply* geocode (const QGeoAddress &address, const QGeoShape &bounds) + { + GeocodeReplyTest *geocodereply = new GeocodeReplyTest(); + geocodereply->callSetViewport(bounds); + geocodereply->callSetError(QGeoCodeReply::NoError,address.city()); + geocodereply->callSetFinished(true); + emit(this->finished(geocodereply)); + + return static_cast(geocodereply); + } + + QGeoCodeReply* reverseGeocode(const QGeoCoordinate &coordinate, const QGeoShape &bounds) + { + GeocodeReplyTest *geocodereply = new GeocodeReplyTest(); + geocodereply->callSetViewport(bounds); + geocodereply->callSetError(QGeoCodeReply::NoError,coordinate.toString()); + geocodereply->callSetFinished(true); + emit(this->finished(geocodereply)); + return static_cast(geocodereply); + } +}; + +#endif diff --git a/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerplugins.pro b/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerplugins.pro new file mode 100644 index 0000000..650bccb --- /dev/null +++ b/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerplugins.pro @@ -0,0 +1,15 @@ +TARGET = qtgeoservices_geocodingplugin +QT += location + +PLUGIN_TYPE = geoservices +PLUGIN_CLASS_NAME = GeocodingTestGeoServicePlugin +PLUGIN_EXTENDS = - +load(qt_plugin) + +HEADERS += qgeocodingmanagerengine_test.h \ + qgeoserviceproviderplugin_test.h + +SOURCES += qgeoserviceproviderplugin_test.cpp + +OTHER_FILES += \ + geocoding_plugin.json diff --git a/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.cpp b/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.cpp new file mode 100644 index 0000000..c7729c2 --- /dev/null +++ b/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoserviceproviderplugin_test.h" +#include "qgeocodingmanagerengine_test.h" + +#include + +QGeoServiceProviderFactoryTest::QGeoServiceProviderFactoryTest() +{ +} + +QGeoServiceProviderFactoryTest::~QGeoServiceProviderFactoryTest() +{ +} + +QGeoCodingManagerEngine* QGeoServiceProviderFactoryTest::createGeocodingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, + QString *errorString) const +{ + return new QGeoCodingManagerEngineTest(parameters, error, errorString); +} diff --git a/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.h b/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.h new file mode 100644 index 0000000..53d2961 --- /dev/null +++ b/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDER_TEST_H +#define QGEOSERVICEPROVIDER_TEST_H + +#include +#include + +QT_USE_NAMESPACE + +class QGeoServiceProviderFactoryTest: public QObject, public QGeoServiceProviderFactory +{ + Q_OBJECT + Q_INTERFACES(QGeoServiceProviderFactory) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0" + FILE "geocoding_plugin.json") + +public: + QGeoServiceProviderFactoryTest(); + ~QGeoServiceProviderFactoryTest(); + + QGeoCodingManagerEngine* createGeocodingManagerEngine( + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const; +}; + +#endif + + diff --git a/tests/auto/qgeocoordinate/qgeocoordinate.pro b/tests/auto/qgeocoordinate/qgeocoordinate.pro new file mode 100644 index 0000000..52795e1 --- /dev/null +++ b/tests/auto/qgeocoordinate/qgeocoordinate.pro @@ -0,0 +1,8 @@ +CONFIG += testcase +TARGET = tst_qgeocoordinate + +HEADERS += ../utils/qlocationtestutils_p.h +SOURCES += tst_qgeocoordinate.cpp \ + ../utils/qlocationtestutils.cpp + +QT += positioning testlib diff --git a/tests/auto/qgeocoordinate/tst_qgeocoordinate.cpp b/tests/auto/qgeocoordinate/tst_qgeocoordinate.cpp new file mode 100644 index 0000000..fa9fd5c --- /dev/null +++ b/tests/auto/qgeocoordinate/tst_qgeocoordinate.cpp @@ -0,0 +1,951 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include "../utils/qlocationtestutils_p.h" + +#include +#include + +#include +#include + +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QGeoCoordinate::CoordinateFormat) +Q_DECLARE_METATYPE(QGeoCoordinate::CoordinateType) + +static const QGeoCoordinate BRISBANE(-27.46758, 153.027892); +static const QGeoCoordinate MELBOURNE(-37.814251, 144.963169); +static const QGeoCoordinate LONDON(51.500152, -0.126236); +static const QGeoCoordinate NEW_YORK(40.71453, -74.00713); +static const QGeoCoordinate NORTH_POLE(90, 0); +static const QGeoCoordinate SOUTH_POLE(-90, 0); + +static const QChar DEGREES_SYMB(0x00B0); + + +QByteArray tst_qgeocoordinate_debug; + +void tst_qgeocoordinate_messageHandler(QtMsgType type, const QMessageLogContext &, const QString &msg) +{ + switch (type) { + case QtDebugMsg : + tst_qgeocoordinate_debug = msg.toLocal8Bit(); + break; + default: + break; + } +} + + +class tst_QGeoCoordinate : public QObject +{ + Q_OBJECT + +private: + enum TestDataType { + Latitude, + Longitude, + Altitude + }; + +private slots: + void initTestcase() + { + qRegisterMetaType(); + QMetaType::registerEqualsComparator(); + } + + void constructor() + { + QGeoCoordinate c; + QVERIFY(!c.isValid()); + QCOMPARE(c, QGeoCoordinate()); + } + + void constructor_lat_long() + { + QFETCH(double, latitude); + QFETCH(double, longitude); + QFETCH(QGeoCoordinate::CoordinateType, type); + + QGeoCoordinate c(latitude, longitude); + QCOMPARE(c.type(), type); + if (type != QGeoCoordinate::InvalidCoordinate) { + QVERIFY(c.isValid()); + QCOMPARE(c.latitude(), latitude); + QCOMPARE(c.longitude(), longitude); + } else { + QVERIFY(!c.isValid()); + QVERIFY(c.latitude() != latitude); + QVERIFY(c.longitude() != longitude); + } + } + + void constructor_lat_long_data() + { + QTest::addColumn("latitude"); + QTest::addColumn("longitude"); + QTest::addColumn("type"); + + QTest::newRow("both zero") << 0.0 << 0.0 << QGeoCoordinate::Coordinate2D; + QTest::newRow("both negative") << -1.0 << -1.0 << QGeoCoordinate::Coordinate2D; + QTest::newRow("both positive") << 1.0 << 1.0 << QGeoCoordinate::Coordinate2D; + QTest::newRow("latitude negative") << -1.0 << 1.0 << QGeoCoordinate::Coordinate2D; + QTest::newRow("longitude negative") << 1.0 << -1.0 << QGeoCoordinate::Coordinate2D; + + QTest::newRow("both too high") << 90.1 << 180.1 << QGeoCoordinate::InvalidCoordinate; + QTest::newRow("latitude too high") << 90.1 << 0.1 << QGeoCoordinate::InvalidCoordinate; + QTest::newRow("longitude too high") << 0.1 << 180.1 << QGeoCoordinate::InvalidCoordinate; + + QTest::newRow("both too low") << -90.1 << -180.1 << QGeoCoordinate::InvalidCoordinate; + QTest::newRow("latitude too low") << -90.1 << 0.1 << QGeoCoordinate::InvalidCoordinate; + QTest::newRow("longitude too low") << 0.1 << -180.1 << QGeoCoordinate::InvalidCoordinate; + + QTest::newRow("both not too high") << 90.0 << 180.0 << QGeoCoordinate::Coordinate2D; + QTest::newRow("both not too low") << -90.0 << -180.0 << QGeoCoordinate::Coordinate2D; + + QTest::newRow("latitude too high and longitude too low") << 90.1 << -180.1 << QGeoCoordinate::InvalidCoordinate; + QTest::newRow("latitude too low and longitude too high") << -90.1 << 180.1 << QGeoCoordinate::InvalidCoordinate; + } + + void constructor_lat_long_alt() + { + QFETCH(double, latitude); + QFETCH(double, longitude); + QFETCH(double, altitude); + QFETCH(QGeoCoordinate::CoordinateType, type); + + QGeoCoordinate c(latitude, longitude, altitude); + QCOMPARE(c.type(), type); + if (type != QGeoCoordinate::InvalidCoordinate) { + QCOMPARE(c.latitude(), latitude); + QCOMPARE(c.longitude(), longitude); + QCOMPARE(c.altitude(), altitude); + } else { + QVERIFY(!c.isValid()); + QVERIFY(c.latitude() != latitude); + QVERIFY(c.longitude() != longitude); + QVERIFY(c.altitude() != altitude); + } + } + + void constructor_lat_long_alt_data() + { + QTest::addColumn("latitude"); + QTest::addColumn("longitude"); + QTest::addColumn("altitude"); + QTest::addColumn("type"); + + QTest::newRow("all zero") << 0.0 << 0.0 << 0.0 << QGeoCoordinate::Coordinate3D; + QTest::newRow("all negative") << -1.0 << -1.0 << -2.0 << QGeoCoordinate::Coordinate3D; + QTest::newRow("all positive") << 1.0 << 1.0 << 4.0 << QGeoCoordinate::Coordinate3D; + + QTest::newRow("latitude negative") << -1.0 << 1.0 << 1.0 << QGeoCoordinate::Coordinate3D; + QTest::newRow("longitude negative") << 1.0 << -1.0 << 1.0 << QGeoCoordinate::Coordinate3D; + QTest::newRow("altitude negative") << 1.0 << 1.0 << -1.0 << QGeoCoordinate::Coordinate3D; + + QTest::newRow("altitude not too high") << 1.0 << 1.0 << DBL_MAX << QGeoCoordinate::Coordinate3D; + QTest::newRow("altitude not too low") << 1.0 << 1.0 << DBL_MIN << QGeoCoordinate::Coordinate3D; + + QTest::newRow("all not too high") << 90.0 << 180.0 << DBL_MAX << QGeoCoordinate::Coordinate3D; + QTest::newRow("all not too low") << -90.0 << -180.0 << DBL_MIN << QGeoCoordinate::Coordinate3D; + + QTest::newRow("all too high") << 90.1 << 180.1 << DBL_MAX << QGeoCoordinate::InvalidCoordinate; + QTest::newRow("all too low") << -90.1 << -180.1 << DBL_MIN << QGeoCoordinate::InvalidCoordinate; + } + + void copy_constructor() + { + QFETCH(QGeoCoordinate, c); + + QGeoCoordinate copy(c); + QCOMPARE(copy.type(), c.type()); + if (c.type() != QGeoCoordinate::InvalidCoordinate) { + QCOMPARE(copy.latitude(), c.latitude()); + QCOMPARE(copy.longitude(), c.longitude()); + if (c.type() == QGeoCoordinate::Coordinate3D) + QCOMPARE(copy.altitude(), c.altitude()); + } + } + + void copy_constructor_data() + { + QTest::addColumn("c"); + + QTest::newRow("no argument") << QGeoCoordinate(); + QTest::newRow("latitude, longitude arguments all zero") << QGeoCoordinate(0.0, 0.0); + + QTest::newRow("latitude, longitude arguments not too high") << QGeoCoordinate(90.0, 180.0); + QTest::newRow("latitude, longitude arguments not too low") << QGeoCoordinate(-90.0, -180.0); + QTest::newRow("latitude, longitude arguments too high") << QGeoCoordinate(90.1, 180.1); + QTest::newRow("latitude, longitude arguments too low") << QGeoCoordinate(-90.1, -180.1); + + QTest::newRow("latitude, longitude, altitude arguments all zero") << QGeoCoordinate(0.0, 0.0, 0.0); + QTest::newRow("latitude, longitude, altitude arguments not too high values") << QGeoCoordinate(90.0, 180.0, DBL_MAX); + QTest::newRow("latitude, longitude, altitude arguments not too low values") << QGeoCoordinate(-90.0, -180.0, DBL_MIN); + + QTest::newRow("latitude, longitude, altitude arguments too high latitude & longitude") << QGeoCoordinate(90.1, 180.1, DBL_MAX); + QTest::newRow("latitude, longitude, altitude arguments too low latitude & longitude") << QGeoCoordinate(-90.1, -180.1, DBL_MAX); + } + + void destructor() + { + QGeoCoordinate *coordinate; + + coordinate = new QGeoCoordinate(); + delete coordinate; + + coordinate = new QGeoCoordinate(0.0, 0.0); + delete coordinate; + + coordinate = new QGeoCoordinate(0.0, 0.0, 0.0); + delete coordinate; + + coordinate = new QGeoCoordinate(90.0, 180.0); + delete coordinate; + + coordinate = new QGeoCoordinate(-90.0, -180.0); + delete coordinate; + + coordinate = new QGeoCoordinate(90.1, 180.1); + delete coordinate; + + coordinate = new QGeoCoordinate(-90.1, -180.1); + delete coordinate; + } + + void destructor2() + { + QFETCH(QGeoCoordinate, c); + QGeoCoordinate *coordinate = new QGeoCoordinate(c); + delete coordinate; + } + + void destructor2_data() + { + copy_constructor_data(); + } + + void assign() + { + QFETCH(QGeoCoordinate, c); + + QGeoCoordinate c1 = c; + QCOMPARE(c.type(), c1.type()); + if (c.isValid()) { + QCOMPARE(c.latitude(), c.latitude()); + QCOMPARE(c.longitude(), c.longitude()); + if (c.type() == QGeoCoordinate::Coordinate3D) + QCOMPARE(c.altitude(), c.altitude()); + } + } + + void assign_data() + { + copy_constructor_data(); + } + + void comparison() + { + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(bool, result); + + QCOMPARE(c1 == c2, result); + QVariant v1 = QVariant::fromValue(c1); + QVariant v2 = QVariant::fromValue(c2); + QCOMPARE(v2 == v1, result); + } + + void comparison_data() + { + QTest::addColumn("c1"); + QTest::addColumn("c2"); + QTest::addColumn("result"); + + QTest::newRow("Invalid != BRISBANE") + << QGeoCoordinate(-190,-1000) << BRISBANE << false; + QTest::newRow("BRISBANE != MELBOURNE") + << BRISBANE << MELBOURNE << false; + QTest::newRow("equal") + << BRISBANE << BRISBANE << true; + QTest::newRow("LONDON != uninitialized data") + << LONDON << QGeoCoordinate() << false; + QTest::newRow("uninitialized data == uninitialized data") + << QGeoCoordinate() << QGeoCoordinate() << true; + QTest::newRow("invalid == same invalid") + << QGeoCoordinate(-190,-1000) << QGeoCoordinate(-190,-1000) << true; + QTest::newRow("invalid == different invalid") + << QGeoCoordinate(-190,-1000) << QGeoCoordinate(190,1000) << true; + QTest::newRow("valid != another valid") + << QGeoCoordinate(-90,-180) << QGeoCoordinate(-45,+45) << false; + QTest::newRow("valid == same valid") + << QGeoCoordinate(-90,-180) << QGeoCoordinate(-90,-180) << true; + QTest::newRow("different longitudes at north pole are equal") + << QGeoCoordinate(90, 0) << QGeoCoordinate(90, 45) << true; + QTest::newRow("different longitudes at south pole are equal") + << QGeoCoordinate(-90, 0) << QGeoCoordinate(-90, 45) << true; + } + + void type() + { + QFETCH(QGeoCoordinate, c); + QFETCH(QGeoCoordinate::CoordinateType, type); + + QCOMPARE(c.type(), type); + } + + void type_data() + { + QTest::addColumn("c"); + QTest::addColumn("type"); + + QGeoCoordinate c; + + QTest::newRow("no values set") << c << QGeoCoordinate::InvalidCoordinate; + + c.setAltitude(1.0); + QTest::newRow("only altitude is set") << c << QGeoCoordinate::InvalidCoordinate; + + c.setLongitude(1.0); + QTest::newRow("only latitude and altitude is set") << c << QGeoCoordinate::InvalidCoordinate; + + c.setLatitude(-1.0); + QTest::newRow("all valid: 3D Coordinate") << c << QGeoCoordinate::Coordinate3D; + + c.setLatitude(-90.1); + QTest::newRow("too low latitude and valid longitude") << c << QGeoCoordinate::InvalidCoordinate; + + c.setLongitude(-180.1); + c.setLatitude(90.0); + QTest::newRow("valid latitude and too low longitude") << c << QGeoCoordinate::InvalidCoordinate; + + c.setLatitude(90.1); + c.setLongitude(-180.0); + QTest::newRow("too high latitude and valid longitude") << c << QGeoCoordinate::InvalidCoordinate; + + c.setLatitude(-90.0); + c.setLongitude(180.1); + QTest::newRow("valid latitude and too high longitude") << c << QGeoCoordinate::InvalidCoordinate; + } + + void valid() + { + QFETCH(QGeoCoordinate, c); + QCOMPARE(c.isValid(), c.type() != QGeoCoordinate::InvalidCoordinate); + } + + void valid_data() + { + type_data(); + } + + void addDataValues(TestDataType type) + { + QTest::addColumn("value"); + QTest::addColumn("valid"); + + QTest::newRow("negative") << -1.0 << true; + QTest::newRow("zero") << 0.0 << true; + QTest::newRow("positive") << 1.0 << true; + + switch (type) { + case Latitude: + QTest::newRow("too low") << -90.1 << false; + QTest::newRow("not too low") << -90.0 << true; + QTest::newRow("not too hight") << 90.0 << true; + QTest::newRow("too high") << 90.1; + break; + case Longitude: + QTest::newRow("too low") << -180.1 << false; + QTest::newRow("not too low") << -180.0 << true; + QTest::newRow("not too hight") << 180.0 << true; + QTest::newRow("too high") << 180.1; + break; + case Altitude: + break; + } + } + + void latitude() + { + QFETCH(double, value); + QGeoCoordinate c; + c.setLatitude(value); + QCOMPARE(c.latitude(), value); + + QGeoCoordinate c2 = c; + QCOMPARE(c.latitude(), value); + QCOMPARE(c2, c); + } + void latitude_data() { addDataValues(Latitude); } + + void longitude() + { + QFETCH(double, value); + QGeoCoordinate c; + c.setLongitude(value); + QCOMPARE(c.longitude(), value); + + QGeoCoordinate c2 = c; + QCOMPARE(c.longitude(), value); + QCOMPARE(c2, c); + } + void longitude_data() { addDataValues(Longitude); } + + void altitude() + { + QFETCH(double, value); + QGeoCoordinate c; + c.setAltitude(value); + QCOMPARE(c.altitude(), value); + + QGeoCoordinate c2 = c; + QCOMPARE(c.altitude(), value); + QCOMPARE(c2, c); + } + void altitude_data() { addDataValues(Altitude); } + + void distanceTo() + { + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(qreal, distance); + + QCOMPARE(QString::number(c1.distanceTo(c2)), QString::number(distance)); + } + + void distanceTo_data() + { + QTest::addColumn("c1"); + QTest::addColumn("c2"); + QTest::addColumn("distance"); + + QTest::newRow("invalid coord 1") + << QGeoCoordinate() << BRISBANE << qreal(0.0); + QTest::newRow("invalid coord 2") + << BRISBANE << QGeoCoordinate() << qreal(0.0); + QTest::newRow("brisbane -> melbourne") + << BRISBANE << MELBOURNE << qreal(1374820.1618767744); + QTest::newRow("london -> new york") + << LONDON << NEW_YORK << qreal(5570538.4987236429); + QTest::newRow("north pole -> south pole") + << NORTH_POLE << SOUTH_POLE << qreal(20015109.4154876769); + } + + void azimuthTo() + { + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(qreal, azimuth); + + qreal result = c1.azimuthTo(c2); + QVERIFY(result >= 0.0); + QVERIFY(result < 360.0); + QCOMPARE(QString::number(result), QString::number(azimuth)); + } + + void azimuthTo_data() + { + QTest::addColumn("c1"); + QTest::addColumn("c2"); + QTest::addColumn("azimuth"); + + QTest::newRow("invalid coord 1") + << QGeoCoordinate() << BRISBANE << qreal(0.0); + QTest::newRow("invalid coord 2") + << BRISBANE << QGeoCoordinate() << qreal(0.0); + QTest::newRow("brisbane -> melbourne") + << BRISBANE << MELBOURNE << qreal(211.1717286649); + QTest::newRow("london -> new york") + << LONDON << NEW_YORK << qreal(288.3388804508); + QTest::newRow("north pole -> south pole") + << NORTH_POLE << SOUTH_POLE << qreal(180.0); + QTest::newRow("Almost 360degrees bearing") + << QGeoCoordinate(0.5,45.0,0.0) << QGeoCoordinate(0.5,-134.9999651,0.0) << qreal(359.998); + } + + void atDistanceAndAzimuth() + { + QFETCH(QGeoCoordinate, origin); + QFETCH(qreal, distance); + QFETCH(qreal, azimuth); + QFETCH(QGeoCoordinate, result); + + QCOMPARE(result, origin.atDistanceAndAzimuth(distance, azimuth)); + } + + void atDistanceAndAzimuth_data() + { + QTest::addColumn("origin"); + QTest::addColumn("distance"); + QTest::addColumn("azimuth"); + QTest::addColumn("result"); + + QTest::newRow("invalid coord") + << QGeoCoordinate() + << qreal(1000.0) + << qreal(10.0) + << QGeoCoordinate(); + if (sizeof(qreal) == sizeof(double)) { + QTest::newRow("brisbane -> melbourne") + << BRISBANE + << qreal(1374820.1618767744) + << qreal(211.1717286649) + << MELBOURNE; + QTest::newRow("london -> new york") + << LONDON + << qreal(5570538.4987236429) + << qreal(288.3388804508) + << NEW_YORK; + QTest::newRow("north pole -> south pole") + << NORTH_POLE + << qreal(20015109.4154876769) + << qreal(180.0) + << SOUTH_POLE; + } else { + QTest::newRow("brisbane -> melbourne") + << BRISBANE + << qreal(1374820.1618767744) + << qreal(211.1717286649) + << QGeoCoordinate(-37.8142515084775, 144.963170622944); + QTest::newRow("london -> new york") + << LONDON + << qreal(5570538.4987236429) + << qreal(288.3388804508) + << QGeoCoordinate(40.7145220608416, -74.0071216045375); + QTest::newRow("north pole -> south pole") + << NORTH_POLE + << qreal(20015109.4154876769) + << qreal(180.0) + << QGeoCoordinate(-89.9999947369857, -90.0); + } + } + + void degreesToString() + { + QFETCH(QGeoCoordinate, coord); + QFETCH(QGeoCoordinate::CoordinateFormat, format); + QFETCH(QString, string); + + QCOMPARE(coord.toString(format), string); + } + + void degreesToString_data() + { + QTest::addColumn("coord"); + QTest::addColumn("format"); + QTest::addColumn("string"); + + QGeoCoordinate northEast(27.46758, 153.027892); + QGeoCoordinate northEastWithAlt(27.46758, 153.027892, 28.23411); + QGeoCoordinate southEast(-27.46758, 153.027892); + QGeoCoordinate southEastWithAlt(-27.46758, 153.027892, 28.23411); + QGeoCoordinate northWest(27.46758, -153.027892); + QGeoCoordinate northWestWithAlt(27.46758, -153.027892, 28.23411); + QGeoCoordinate southWest(-27.46758, -153.027892); + QGeoCoordinate southWestWithAlt(-27.46758, -153.027892, 28.23411); + + QGeoCoordinate empty; + QGeoCoordinate toohigh(90.1, 180.1); + QGeoCoordinate toolow(-90.1, -180.1); + QGeoCoordinate zeroLatLong(0.0, 0.0); + QGeoCoordinate allZero(0.0, 0.0, 0.0); + + QTest::newRow("empty, dd, no hemisphere") + << empty << QGeoCoordinate::Degrees + << QString(); + QTest::newRow("empty, dd, hemisphere") + << empty << QGeoCoordinate::DegreesWithHemisphere + << QString(); + QTest::newRow("empty, dm, no hemisphere") + << empty << QGeoCoordinate::DegreesMinutes + << QString(); + QTest::newRow("empty, dm, hemisphere") + << empty << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString(); + QTest::newRow("empty, dms, no hemisphere") + << empty << QGeoCoordinate::DegreesMinutesSeconds + << QString(); + QTest::newRow("empty, dms, hemisphere") + << empty << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString(); + + QTest::newRow("too low, dd, no hemisphere") + << toolow << QGeoCoordinate::Degrees + << QString(); + QTest::newRow("too low, dd, hemisphere") + << toolow << QGeoCoordinate::DegreesWithHemisphere + << QString(); + QTest::newRow("too low, dm, no hemisphere") + << toolow << QGeoCoordinate::DegreesMinutes + << QString(); + QTest::newRow("too low, dm, hemisphere") + << toolow << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString(); + QTest::newRow("too low, dms, no hemisphere") + << toolow << QGeoCoordinate::DegreesMinutesSeconds + << QString(); + QTest::newRow("too low, dms, hemisphere") + << toolow << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString(); + + QTest::newRow("too high, dd, no hemisphere") + << toohigh << QGeoCoordinate::Degrees + << QString(); + QTest::newRow("too high, dd, hemisphere") + << toohigh << QGeoCoordinate::DegreesWithHemisphere + << QString(); + QTest::newRow("too high, dm, no hemisphere") + << toohigh << QGeoCoordinate::DegreesMinutes + << QString(); + QTest::newRow("too high, dm, hemisphere") + << toohigh << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString(); + QTest::newRow("too high, dms, no hemisphere") + << toohigh << QGeoCoordinate::DegreesMinutesSeconds + << QString(); + QTest::newRow("too high, dms, hemisphere") + << toohigh << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString(); + + QTest::newRow("zeroLatLong, dd, no hemisphere") + << zeroLatLong << QGeoCoordinate::Degrees + << QString("0.00000%1, 0.00000%1").arg(DEGREES_SYMB); + QTest::newRow("zeroLatLong, dd, hemisphere") + << zeroLatLong << QGeoCoordinate::DegreesWithHemisphere + << QString("0.00000%1, 0.00000%1").arg(DEGREES_SYMB); + QTest::newRow("zeroLatLong, dm, no hemisphere") + << zeroLatLong << QGeoCoordinate::DegreesMinutes + << QString("0%1 0.000', 0%1 0.000'").arg(DEGREES_SYMB); + QTest::newRow("zeroLatLong, dm, hemisphere") + << zeroLatLong << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("0%1 0.000', 0%1 0.000'").arg(DEGREES_SYMB); + QTest::newRow("zeroLatLong, dms, no hemisphere") + << zeroLatLong << QGeoCoordinate::DegreesMinutesSeconds + << QString("0%1 0' 0.0\", 0%1 0' 0.0\"").arg(DEGREES_SYMB); + QTest::newRow("zeroLatLong, dms, hemisphere") + << zeroLatLong << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("0%1 0' 0.0\", 0%1 0' 0.0\"").arg(DEGREES_SYMB); + + QTest::newRow("allZero, dd, no hemisphere") + << allZero << QGeoCoordinate::Degrees + << QString("0.00000%1, 0.00000%1, 0m").arg(DEGREES_SYMB); + QTest::newRow("allZero, dd, hemisphere") + << allZero << QGeoCoordinate::DegreesWithHemisphere + << QString("0.00000%1, 0.00000%1, 0m").arg(DEGREES_SYMB); + QTest::newRow("allZero, dm, no hemisphere") + << allZero << QGeoCoordinate::DegreesMinutes + << QString("0%1 0.000', 0%1 0.000', 0m").arg(DEGREES_SYMB); + QTest::newRow("allZero, dm, hemisphere") + << allZero << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("0%1 0.000', 0%1 0.000', 0m").arg(DEGREES_SYMB); + QTest::newRow("allZero, dms, no hemisphere") + << allZero << QGeoCoordinate::DegreesMinutesSeconds + << QString("0%1 0' 0.0\", 0%1 0' 0.0\", 0m").arg(DEGREES_SYMB); + QTest::newRow("allZero, dms, hemisphere") + << allZero << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("0%1 0' 0.0\", 0%1 0' 0.0\", 0m").arg(DEGREES_SYMB); + + QTest::newRow("NE, dd, no hemisphere") + << northEast << QGeoCoordinate::Degrees + << QString("27.46758%1, 153.02789%1").arg(DEGREES_SYMB); + QTest::newRow("NE, dd, hemisphere") + << northEast << QGeoCoordinate::DegreesWithHemisphere + << QString("27.46758%1 N, 153.02789%1 E").arg(DEGREES_SYMB); + QTest::newRow("NE, dm, no hemisphere") + << northEast << QGeoCoordinate::DegreesMinutes + << QString("27%1 28.055', 153%1 1.674'").arg(DEGREES_SYMB); + QTest::newRow("NE, dm, hemisphere") + << northEast << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("27%1 28.055' N, 153%1 1.674' E").arg(DEGREES_SYMB); + QTest::newRow("NE, dms, no hemisphere") + << northEast << QGeoCoordinate::DegreesMinutesSeconds + << QString("27%1 28' 3.3\", 153%1 1' 40.4\"").arg(DEGREES_SYMB); + QTest::newRow("NE, dms, hemisphere") + << northEast << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("27%1 28' 3.3\" N, 153%1 1' 40.4\" E").arg(DEGREES_SYMB); + + QTest::newRow("NE with alt, dd, no hemisphere") + << northEastWithAlt << QGeoCoordinate::Degrees + << QString("27.46758%1, 153.02789%1, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NE with alt, dd, hemisphere") + << northEastWithAlt << QGeoCoordinate::DegreesWithHemisphere + << QString("27.46758%1 N, 153.02789%1 E, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NE with alt, dm, no hemisphere") + << northEastWithAlt << QGeoCoordinate::DegreesMinutes + << QString("27%1 28.055', 153%1 1.674', 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NE with alt, dm, hemisphere") + << northEastWithAlt << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("27%1 28.055' N, 153%1 1.674' E, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NE with alt, dms, no hemisphere") + << northEastWithAlt << QGeoCoordinate::DegreesMinutesSeconds + << QString("27%1 28' 3.3\", 153%1 1' 40.4\", 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NE with alt, dms, hemisphere") + << northEastWithAlt << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("27%1 28' 3.3\" N, 153%1 1' 40.4\" E, 28.2341m").arg(DEGREES_SYMB); + + QTest::newRow("SE, dd, no hemisphere") + << southEast << QGeoCoordinate::Degrees + << QString("-27.46758%1, 153.02789%1").arg(DEGREES_SYMB); + QTest::newRow("SE, dd, hemisphere") + << southEast << QGeoCoordinate::DegreesWithHemisphere + << QString("27.46758%1 S, 153.02789%1 E").arg(DEGREES_SYMB); + QTest::newRow("SE, dm, no hemisphere") + << southEast << QGeoCoordinate::DegreesMinutes + << QString("-27%1 28.055', 153%1 1.674'").arg(DEGREES_SYMB); + QTest::newRow("SE, dm, hemisphere") + << southEast << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("27%1 28.055' S, 153%1 1.674' E").arg(DEGREES_SYMB); + QTest::newRow("SE, dms, no hemisphere") + << southEast << QGeoCoordinate::DegreesMinutesSeconds + << QString("-27%1 28' 3.3\", 153%1 1' 40.4\"").arg(DEGREES_SYMB); + QTest::newRow("SE, dms, hemisphere") + << southEast << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("27%1 28' 3.3\" S, 153%1 1' 40.4\" E").arg(DEGREES_SYMB); + + QTest::newRow("SE with alt, dd, no hemisphere, 28.2341m") + << southEastWithAlt << QGeoCoordinate::Degrees + << QString("-27.46758%1, 153.02789%1, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SE with alt, dd, hemisphere, 28.2341m") + << southEastWithAlt << QGeoCoordinate::DegreesWithHemisphere + << QString("27.46758%1 S, 153.02789%1 E, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SE with alt, dm, no hemisphere, 28.2341m") + << southEastWithAlt << QGeoCoordinate::DegreesMinutes + << QString("-27%1 28.055', 153%1 1.674', 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SE with alt, dm, hemisphere, 28.2341m") + << southEastWithAlt << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("27%1 28.055' S, 153%1 1.674' E, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SE with alt, dms, no hemisphere, 28.2341m") + << southEastWithAlt << QGeoCoordinate::DegreesMinutesSeconds + << QString("-27%1 28' 3.3\", 153%1 1' 40.4\", 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SE with alt, dms, hemisphere, 28.2341m") + << southEastWithAlt << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("27%1 28' 3.3\" S, 153%1 1' 40.4\" E, 28.2341m").arg(DEGREES_SYMB);; + + QTest::newRow("NW, dd, no hemisphere") + << northWest << QGeoCoordinate::Degrees + << QString("27.46758%1, -153.02789%1").arg(DEGREES_SYMB); + QTest::newRow("NW, dd, hemisphere") + << northWest << QGeoCoordinate::DegreesWithHemisphere + << QString("27.46758%1 N, 153.02789%1 W").arg(DEGREES_SYMB); + QTest::newRow("NW, dm, no hemisphere") + << northWest << QGeoCoordinate::DegreesMinutes + << QString("27%1 28.055', -153%1 1.674'").arg(DEGREES_SYMB); + QTest::newRow("NW, dm, hemisphere") + << northWest << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("27%1 28.055' N, 153%1 1.674' W").arg(DEGREES_SYMB); + QTest::newRow("NW, dms, no hemisphere") + << northWest << QGeoCoordinate::DegreesMinutesSeconds + << QString("27%1 28' 3.3\", -153%1 1' 40.4\"").arg(DEGREES_SYMB); + QTest::newRow("NW, dms, hemisphere") + << northWest << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("27%1 28' 3.3\" N, 153%1 1' 40.4\" W").arg(DEGREES_SYMB); + + QTest::newRow("NW with alt, dd, no hemisphere, 28.2341m") + << northWestWithAlt << QGeoCoordinate::Degrees + << QString("27.46758%1, -153.02789%1, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NW with alt, dd, hemisphere, 28.2341m") + << northWestWithAlt << QGeoCoordinate::DegreesWithHemisphere + << QString("27.46758%1 N, 153.02789%1 W, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NW with alt, dm, no hemisphere, 28.2341m") + << northWestWithAlt << QGeoCoordinate::DegreesMinutes + << QString("27%1 28.055', -153%1 1.674', 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NW with alt, dm, hemisphere, 28.2341m") + << northWestWithAlt << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("27%1 28.055' N, 153%1 1.674' W, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NW with alt, dms, no hemisphere, 28.2341m") + << northWestWithAlt << QGeoCoordinate::DegreesMinutesSeconds + << QString("27%1 28' 3.3\", -153%1 1' 40.4\", 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("NW with alt, dms, hemisphere, 28.2341m") + << northWestWithAlt << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("27%1 28' 3.3\" N, 153%1 1' 40.4\" W, 28.2341m").arg(DEGREES_SYMB); + + QTest::newRow("SW, dd, no hemisphere") + << southWest << QGeoCoordinate::Degrees + << QString("-27.46758%1, -153.02789%1").arg(DEGREES_SYMB); + QTest::newRow("SW, dd, hemisphere") + << southWest << QGeoCoordinate::DegreesWithHemisphere + << QString("27.46758%1 S, 153.02789%1 W").arg(DEGREES_SYMB); + QTest::newRow("SW, dm, no hemisphere") + << southWest << QGeoCoordinate::DegreesMinutes + << QString("-27%1 28.055', -153%1 1.674'").arg(DEGREES_SYMB); + QTest::newRow("SW, dm, hemisphere") + << southWest << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("27%1 28.055' S, 153%1 1.674' W").arg(DEGREES_SYMB); + QTest::newRow("SW, dms, no hemisphere") + << southWest << QGeoCoordinate::DegreesMinutesSeconds + << QString("-27%1 28' 3.3\", -153%1 1' 40.4\"").arg(DEGREES_SYMB); + QTest::newRow("SW, dms, hemisphere") + << southWest << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("27%1 28' 3.3\" S, 153%1 1' 40.4\" W").arg(DEGREES_SYMB); + + QTest::newRow("SW with alt, dd, no hemisphere, 28.2341m") + << southWestWithAlt << QGeoCoordinate::Degrees + << QString("-27.46758%1, -153.02789%1, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SW with alt, dd, hemisphere, 28.2341m") + << southWestWithAlt << QGeoCoordinate::DegreesWithHemisphere + << QString("27.46758%1 S, 153.02789%1 W, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SW with alt, dm, no hemisphere, 28.2341m") + << southWestWithAlt << QGeoCoordinate::DegreesMinutes + << QString("-27%1 28.055', -153%1 1.674', 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SW with alt, dm, hemisphere, 28.2341m") + << southWestWithAlt << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString("27%1 28.055' S, 153%1 1.674' W, 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SW with alt, dms, no hemisphere, 28.2341m") + << southWestWithAlt << QGeoCoordinate::DegreesMinutesSeconds + << QString("-27%1 28' 3.3\", -153%1 1' 40.4\", 28.2341m").arg(DEGREES_SYMB); + QTest::newRow("SW with alt, dms, hemisphere, 28.2341m") + << southWestWithAlt << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString("27%1 28' 3.3\" S, 153%1 1' 40.4\" W, 28.2341m").arg(DEGREES_SYMB); + + QTest::newRow("Wrap seconds to Minutes DMSH") + << QGeoCoordinate(1.1333333, 1.1333333) << QGeoCoordinate::DegreesMinutesSecondsWithHemisphere + << QString( "1%1 8' 0.0\" N, 1%1 8' 0.0\" E").arg(DEGREES_SYMB); + QTest::newRow("Wrap seconds to Minutes DMS") + << QGeoCoordinate(1.1333333, 1.1333333) << QGeoCoordinate::DegreesMinutesSeconds + << QString( "1%1 8' 0.0\", 1%1 8' 0.0\"").arg(DEGREES_SYMB); + QTest::newRow("Wrap minutes to Degrees DMH") + << QGeoCoordinate(1.999999, 1.999999) << QGeoCoordinate::DegreesMinutesWithHemisphere + << QString( "2%1 0.000' N, 2%1 0.000' E").arg(DEGREES_SYMB); + QTest::newRow("Wrap minutes to Degrees DM") + << QGeoCoordinate(1.999999, 1.999999) << QGeoCoordinate::DegreesMinutes + << QString( "2%1 0.000', 2%1 0.000'").arg(DEGREES_SYMB); + + QTest::newRow("Wrap seconds to minutes to Degrees DM -> above valid long/lat values") + << QGeoCoordinate(89.9999, 179.9999) << QGeoCoordinate::DegreesMinutesSeconds + << QString( "90%1 0' 0.0\", 180%1 0' 0.0\"").arg(DEGREES_SYMB); + + QTest::newRow("Wrap minutes to Degrees DM ->above valid long/lat values") + << QGeoCoordinate(89.9999, 179.9999) << QGeoCoordinate::DegreesMinutes + << QString( "90%1 0.000', 180%1 0.000'").arg(DEGREES_SYMB); + + } + + void datastream() + { + QFETCH(QGeoCoordinate, c); + + QByteArray ba; + QDataStream out(&ba, QIODevice::WriteOnly); + out << c; + + QDataStream in(&ba, QIODevice::ReadOnly); + QGeoCoordinate inCoord; + in >> inCoord; + QCOMPARE(inCoord, c); + } + + void datastream_data() + { + QTest::addColumn("c"); + + QTest::newRow("invalid") << QGeoCoordinate(); + QTest::newRow("valid lat, long") << BRISBANE; + QTest::newRow("valid lat, long, alt") << QGeoCoordinate(-1, -1, -1); + QTest::newRow("valid lat, long, alt again") << QGeoCoordinate(1, 1, 1); + } + + void debug() + { + QFETCH(QGeoCoordinate, c); + QFETCH(int, nextValue); + QFETCH(QByteArray, debugString); + + qInstallMessageHandler(tst_qgeocoordinate_messageHandler); + qDebug() << c << nextValue; + qInstallMessageHandler(0); + QCOMPARE(tst_qgeocoordinate_debug, debugString); + } + + void debug_data() + { + QTest::addColumn("c"); + QTest::addColumn("nextValue"); + QTest::addColumn("debugString"); + + + QTest::newRow("uninitialized") << QGeoCoordinate() << 45 + << QByteArray("QGeoCoordinate(?, ?) 45"); + QTest::newRow("initialized without altitude") << BRISBANE << 45 + << (QString("QGeoCoordinate(%1, %2) 45").arg(BRISBANE.latitude()) + .arg(BRISBANE.longitude())).toLatin1(); + QTest::newRow("invalid initialization") << QGeoCoordinate(-100,-200) << 45 + << QByteArray("QGeoCoordinate(?, ?) 45"); + QTest::newRow("initialized with altitude") << QGeoCoordinate(1,2,3) << 45 + << QByteArray("QGeoCoordinate(1, 2, 3) 45"); + } + + void hash() + { + uint s1 = qHash(QGeoCoordinate(1, 1, 2)); + uint s2 = qHash(QGeoCoordinate(2, 1, 1)); + uint s3 = qHash(QGeoCoordinate(1, 2, 1)); + uint s10 = qHash(QGeoCoordinate(0, 0, 2)); + uint s20 = qHash(QGeoCoordinate(2, 0, 0)); + uint s30 = qHash(QGeoCoordinate(0, 2, 0)); + uint s30NoAlt = qHash(QGeoCoordinate(0, 2)); + uint s30WithSeed = qHash(QGeoCoordinate(0, 2, 0), 1); + uint nullCoordinate = qHash(QGeoCoordinate()); + + uint north1 = qHash(QGeoCoordinate(90.0, 34.7, 0)); + uint north2 = qHash(QGeoCoordinate(90.0, 180, 0)); + + uint south1 = qHash(QGeoCoordinate(90.0, 67.7, 34.0)); + uint south2 = qHash(QGeoCoordinate(90.0, 111, 34.0)); + + QVERIFY(s1 != s2); + QVERIFY(s2 != s3); + QVERIFY(s1 != s3); + QVERIFY(s10 != s20); + QVERIFY(s20 != s30); + QVERIFY(s10 != s30); + QVERIFY(s30NoAlt != s30); + QVERIFY(s30WithSeed != s30); + + QVERIFY(nullCoordinate != s1); + QVERIFY(nullCoordinate != s2); + QVERIFY(nullCoordinate != s3); + QVERIFY(nullCoordinate != s10); + QVERIFY(nullCoordinate != s20); + QVERIFY(nullCoordinate != s30); + QVERIFY(nullCoordinate != s30NoAlt); + QVERIFY(nullCoordinate != s30WithSeed); + + QVERIFY(north1 == north2); + QVERIFY(south1 == south2); + } +}; + +QTEST_GUILESS_MAIN(tst_QGeoCoordinate) +#include "tst_qgeocoordinate.moc" diff --git a/tests/auto/qgeolocation/qgeolocation.pro b/tests/auto/qgeolocation/qgeolocation.pro new file mode 100644 index 0000000..3b5b3a3 --- /dev/null +++ b/tests/auto/qgeolocation/qgeolocation.pro @@ -0,0 +1,9 @@ +CONFIG += testcase +TARGET = tst_qgeolocation + +HEADERS += ../utils/qlocationtestutils_p.h \ + tst_qgeolocation.h +SOURCES += tst_qgeolocation.cpp \ + ../utils/qlocationtestutils.cpp + +QT += positioning testlib diff --git a/tests/auto/qgeolocation/tst_qgeolocation.cpp b/tests/auto/qgeolocation/tst_qgeolocation.cpp new file mode 100644 index 0000000..9e40b0b --- /dev/null +++ b/tests/auto/qgeolocation/tst_qgeolocation.cpp @@ -0,0 +1,249 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tst_qgeolocation.h" + +QT_USE_NAMESPACE + +tst_QGeoLocation::tst_QGeoLocation() +{ +} + +void tst_QGeoLocation::initTestCase() +{ + +} + +void tst_QGeoLocation::cleanupTestCase() +{ + +} + +void tst_QGeoLocation::init() +{ +} + +void tst_QGeoLocation::cleanup() +{ +} + +void tst_QGeoLocation::constructor() +{ + QCOMPARE(m_location.address(), m_address); + QCOMPARE(m_location.coordinate(), m_coordinate); + QCOMPARE(m_location.boundingBox(), m_viewport); +} + +void tst_QGeoLocation::copy_constructor() +{ + QGeoLocation *qgeolocationcopy = new QGeoLocation (m_location); + QCOMPARE(m_location, *qgeolocationcopy); + delete qgeolocationcopy; +} + +void tst_QGeoLocation::destructor() +{ + QGeoLocation *qgeolocationcopy; + + qgeolocationcopy = new QGeoLocation(); + delete qgeolocationcopy; + + qgeolocationcopy = new QGeoLocation(m_location); + delete qgeolocationcopy; +} + +void tst_QGeoLocation::address() +{ + m_address.setCity("Berlin"); + m_address.setCountry("Germany"); + m_address.setCountryCode("DEU"); + m_address.setDistrict("Mitte"); + m_address.setPostalCode("10115"); + m_address.setStreet("Invalidenstrasse"); + + m_location.setAddress(m_address); + + QCOMPARE(m_location.address(),m_address); + + m_address.setPostalCode("10125"); + QVERIFY(m_location.address() != m_address); +} + +void tst_QGeoLocation::coordinate() +{ + m_coordinate.setLatitude(13.3851); + m_coordinate.setLongitude(52.5312); + m_coordinate.setAltitude(134.23); + + m_location.setCoordinate(m_coordinate); + + QCOMPARE(m_location.coordinate(), m_coordinate); + + m_coordinate.setAltitude(0); + QVERIFY(m_location.coordinate() != m_coordinate); +} + +void tst_QGeoLocation::viewport() +{ + m_coordinate.setLatitude(13.3851); + m_coordinate.setLongitude(52.5312); + + QGeoRectangle qgeoboundingboxcopy(m_coordinate, 0.4, 0.4); + m_location.setBoundingBox(qgeoboundingboxcopy); + + QCOMPARE(m_location.boundingBox(),qgeoboundingboxcopy); + + qgeoboundingboxcopy.setHeight(1); + + QVERIFY(m_location.boundingBox() != qgeoboundingboxcopy); +} + +void tst_QGeoLocation::operators() +{ + QGeoAddress qgeoaddresscopy; + qgeoaddresscopy.setCity("Berlin"); + qgeoaddresscopy.setCountry("Germany"); + qgeoaddresscopy.setCountryCode("DEU"); + + QGeoCoordinate qgeocoordinatecopy (32.324 , 41.324 , 24.55); + + m_address.setCity("Madrid"); + m_address.setCountry("Spain"); + m_address.setCountryCode("SPA"); + + m_coordinate.setLatitude(21.3434); + m_coordinate.setLongitude(38.43443); + m_coordinate.setAltitude(634.21); + + m_location.setAddress(m_address); + m_location.setCoordinate(m_coordinate); + + //Create a copy and see that they are the same + QGeoLocation qgeolocationcopy(m_location); + QVERIFY(m_location == qgeolocationcopy); + QVERIFY(!(m_location != qgeolocationcopy)); + + //Modify one and test if they are different + qgeolocationcopy.setAddress(qgeoaddresscopy); + QVERIFY(!(m_location == qgeolocationcopy)); + QVERIFY(m_location != qgeolocationcopy); + qgeolocationcopy.setCoordinate(qgeocoordinatecopy); + QVERIFY(!(m_location == qgeolocationcopy)); + QVERIFY(m_location != qgeolocationcopy); + + //delete qgeolocationcopy; + //Asign and test that they are the same + qgeolocationcopy = m_location; + QVERIFY(m_location ==qgeolocationcopy); + QVERIFY(!(m_location != qgeolocationcopy)); +} + +void tst_QGeoLocation::comparison() +{ + QFETCH(QString, dataField); + + QGeoLocation location; + + //set address + QGeoAddress address; + address.setStreet("21 jump st"); + address.setCountry("USA"); + location.setAddress(address); + + //set coordinate + location.setCoordinate(QGeoCoordinate(5,10)); + + //set viewport + location.setBoundingBox(QGeoRectangle(QGeoCoordinate(5,5),0.4,0.4)); + + QGeoLocation otherLocation(location); + + if (dataField == "no change") { + QCOMPARE(location, otherLocation); + } else { + if (dataField == "address") { + QGeoAddress otherAddress; + otherAddress.setStreet("42 evergreen tce"); + otherAddress.setCountry("USA"); + otherLocation.setAddress(otherAddress); + } else if (dataField == "coordinate") { + otherLocation.setCoordinate(QGeoCoordinate(12,13)); + } else if (dataField == "viewport"){ + otherLocation.setBoundingBox(QGeoRectangle(QGeoCoordinate(1,2), 0.5,0.5)); + } else { + qFatal("Unknown data field to test"); + } + + QVERIFY(location != otherLocation); + } +} + +void tst_QGeoLocation::comparison_data() +{ + QTest::addColumn ("dataField"); + QTest::newRow("no change") << "no change"; + QTest::newRow("address") << "address"; + QTest::newRow("coordinate") << "coordinate"; +} + +void tst_QGeoLocation::isEmpty() +{ + QGeoAddress address; + address.setCity(QStringLiteral("Braunschweig")); + QVERIFY(!address.isEmpty()); + + QGeoRectangle boundingBox; + boundingBox.setTopLeft(QGeoCoordinate(1, -1)); + boundingBox.setBottomRight(QGeoCoordinate(-1, 1)); + QVERIFY(!boundingBox.isEmpty()); + + QGeoLocation location; + + QVERIFY(location.isEmpty()); + + // address + location.setAddress(address); + QVERIFY(!location.isEmpty()); + location.setAddress(QGeoAddress()); + QVERIFY(location.isEmpty()); + + // coordinate + location.setCoordinate(QGeoCoordinate(1, 2)); + QVERIFY(!location.isEmpty()); + location.setCoordinate(QGeoCoordinate()); + QVERIFY(location.isEmpty()); + + // bounding box + location.setBoundingBox(boundingBox); + QVERIFY(!location.isEmpty()); + location.setBoundingBox(QGeoRectangle()); + QVERIFY(location.isEmpty()); +} + +QTEST_APPLESS_MAIN(tst_QGeoLocation); + diff --git a/tests/auto/qgeolocation/tst_qgeolocation.h b/tests/auto/qgeolocation/tst_qgeolocation.h new file mode 100644 index 0000000..182cad2 --- /dev/null +++ b/tests/auto/qgeolocation/tst_qgeolocation.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_QGEOLOCATION_H +#define TST_QGEOLOCATION_H + +#include +#include +#include +#include + +#include "../utils/qlocationtestutils_p.h" +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QGeoLocation : public QObject +{ + Q_OBJECT + +public: + tst_QGeoLocation(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + //Start Unit Tests for qgeolocation.h + void constructor(); + void copy_constructor(); + void destructor(); + void address(); + void coordinate(); + void viewport(); + void operators(); + void comparison(); + void comparison_data(); + void isEmpty(); + //End Unit Tests for qgeolocation.h + +private: + QGeoLocation m_location; + + QGeoAddress m_address; + QGeoCoordinate m_coordinate; + QGeoRectangle m_viewport; +}; + +Q_DECLARE_METATYPE( QGeoCoordinate::CoordinateFormat); +Q_DECLARE_METATYPE( QGeoCoordinate::CoordinateType); +Q_DECLARE_METATYPE( QList); + +#endif + diff --git a/tests/auto/qgeomaneuver/qgeomaneuver.pro b/tests/auto/qgeomaneuver/qgeomaneuver.pro new file mode 100644 index 0000000..670d0cd --- /dev/null +++ b/tests/auto/qgeomaneuver/qgeomaneuver.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeomaneuver + +# Input +HEADERS += ../utils/qlocationtestutils_p.h \ + tst_qgeomaneuver.h +SOURCES += tst_qgeomaneuver.cpp \ + ../utils/qlocationtestutils.cpp + +QT += location testlib diff --git a/tests/auto/qgeomaneuver/tst_qgeomaneuver.cpp b/tests/auto/qgeomaneuver/tst_qgeomaneuver.cpp new file mode 100644 index 0000000..25d5bf7 --- /dev/null +++ b/tests/auto/qgeomaneuver/tst_qgeomaneuver.cpp @@ -0,0 +1,257 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tst_qgeomaneuver.h" + + +tst_QGeoManeuver::tst_QGeoManeuver() +{ +} + +void tst_QGeoManeuver::initTestCase() +{ + +} + +void tst_QGeoManeuver::cleanupTestCase() +{ + +} + +void tst_QGeoManeuver::init() +{ + + qgeomaneuver = new QGeoManeuver(); +} + +void tst_QGeoManeuver::cleanup() +{ + delete qgeomaneuver; +} + +void tst_QGeoManeuver::constructor() +{ + QString empty =""; + + QVERIFY(!qgeomaneuver->isValid()); + QCOMPARE(qgeomaneuver->direction(),QGeoManeuver::NoDirection); + QCOMPARE(qgeomaneuver->distanceToNextInstruction(), qreal(0.0)); + QCOMPARE(qgeomaneuver->instructionText(),empty); + QCOMPARE(qgeomaneuver->timeToNextInstruction(),0); +} + +void tst_QGeoManeuver::copy_constructor() +{ + QGeoManeuver *qgeomaneuvercopy = new QGeoManeuver (*qgeomaneuver); + + QCOMPARE(*qgeomaneuver,*qgeomaneuvercopy); + + delete qgeomaneuvercopy; +} + +void tst_QGeoManeuver::destructor() +{ + QGeoManeuver *qgeomaneuvercopy; + + qgeomaneuvercopy = new QGeoManeuver(); + delete qgeomaneuvercopy; + + qgeomaneuvercopy = new QGeoManeuver(*qgeomaneuver); + delete qgeomaneuvercopy; +} + +void tst_QGeoManeuver::direction() +{ + QFETCH(QGeoManeuver::InstructionDirection,direction); + + qgeomaneuver->setDirection(direction); + + QCOMPARE(qgeomaneuver->direction(),direction); +} +void tst_QGeoManeuver::direction_data() +{ + QTest::addColumn("direction"); + + QTest::newRow("instruction1") << QGeoManeuver::NoDirection; + QTest::newRow("instruction2") << QGeoManeuver::DirectionForward; + QTest::newRow("instruction3") << QGeoManeuver::DirectionBearRight; + QTest::newRow("instruction4") << QGeoManeuver::DirectionLightRight; + QTest::newRow("instruction5") << QGeoManeuver::DirectionRight; + QTest::newRow("instruction6") << QGeoManeuver::DirectionHardRight; + QTest::newRow("instruction7") << QGeoManeuver::DirectionUTurnRight; + QTest::newRow("instruction8") << QGeoManeuver::DirectionUTurnLeft; + QTest::newRow("instruction9") << QGeoManeuver::DirectionHardLeft; + QTest::newRow("instruction10") << QGeoManeuver::DirectionLeft; + QTest::newRow("instruction11") << QGeoManeuver::DirectionLightLeft; + QTest::newRow("instruction12") << QGeoManeuver::DirectionBearLeft; +} + +void tst_QGeoManeuver::distanceToNextInstruction() +{ + qreal distance = 0.0; + qgeomaneuver->setDistanceToNextInstruction(distance); + + QCOMPARE (qgeomaneuver->distanceToNextInstruction(), distance); + + distance = -3423.4324; + + QVERIFY (qgeomaneuver->distanceToNextInstruction() != distance); + + qgeomaneuver->setDistanceToNextInstruction(distance); + QCOMPARE (qgeomaneuver->distanceToNextInstruction(),distance); +} + +void tst_QGeoManeuver::instructionText() +{ + QString text = "After 50m turn left"; + + qgeomaneuver->setInstructionText(text); + + QCOMPARE (qgeomaneuver->instructionText(),text); + + text="After 40m, turn left"; + QVERIFY (qgeomaneuver->instructionText() != text); + +} + +void tst_QGeoManeuver::position() +{ + QFETCH(double, latitude); + QFETCH(double, longitude); + + qgeocoordinate = new QGeoCoordinate (latitude,longitude); + + qgeomaneuver->setPosition(*qgeocoordinate); + + QCOMPARE(qgeomaneuver->position(),*qgeocoordinate); + + delete qgeocoordinate; +} + +void tst_QGeoManeuver::position_data() +{ + QTest::addColumn("latitude"); + QTest::addColumn("longitude"); + + QTest::newRow("invalid0") << -12220.0 << 0.0; + QTest::newRow("invalid1") << 0.0 << 181.0; + + QTest::newRow("correct0") << 0.0 << 0.0; + QTest::newRow("correct1") << 90.0 << 0.0; + QTest::newRow("correct2") << 0.0 << 180.0; + QTest::newRow("correct3") << -90.0 << 0.0; + QTest::newRow("correct4") << 0.0 << -180.0; + QTest::newRow("correct5") << 45.0 << 90.0; +} + +void tst_QGeoManeuver::timeToNextInstruction() +{ + int time = 0; + qgeomaneuver->setTimeToNextInstruction(time); + + QCOMPARE (qgeomaneuver->timeToNextInstruction(),time); + + time = 35; + + QVERIFY (qgeomaneuver->timeToNextInstruction() != time); + + qgeomaneuver->setTimeToNextInstruction(time); + QCOMPARE (qgeomaneuver->timeToNextInstruction(),time); +} + +void tst_QGeoManeuver::waypoint() +{ + QFETCH(double, latitude); + QFETCH(double, longitude); + + qgeocoordinate = new QGeoCoordinate (latitude,longitude); + + qgeomaneuver->setWaypoint(*qgeocoordinate); + + QCOMPARE(qgeomaneuver->waypoint(),*qgeocoordinate); + + qgeocoordinate->setLatitude(30.3); + QVERIFY(qgeomaneuver->waypoint() != *qgeocoordinate); + + + delete qgeocoordinate; +} +void tst_QGeoManeuver::waypoint_data() +{ + QTest::addColumn("latitude"); + QTest::addColumn("longitude"); + + QTest::newRow("invalid0") << -12220.0 << 0.0; + QTest::newRow("invalid1") << 0.0 << 181.0; + + QTest::newRow("correct0") << 0.0 << 0.0; + QTest::newRow("correct1") << 90.0 << 0.0; + QTest::newRow("correct2") << 0.0 << 180.0; + QTest::newRow("correct3") << -90.0 << 0.0; + QTest::newRow("correct4") << 0.0 << -180.0; + QTest::newRow("correct5") << 45.0 << 90.0; +} + +void tst_QGeoManeuver::isValid() +{ + QVERIFY(!qgeomaneuver->isValid()); + qgeomaneuver->setDirection(QGeoManeuver::DirectionBearLeft); + QVERIFY(qgeomaneuver->isValid()); +} + +void tst_QGeoManeuver::operators(){ + + QGeoManeuver *qgeomaneuvercopy = new QGeoManeuver(*qgeomaneuver); + + QVERIFY(qgeomaneuver->operator ==(*qgeomaneuvercopy)); + QVERIFY(!qgeomaneuver->operator !=(*qgeomaneuvercopy)); + + qgeomaneuver->setDirection(QGeoManeuver::DirectionBearLeft); + qgeomaneuver->setInstructionText("Turn left in 50m"); + qgeomaneuver->setTimeToNextInstruction(60); + qgeomaneuver->setDistanceToNextInstruction(560.45); + + qgeomaneuvercopy->setDirection(QGeoManeuver::DirectionForward); + qgeomaneuvercopy->setInstructionText("Turn left in 80m"); + qgeomaneuvercopy->setTimeToNextInstruction(70); + qgeomaneuvercopy->setDistanceToNextInstruction(56065.45); + +// Not passing + QVERIFY(!(qgeomaneuver->operator ==(*qgeomaneuvercopy))); +// Not passing + QVERIFY(qgeomaneuver->operator !=(*qgeomaneuvercopy)); + + *qgeomaneuvercopy = qgeomaneuvercopy->operator =(*qgeomaneuver); + QVERIFY(qgeomaneuver->operator ==(*qgeomaneuvercopy)); + QVERIFY(!qgeomaneuver->operator !=(*qgeomaneuvercopy)); + + delete qgeomaneuvercopy; +} + + +QTEST_APPLESS_MAIN(tst_QGeoManeuver); diff --git a/tests/auto/qgeomaneuver/tst_qgeomaneuver.h b/tests/auto/qgeomaneuver/tst_qgeomaneuver.h new file mode 100644 index 0000000..aad28c8 --- /dev/null +++ b/tests/auto/qgeomaneuver/tst_qgeomaneuver.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_QGEOMANEUVER_H +#define TST_QGEOMANEUVER_H + + +#include +#include +#include +#include +#include + +#include "../utils/qlocationtestutils_p.h" +#include +#include + + +class tst_QGeoManeuver : public QObject +{ + Q_OBJECT + +public: + tst_QGeoManeuver(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + //Start unit test for QGeoRouteManeuver + void constructor(); + void copy_constructor(); + void destructor(); + void direction(); + void direction_data(); + void distanceToNextInstruction(); + void instructionText(); + void position(); + void position_data(); + void timeToNextInstruction(); + void waypoint(); + void waypoint_data(); + void isValid(); + void operators(); + //End Unit Test for QGeoRouteManeuver + +private: + QGeoManeuver *qgeomaneuver; + QGeoCoordinate *qgeocoordinate; + +}; + +Q_DECLARE_METATYPE( QList); +Q_DECLARE_METATYPE (QGeoManeuver::InstructionDirection); + +#endif // TST_QGEOMANEUVER_H + diff --git a/tests/auto/qgeopositioninfo/qgeopositioninfo.pro b/tests/auto/qgeopositioninfo/qgeopositioninfo.pro new file mode 100644 index 0000000..f928c8b --- /dev/null +++ b/tests/auto/qgeopositioninfo/qgeopositioninfo.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeopositioninfo + +SOURCES += tst_qgeopositioninfo.cpp + +QT += positioning testlib diff --git a/tests/auto/qgeopositioninfo/tst_qgeopositioninfo.cpp b/tests/auto/qgeopositioninfo/tst_qgeopositioninfo.cpp new file mode 100644 index 0000000..72904e1 --- /dev/null +++ b/tests/auto/qgeopositioninfo/tst_qgeopositioninfo.cpp @@ -0,0 +1,386 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include + +#include +#include +#include +#include +#include + +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QGeoPositionInfo) +Q_DECLARE_METATYPE(QGeoPositionInfo::Attribute) + +QByteArray tst_qgeopositioninfo_debug; + +void tst_qgeopositioninfo_messageHandler(QtMsgType type, const QMessageLogContext&, const QString &msg) +{ + switch (type) { + case QtDebugMsg : + tst_qgeopositioninfo_debug = msg.toLocal8Bit(); + break; + default: + break; + } +} + +QList tst_qgeopositioninfo_qrealTestValues() +{ + QList values; + + if (qreal(DBL_MIN) == DBL_MIN) + values << DBL_MIN; + + values << FLT_MIN; + values << -1.0 << 0.0 << 1.0; + values << FLT_MAX; + + if (qreal(DBL_MAX) == DBL_MAX) + values << DBL_MAX; + + return values; +} + +QList tst_qgeopositioninfo_getAttributes() +{ + QList attributes; + attributes << QGeoPositionInfo::Direction + << QGeoPositionInfo::GroundSpeed + << QGeoPositionInfo::VerticalSpeed + << QGeoPositionInfo::MagneticVariation + << QGeoPositionInfo::HorizontalAccuracy + << QGeoPositionInfo::VerticalAccuracy; + return attributes; +} + + +class tst_QGeoPositionInfo : public QObject +{ + Q_OBJECT + +private: + QGeoPositionInfo infoWithAttribute(QGeoPositionInfo::Attribute attribute, qreal value) + { + QGeoPositionInfo info; + info.setAttribute(attribute, value); + return info; + } + + void addTestData_info() + { + QTest::addColumn("info"); + + QTest::newRow("invalid") << QGeoPositionInfo(); + + QTest::newRow("coord") << QGeoPositionInfo(QGeoCoordinate(-27.3422,150.2342), QDateTime()); + QTest::newRow("datetime") << QGeoPositionInfo(QGeoCoordinate(), QDateTime::currentDateTime()); + + QList attributes = tst_qgeopositioninfo_getAttributes(); + QList values = tst_qgeopositioninfo_qrealTestValues(); + for (int i=0; i("coord"); + QTest::addColumn("dateTime"); + QTest::addColumn("valid"); + + QTest::newRow("both null") << QGeoCoordinate() << QDateTime() << false; + QTest::newRow("both valid") << QGeoCoordinate(1,1) << QDateTime::currentDateTime() << true; + QTest::newRow("valid coord") << QGeoCoordinate(1,1) << QDateTime() << false; + QTest::newRow("valid datetime") << QGeoCoordinate() << QDateTime::currentDateTime() << false; + QTest::newRow("valid time but not date == invalid") + << QGeoCoordinate() << QDateTime(QDate(), QTime::currentTime()) << false; + QTest::newRow("valid date but not time == valid due to QDateTime constructor") + << QGeoCoordinate() << QDateTime(QDate::currentDate(), QTime()) << false; + } + + void constructor_copy() + { + QFETCH(QGeoPositionInfo, info); + + QCOMPARE(QGeoPositionInfo(info), info); + } + + void constructor_copy_data() + { + addTestData_info(); + } + + void operator_assign() + { + QFETCH(QGeoPositionInfo, info); + + QGeoPositionInfo info2 = info; + QCOMPARE(info2, info); + } + + void operator_assign_data() + { + addTestData_info(); + } + + void operator_equals() + { + QFETCH(QGeoPositionInfo, info); + + QVERIFY(info == info); + if (info.isValid()) + QCOMPARE(info == QGeoPositionInfo(), false); + } + + void operator_equals_data() + { + addTestData_info(); + } + + void operator_notEquals() + { + QFETCH(QGeoPositionInfo, info); + + QCOMPARE(info != info, false); + if (info.isValid()) + QCOMPARE(info != QGeoPositionInfo(), true); + } + + void operator_notEquals_data() + { + addTestData_info(); + } + + void setDateTime() + { + QFETCH(QDateTime, dateTime); + + QGeoPositionInfo info; + info.setTimestamp(dateTime); + QCOMPARE(info.timestamp(), dateTime); + } + + void setDateTime_data() + { + QTest::addColumn("dateTime"); + QTest::newRow("invalid") << QDateTime(); + QTest::newRow("now") << QDateTime::currentDateTime(); + } + + void dateTime() + { + QGeoPositionInfo info; + QVERIFY(info.timestamp().isNull()); + } + + void setCoordinate() + { + + QFETCH(QGeoCoordinate, coord); + + QGeoPositionInfo info; + info.setCoordinate(coord); + QCOMPARE(info.coordinate(), coord); + } + + void setCoordinate_data() + { + QTest::addColumn("coord"); + + QTest::newRow("invalid") << QGeoCoordinate(); + QTest::newRow("valid") << QGeoCoordinate(30,30); + } + + void attribute() + { + QFETCH(QGeoPositionInfo::Attribute, attribute); + QFETCH(qreal, value); + + QGeoPositionInfo info; + QVERIFY(qIsNaN(info.attribute(attribute))); + + info.setAttribute(attribute, value); + QCOMPARE(info.attribute(attribute), value); + + info.removeAttribute(attribute); + QVERIFY(qIsNaN(info.attribute(attribute))); + } + + void attribute_data() + { + QTest::addColumn("attribute"); + QTest::addColumn("value"); + + QList attributes = tst_qgeopositioninfo_getAttributes(); + QList values = tst_qgeopositioninfo_qrealTestValues(); + for (int i=0; i> inInfo; + QCOMPARE(inInfo, info); + } + + void datastream_data() + { + addTestData_info(); + } + + void debug() + { + QFETCH(QGeoPositionInfo, info); + QFETCH(int, nextValue); + QFETCH(QByteArray, debugStringEnd); + + qInstallMessageHandler(tst_qgeopositioninfo_messageHandler); + qDebug() << info << nextValue; + qInstallMessageHandler(0); + + // use endsWith() so we don't depend on QDateTime's debug() implementation + QVERIFY2(tst_qgeopositioninfo_debug.endsWith(debugStringEnd), + qPrintable(QString::fromLatin1("'%1' does not end with '%2'"). + arg(QLatin1String(tst_qgeopositioninfo_debug), + QLatin1String(debugStringEnd)))); + } + + void debug_data() + { + QTest::addColumn("info"); + QTest::addColumn("nextValue"); + QTest::addColumn("debugStringEnd"); + + QTest::newRow("no values") << QGeoPositionInfo() << 40 + << QString("QGeoCoordinate(?, ?)) 40").toLatin1(); + + QGeoCoordinate coord(1, 1); + QTest::newRow("coord, time") << QGeoPositionInfo(coord, QDateTime::currentDateTime()) + << 40 << QByteArray("QGeoCoordinate(1, 1)) 40"); + + QGeoPositionInfo info; + info.setAttribute(QGeoPositionInfo::Direction, 1.1); + info.setAttribute(QGeoPositionInfo::GroundSpeed, 2.1); + info.setAttribute(QGeoPositionInfo::VerticalSpeed, 3.1); + info.setAttribute(QGeoPositionInfo::MagneticVariation, 4.1); + info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, 5.1); + info.setAttribute(QGeoPositionInfo::VerticalAccuracy, 6.1); + QTest::newRow("all attributes") << info << 40 + << QByteArray("QGeoCoordinate(?, ?), Direction=1.1, GroundSpeed=2.1, VerticalSpeed=3.1, MagneticVariation=4.1, HorizontalAccuracy=5.1, VerticalAccuracy=6.1) 40"); + } +}; + + +QTEST_APPLESS_MAIN(tst_QGeoPositionInfo) +#include "tst_qgeopositioninfo.moc" diff --git a/tests/auto/qgeopositioninfosource/qgeopositioninfosource.pro b/tests/auto/qgeopositioninfosource/qgeopositioninfosource.pro new file mode 100644 index 0000000..ee49425 --- /dev/null +++ b/tests/auto/qgeopositioninfosource/qgeopositioninfosource.pro @@ -0,0 +1,15 @@ +TEMPLATE = app +CONFIG+=testcase +testcase.timeout = 400 # this test is slow +TARGET=tst_qgeopositioninfosource + +HEADERS += ../utils/qlocationtestutils_p.h \ + testqgeopositioninfosource_p.h + +SOURCES += ../utils/qlocationtestutils.cpp \ + testqgeopositioninfosource.cpp \ + tst_qgeopositioninfosource.cpp + +CONFIG -= app_bundle + +QT += positioning testlib diff --git a/tests/auto/qgeopositioninfosource/testqgeopositioninfosource.cpp b/tests/auto/qgeopositioninfosource/testqgeopositioninfosource.cpp new file mode 100644 index 0000000..31ab86f --- /dev/null +++ b/tests/auto/qgeopositioninfosource/testqgeopositioninfosource.cpp @@ -0,0 +1,777 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "testqgeopositioninfosource_p.h" +#include "../utils/qlocationtestutils_p.h" + +Q_DECLARE_METATYPE(QGeoPositionInfoSource::PositioningMethod) +Q_DECLARE_METATYPE(QGeoPositionInfoSource::PositioningMethods) +Q_DECLARE_METATYPE(QGeoPositionInfo) + +#define MAX_WAITING_TIME 50000 + +// Must provide a valid source, unless testing the source +// returned by QGeoPositionInfoSource::createDefaultSource() on a system +// that has no default source +#define CHECK_SOURCE_VALID { \ + if (!m_source) { \ + if (m_testingDefaultSource && QGeoPositionInfoSource::createDefaultSource(0) == 0) \ + QSKIP("No default position source on this system"); \ + else \ + QFAIL("createTestSource() must return a valid source!"); \ + } \ + } + +class MyPositionSource : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + MyPositionSource(QObject *parent = 0) + : QGeoPositionInfoSource(parent) { + } + + QGeoPositionInfo lastKnownPosition(bool /*fromSatellitePositioningMethodsOnly = false*/) const { + return QGeoPositionInfo(); + } + + void setSupportedPositioningMethods(PositioningMethods methods) { + m_methods = methods; + } + + virtual PositioningMethods supportedPositioningMethods() const { + return m_methods; + } + virtual int minimumUpdateInterval() const { + return 0; + } + + virtual void startUpdates() {} + virtual void stopUpdates() {} + + virtual void requestUpdate(int) {} + + Error error() const { return QGeoPositionInfoSource::NoError; } + +private: + PositioningMethods m_methods; +}; + +class DefaultSourceTest : public TestQGeoPositionInfoSource +{ + Q_OBJECT +protected: + QGeoPositionInfoSource *createTestSource() { + return QGeoPositionInfoSource::createSource(QStringLiteral("test.source"), 0); + } +}; + + +TestQGeoPositionInfoSource::TestQGeoPositionInfoSource(QObject *parent) + : QObject(parent) +{ + m_testingDefaultSource = false; + /* + * Set custom path since CI doesn't install test plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif +} + +TestQGeoPositionInfoSource *TestQGeoPositionInfoSource::createDefaultSourceTest() +{ + DefaultSourceTest *test = new DefaultSourceTest; + test->m_testingDefaultSource = true; + return test; +} + +void TestQGeoPositionInfoSource::test_slot1() +{ +} + +void TestQGeoPositionInfoSource::test_slot2() +{ + m_testSlot2Called = true; +} + +void TestQGeoPositionInfoSource::base_initTestCase() +{ + qRegisterMetaType(); +} + +void TestQGeoPositionInfoSource::base_init() +{ + m_source = createTestSource(); + m_testSlot2Called = false; +} + +void TestQGeoPositionInfoSource::base_cleanup() +{ + delete m_source; + m_source = 0; +} + +void TestQGeoPositionInfoSource::base_cleanupTestCase() +{ +} + +void TestQGeoPositionInfoSource::initTestCase() +{ + base_initTestCase(); +} + +void TestQGeoPositionInfoSource::init() +{ + base_init(); +} + +void TestQGeoPositionInfoSource::cleanup() +{ + base_cleanup(); +} + +void TestQGeoPositionInfoSource::cleanupTestCase() +{ + base_cleanupTestCase(); +} + +// TC_ID_3_x_1 +void TestQGeoPositionInfoSource::constructor_withParent() +{ + QObject *parent = new QObject(); + new MyPositionSource(parent); + delete parent; +} + +// TC_ID_3_x_2 +void TestQGeoPositionInfoSource::constructor_noParent() +{ + MyPositionSource *obj = new MyPositionSource(); + delete obj; +} + +void TestQGeoPositionInfoSource::updateInterval() +{ + MyPositionSource s; + QCOMPARE(s.updateInterval(), 0); +} + +void TestQGeoPositionInfoSource::setPreferredPositioningMethods() +{ + QFETCH(QGeoPositionInfoSource::PositioningMethod, supported); + QFETCH(QGeoPositionInfoSource::PositioningMethod, preferred); + QFETCH(QGeoPositionInfoSource::PositioningMethod, resulting); + + MyPositionSource s; + s.setSupportedPositioningMethods(supported); + s.setPreferredPositioningMethods(preferred); + QCOMPARE(s.preferredPositioningMethods(), resulting); +} + +void TestQGeoPositionInfoSource::setPreferredPositioningMethods_data() +{ + QTest::addColumn("supported"); + QTest::addColumn("preferred"); + QTest::addColumn("resulting"); + + QTest::newRow("Sat supported, Sat preferred") + << QGeoPositionInfoSource::SatellitePositioningMethods + << QGeoPositionInfoSource::SatellitePositioningMethods + << QGeoPositionInfoSource::SatellitePositioningMethods; + QTest::newRow("Sat supported, Non-Sat preferred") + << QGeoPositionInfoSource::SatellitePositioningMethods + << QGeoPositionInfoSource::NonSatellitePositioningMethods + << QGeoPositionInfoSource::SatellitePositioningMethods; + QTest::newRow("Sat supported, All preferred") + << QGeoPositionInfoSource::SatellitePositioningMethods + << QGeoPositionInfoSource::AllPositioningMethods + << QGeoPositionInfoSource::SatellitePositioningMethods; + + QTest::newRow("Non-Sat supported, Sat preferred") + << QGeoPositionInfoSource::NonSatellitePositioningMethods + << QGeoPositionInfoSource::SatellitePositioningMethods + << QGeoPositionInfoSource::NonSatellitePositioningMethods; + QTest::newRow("Non-Sat supported, Non-Sat preferred") + << QGeoPositionInfoSource::NonSatellitePositioningMethods + << QGeoPositionInfoSource::NonSatellitePositioningMethods + << QGeoPositionInfoSource::NonSatellitePositioningMethods; + QTest::newRow("Non-Sat supported, All preferred") + << QGeoPositionInfoSource::NonSatellitePositioningMethods + << QGeoPositionInfoSource::AllPositioningMethods + << QGeoPositionInfoSource::NonSatellitePositioningMethods; + + QTest::newRow("All supported, Sat preferred") + << QGeoPositionInfoSource::AllPositioningMethods + << QGeoPositionInfoSource::SatellitePositioningMethods + << QGeoPositionInfoSource::SatellitePositioningMethods; + QTest::newRow("All supported, Non-Sat preferred") + << QGeoPositionInfoSource::AllPositioningMethods + << QGeoPositionInfoSource::NonSatellitePositioningMethods + << QGeoPositionInfoSource::NonSatellitePositioningMethods; + QTest::newRow("All supported, All preferred") + << QGeoPositionInfoSource::AllPositioningMethods + << QGeoPositionInfoSource::AllPositioningMethods + << QGeoPositionInfoSource::AllPositioningMethods; +} + +void TestQGeoPositionInfoSource::preferredPositioningMethods() +{ + MyPositionSource s; + QCOMPARE(s.preferredPositioningMethods(), 0); +} + +//TC_ID_3_x_1 : Create a position source with the given parent that reads from the system's default +// sources of location data +void TestQGeoPositionInfoSource::createDefaultSource() +{ + QObject *parent = new QObject; + + QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource(parent); + // now all platforms have the dummy plugin at least + QVERIFY(source != 0); + delete parent; +} + +void TestQGeoPositionInfoSource::setUpdateInterval() +{ + CHECK_SOURCE_VALID; + + QFETCH(int, interval); + QFETCH(int, expectedInterval); + + m_source->setUpdateInterval(interval); + QCOMPARE(m_source->updateInterval(), expectedInterval); +} + +void TestQGeoPositionInfoSource::setUpdateInterval_data() +{ + QTest::addColumn("interval"); + QTest::addColumn("expectedInterval"); + QGeoPositionInfoSource *source = createTestSource(); + int minUpdateInterval = source ? source->minimumUpdateInterval() : -1; + if (source) + delete source; + + QTest::newRow("0") << 0 << 0; + + if (minUpdateInterval > -1) { + QTest::newRow("INT_MIN") << INT_MIN << minUpdateInterval; + QTest::newRow("-1") << -1 << minUpdateInterval; + } + + if (minUpdateInterval > 0) { + QTest::newRow("more than minInterval") << minUpdateInterval + 1 << minUpdateInterval + 1; + QTest::newRow("equal to minInterval") << minUpdateInterval << minUpdateInterval; + } + + if (minUpdateInterval > 1) { + QTest::newRow("less then minInterval") << minUpdateInterval - 1 << minUpdateInterval; + QTest::newRow("in btw zero and minInterval") << 1 << minUpdateInterval; + } +} + +void TestQGeoPositionInfoSource::lastKnownPosition() +{ + CHECK_SOURCE_VALID; + QFETCH(QGeoPositionInfoSource::PositioningMethod, positioningMethod); + QFETCH(bool, lastKnownPositionArgument); + + if ((m_source->supportedPositioningMethods() & positioningMethod) == 0) + QSKIP("Not a supported positioning method for this position source"); + + m_source->setPreferredPositioningMethods(positioningMethod); + + QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy timeout(m_source, SIGNAL(updateTimeout())); + int time_out = 7000; + m_source->setUpdateInterval(time_out); + m_source->startUpdates(); + + // Use QEventLoop instead of qWait() to ensure we stop as soon as a + // position is emitted (otherwise the lastKnownPosition() may have + // changed by the time it is checked) + QEventLoop loop; + QTimer timer; + //simulated CI tests will quickly return -> real GPS tests take 2 minutes for satellite systems + //use a 5 min timeout + timer.setInterval(300000); + connect(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)), + &loop, SLOT(quit())); + connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + timer.start(); + loop.exec(); + + QVERIFY((spy.count() > 0) && (timeout.count() == 0)); + + QList list = spy.takeFirst(); + QGeoPositionInfo info = list.at(0).value(); + QGeoPositionInfo lastPositioninfo = m_source->lastKnownPosition(lastKnownPositionArgument); + + // lastPositioninfo is only gauranteed to be valid in all cases when only using satelite + // positioning methods or when lastKnownPositionArgument is false + if (!lastKnownPositionArgument || + positioningMethod == QGeoPositionInfoSource::SatellitePositioningMethods) { + QVERIFY(lastPositioninfo.isValid()); + } + + if (lastPositioninfo.isValid()) { + QCOMPARE(info.coordinate(), lastPositioninfo.coordinate()); + // On some CI machines the above evenloop code is not sufficient as positionUpdated + // still fires causing last know position and last update to be out of sync. + // To accommodate we check that the time stamps are no more than 1s apart + // ideally they should be the same + // doesn't work: QCOMPARE(info.timestamp(), lastPositioninfo.timestamp()); + const qint64 diff = qAbs(info.timestamp().msecsTo(lastPositioninfo.timestamp())); + QCOMPARE(diff < 1000, true); + + QCOMPARE(info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy), + lastPositioninfo.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)); + + if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) { + bool isNaN1 = qIsNaN(info.attribute(QGeoPositionInfo::HorizontalAccuracy)); + bool isNaN2 = qIsNaN(lastPositioninfo.attribute(QGeoPositionInfo::HorizontalAccuracy)); + QCOMPARE(isNaN1, isNaN2); + if (!isNaN1) { + QCOMPARE(qFuzzyCompare(info.attribute(QGeoPositionInfo::HorizontalAccuracy), + lastPositioninfo.attribute(QGeoPositionInfo::HorizontalAccuracy)), true); + } + } + + QCOMPARE(info.hasAttribute(QGeoPositionInfo::VerticalAccuracy), + lastPositioninfo.hasAttribute(QGeoPositionInfo::VerticalAccuracy)); + + if (info.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) { + bool isNaN1 = qIsNaN(info.attribute(QGeoPositionInfo::VerticalAccuracy)); + bool isNaN2 = qIsNaN(lastPositioninfo.attribute(QGeoPositionInfo::VerticalAccuracy)); + QCOMPARE(isNaN1, isNaN2); + if (!isNaN1) { + QCOMPARE(qFuzzyCompare(info.attribute(QGeoPositionInfo::VerticalAccuracy), + lastPositioninfo.attribute(QGeoPositionInfo::VerticalAccuracy)), true); + } + } + } + + m_source->stopUpdates(); +} + +void TestQGeoPositionInfoSource::lastKnownPosition_data() +{ + QTest::addColumn("positioningMethod"); + QTest::addColumn("lastKnownPositionArgument"); + + // no good way to determine on MeeGo what are supported. If we ask for all or non-satellites, we + // typically get geoclue-example provider, which is not suitable for this test. + QTest::newRow("all - false") << QGeoPositionInfoSource::AllPositioningMethods << false; + QTest::newRow("all - true") << QGeoPositionInfoSource::AllPositioningMethods << true; + QTest::newRow("satellite - false") << QGeoPositionInfoSource::SatellitePositioningMethods << false; + QTest::newRow("satellite - true") << QGeoPositionInfoSource::SatellitePositioningMethods << true; +} + +void TestQGeoPositionInfoSource::minimumUpdateInterval() +{ + CHECK_SOURCE_VALID; + + QVERIFY(m_source->minimumUpdateInterval() > 0); +} + +//TC_ID_3_x_1 +void TestQGeoPositionInfoSource::startUpdates_testIntervals() +{ + CHECK_SOURCE_VALID; + QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy timeout(m_source, SIGNAL(updateTimeout())); + m_source->setUpdateInterval(7000); + int interval = m_source->updateInterval(); + + m_source->startUpdates(); + + QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 9500); + for (int i = 0; i < 6; i++) { + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 1) && (timeout.count() == 0), (interval*2)); + spy.clear(); + } + + m_source->stopUpdates(); +} + + +void TestQGeoPositionInfoSource::startUpdates_testIntervalChangesWhileRunning() +{ + // There are two ways of dealing with an interval change, and we have left it system dependent. + // The interval can be changed will running or after the next update. + // WinCE uses the first method, S60 uses the second method. + + // The minimum interval on the symbian emulator is 5000 msecs, which is why the times in + // this test are as high as they are. + + CHECK_SOURCE_VALID; + + QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy timeout(m_source, SIGNAL(updateTimeout())); + m_source->setUpdateInterval(0); + m_source->startUpdates(); + m_source->setUpdateInterval(0); + + QTRY_VERIFY_WITH_TIMEOUT(spy.count() > 0, 7000); + QCOMPARE(timeout.count(), 0); + spy.clear(); + + m_source->setUpdateInterval(5000); + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 2) && (timeout.count() == 0), 15000); + spy.clear(); + + m_source->setUpdateInterval(10000); + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 2) && (timeout.count() == 0), 30000); + spy.clear(); + + m_source->setUpdateInterval(5000); + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 2) && (timeout.count() == 0), 15000); + spy.clear(); + + m_source->setUpdateInterval(5000); + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 2) && (timeout.count() == 0), 15000); + spy.clear(); + + m_source->setUpdateInterval(0); + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 1) && (timeout.count() == 0), 7000); + spy.clear(); + + m_source->setUpdateInterval(0); + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 1) && (timeout.count() == 0), 7000); + spy.clear(); + + m_source->stopUpdates(); +} + +//TC_ID_3_x_2 +void TestQGeoPositionInfoSource::startUpdates_testDefaultInterval() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy timeout(m_source, SIGNAL(updateTimeout())); + m_source->startUpdates(); + for (int i = 0; i < 3; i++) { + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() > 0) && (timeout.count() == 0), 7000); + spy.clear(); + } + m_source->stopUpdates(); +} + +//TC_ID_3_x_3 +void TestQGeoPositionInfoSource::startUpdates_testZeroInterval() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy timeout(m_source, SIGNAL(updateTimeout())); + m_source->setUpdateInterval(0); + m_source->startUpdates(); + for (int i = 0; i < 3; i++) { + QTRY_VERIFY_WITH_TIMEOUT((spy.count() > 0) && (timeout.count() == 0), 7000); + spy.clear(); + } + m_source->stopUpdates(); +} + +void TestQGeoPositionInfoSource::startUpdates_moreThanOnce() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy timeout(m_source, SIGNAL(updateTimeout())); + m_source->setUpdateInterval(0); + m_source->startUpdates(); + + m_source->startUpdates(); // check there is no crash + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() > 0) && (timeout.count() == 0), 7000); + + m_source->startUpdates(); // check there is no crash + + m_source->stopUpdates(); +} + +//TC_ID_3_x_1 +void TestQGeoPositionInfoSource::stopUpdates() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy timeout(m_source, SIGNAL(updateTimeout())); + m_source->setUpdateInterval(7000); + m_source->startUpdates(); + for (int i = 0; i < 2; i++) { + QTRY_VERIFY_WITH_TIMEOUT((spy.count() > 0) && (timeout.count() == 0), 9500); + spy.clear(); + } + m_source->stopUpdates(); + QTest::qWait(9500); + QCOMPARE(spy.count(), 0); + spy.clear(); + + m_source->setUpdateInterval(0); + m_source->startUpdates(); + m_source->stopUpdates(); + QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 0, 9500); +} + +//TC_ID_3_x_2 +void TestQGeoPositionInfoSource::stopUpdates_withoutStart() +{ + CHECK_SOURCE_VALID; + m_source->stopUpdates(); // check there is no crash +} + +void TestQGeoPositionInfoSource::requestUpdate() +{ + CHECK_SOURCE_VALID; + QFETCH(int, timeout); + QSignalSpy spy(m_source, SIGNAL(updateTimeout())); + m_source->requestUpdate(timeout); + QTRY_COMPARE(spy.count(), 1); +} + +void TestQGeoPositionInfoSource::requestUpdate_data() +{ + QTest::addColumn("timeout"); + QTest::newRow("less than zero") << -1; //TC_ID_3_x_7 +} + +// TC_ID_3_x_1 : Create position source and call requestUpdate with valid timeout value +void TestQGeoPositionInfoSource::requestUpdate_validTimeout() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(m_source, SIGNAL(updateTimeout())); + + m_source->requestUpdate(7000); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() > 0) && (spyTimeout.count() == 0), 7000); +} + +void TestQGeoPositionInfoSource::requestUpdate_defaultTimeout() +{ + CHECK_SOURCE_VALID; + QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(m_source, SIGNAL(updateTimeout())); + + m_source->requestUpdate(0); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() > 0) && (spyTimeout.count() == 0), 7000); +} + +// TC_ID_3_x_2 : Create position source and call requestUpdate with a timeout less than +// minimumupdateInterval +void TestQGeoPositionInfoSource::requestUpdate_timeoutLessThanMinimumInterval() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyTimeout(m_source, SIGNAL(updateTimeout())); + m_source->requestUpdate(1); + + QTRY_COMPARE_WITH_TIMEOUT(spyTimeout.count(), 1, 1000); +} + +// TC_ID_3_x_3 : Call requestUpdate() with same value repeatedly +void TestQGeoPositionInfoSource::requestUpdate_repeatedCalls() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(m_source, SIGNAL(updateTimeout())); + + m_source->requestUpdate(7000); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() > 0) && (spyTimeout.count() == 0), 7000); + spyUpdate.clear(); + m_source->requestUpdate(7000); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() > 0) && (spyTimeout.count() == 0), 7000); +} + +void TestQGeoPositionInfoSource::requestUpdate_overlappingCalls() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(m_source, SIGNAL(updateTimeout())); + + m_source->requestUpdate(7000); + m_source->requestUpdate(7000); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() > 0) && (spyTimeout.count() == 0), 7000); +} + +//TC_ID_3_x_4 +void TestQGeoPositionInfoSource::requestUpdateAfterStartUpdates_ZeroInterval() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(m_source, SIGNAL(updateTimeout())); + + m_source->setUpdateInterval(0); + m_source->startUpdates(); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() > 0) && (spyTimeout.count() == 0), 7000); + spyUpdate.clear(); + + m_source->requestUpdate(7000); + QTest::qWait(7000); + + QVERIFY((spyUpdate.count() > 0) && (spyTimeout.count() == 0)); + spyUpdate.clear(); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() > 0) && (spyTimeout.count() == 0), MAX_WAITING_TIME); + + m_source->stopUpdates(); +} + +void TestQGeoPositionInfoSource::requestUpdateAfterStartUpdates_SmallInterval() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(m_source, SIGNAL(updateTimeout())); + + m_source->setUpdateInterval(10000); + m_source->startUpdates(); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() == 1) && (spyTimeout.count() == 0), 20000); + spyUpdate.clear(); + + m_source->requestUpdate(7000); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() == 1) && (spyTimeout.count() == 0), 7000); + spyUpdate.clear(); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() == 1) && (spyTimeout.count() == 0), 20000); + + m_source->stopUpdates(); +} + +void TestQGeoPositionInfoSource::requestUpdateBeforeStartUpdates_ZeroInterval() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(m_source, SIGNAL(updateTimeout())); + + m_source->requestUpdate(7000); + + m_source->setUpdateInterval(0); + m_source->startUpdates(); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() >= 2) && (spyTimeout.count() == 0), 14000); + spyUpdate.clear(); + + QTest::qWait(7000); + + QCOMPARE(spyTimeout.count(), 0); + + m_source->stopUpdates(); +} + +void TestQGeoPositionInfoSource::requestUpdateBeforeStartUpdates_SmallInterval() +{ + CHECK_SOURCE_VALID; + QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(m_source, SIGNAL(updateTimeout())); + + m_source->requestUpdate(7000); + + m_source->setUpdateInterval(10000); + m_source->startUpdates(); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() > 0) && (spyTimeout.count() == 0), 7000); + spyUpdate.clear(); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() > 0) && (spyTimeout.count() == 0), 20000); + + m_source->stopUpdates(); +} + +void TestQGeoPositionInfoSource::removeSlotForRequestTimeout() +{ + CHECK_SOURCE_VALID; + + bool i = connect(m_source, SIGNAL(updateTimeout()), this, SLOT(test_slot1())); + QVERIFY(i == true); + i = connect(m_source, SIGNAL(updateTimeout()), this, SLOT(test_slot2())); + QVERIFY(i == true); + i = disconnect(m_source, SIGNAL(updateTimeout()), this, SLOT(test_slot1())); + QVERIFY(i == true); + + m_source->requestUpdate(-1); + QTRY_VERIFY_WITH_TIMEOUT((m_testSlot2Called == true), 1000); +} + +void TestQGeoPositionInfoSource::removeSlotForPositionUpdated() +{ + CHECK_SOURCE_VALID; + + bool i = connect(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(test_slot1())); + QVERIFY(i == true); + i = connect(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(test_slot2())); + QVERIFY(i == true); + i = disconnect(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(test_slot1())); + QVERIFY(i == true); + + m_source->requestUpdate(7000); + + QTRY_VERIFY_WITH_TIMEOUT((m_testSlot2Called == true), 7000); +} + +#include "testqgeopositioninfosource.moc" diff --git a/tests/auto/qgeopositioninfosource/testqgeopositioninfosource_p.h b/tests/auto/qgeopositioninfosource/testqgeopositioninfosource_p.h new file mode 100644 index 0000000..7ee23f8 --- /dev/null +++ b/tests/auto/qgeopositioninfosource/testqgeopositioninfosource_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTQGEOPOSITIONINFOSOURCE_P_H +#define TESTQGEOPOSITIONINFOSOURCE_P_H + +#include + +#ifdef TST_GEOCLUEMOCK_ENABLED +#include "geocluemock.h" +#include +#endif + +#include +#include + +QT_BEGIN_NAMESPACE +class QGeoPositionInfoSource; +QT_END_NAMESPACE + +class TestQGeoPositionInfoSource : public QObject +{ + Q_OBJECT + +public: + TestQGeoPositionInfoSource(QObject *parent = 0); + + static TestQGeoPositionInfoSource *createDefaultSourceTest(); + +public slots: + void test_slot1(); + void test_slot2(); + +protected: + virtual QGeoPositionInfoSource *createTestSource() = 0; + + // MUST be called by subclasses if they override respective test slots + void base_initTestCase(); + void base_init(); + void base_cleanup(); + void base_cleanupTestCase(); + +private slots: + void initTestCase(); + void init(); + void cleanup(); + void cleanupTestCase(); + + void constructor_withParent(); + + void constructor_noParent(); + + void updateInterval(); + + void setPreferredPositioningMethods(); + void setPreferredPositioningMethods_data(); + + void preferredPositioningMethods(); + + void createDefaultSource(); + + void setUpdateInterval(); + void setUpdateInterval_data(); + + void lastKnownPosition(); + void lastKnownPosition_data(); + + void minimumUpdateInterval(); + + void startUpdates_testIntervals(); + void startUpdates_testIntervalChangesWhileRunning(); + void startUpdates_testDefaultInterval(); + void startUpdates_testZeroInterval(); + void startUpdates_moreThanOnce(); + + void stopUpdates(); + void stopUpdates_withoutStart(); + + void requestUpdate(); + void requestUpdate_data(); + + void requestUpdate_validTimeout(); + void requestUpdate_defaultTimeout(); + void requestUpdate_timeoutLessThanMinimumInterval(); + void requestUpdate_repeatedCalls(); + void requestUpdate_overlappingCalls(); + + void requestUpdateAfterStartUpdates_ZeroInterval(); + void requestUpdateAfterStartUpdates_SmallInterval(); + void requestUpdateBeforeStartUpdates_ZeroInterval(); + void requestUpdateBeforeStartUpdates_SmallInterval(); + + void removeSlotForRequestTimeout(); + void removeSlotForPositionUpdated(); + +private: + QGeoPositionInfoSource *m_source; + bool m_testingDefaultSource; + bool m_testSlot2Called; +}; + +#endif diff --git a/tests/auto/qgeopositioninfosource/tst_qgeopositioninfosource.cpp b/tests/auto/qgeopositioninfosource/tst_qgeopositioninfosource.cpp new file mode 100644 index 0000000..105778e --- /dev/null +++ b/tests/auto/qgeopositioninfosource/tst_qgeopositioninfosource.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testqgeopositioninfosource_p.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + TestQGeoPositionInfoSource *test = TestQGeoPositionInfoSource::createDefaultSourceTest(); + int ret = QTest::qExec(test, argc, argv); + delete test; // keep valgrind happy + return ret; +} diff --git a/tests/auto/qgeorectangle/qgeorectangle.pro b/tests/auto/qgeorectangle/qgeorectangle.pro new file mode 100644 index 0000000..9cb635e --- /dev/null +++ b/tests/auto/qgeorectangle/qgeorectangle.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeorectangle + +SOURCES += \ + tst_qgeorectangle.cpp + +QT += positioning testlib diff --git a/tests/auto/qgeorectangle/tst_qgeorectangle.cpp b/tests/auto/qgeorectangle/tst_qgeorectangle.cpp new file mode 100644 index 0000000..71a3765 --- /dev/null +++ b/tests/auto/qgeorectangle/tst_qgeorectangle.cpp @@ -0,0 +1,2351 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QGeoRectangle : public QObject +{ + Q_OBJECT + +private slots: + void default_constructor(); + void center_constructor(); + void corner_constructor(); + void list_constructor(); + void copy_constructor(); + void assignment(); + void destructor(); + + void equality(); + void equality_data(); + + void isValid(); + void isValid_data(); + + void isEmpty(); + void isEmpty_data(); + + void corners(); + void corners_data(); + + void setCorners(); + + void width(); + void width_data(); + + void height(); + void height_data(); + + void center(); + void center_data(); + + void containsCoord(); + void containsCoord_data(); + + void containsBoxAndIntersects(); + void containsBoxAndIntersects_data(); + + void translate(); + void translate_data(); + + void unite(); + void unite_data(); + + void extendShape(); + void extendShape_data(); + + void areaComparison(); + void areaComparison_data(); + + void circleComparison(); + void circleComparison_data(); +}; + +void tst_QGeoRectangle::default_constructor() +{ + QGeoRectangle box; + QCOMPARE(box.topLeft().isValid(), false); + QCOMPARE(box.bottomRight().isValid(), false); +} + +void tst_QGeoRectangle::center_constructor() +{ + QGeoRectangle b1 = QGeoRectangle(QGeoCoordinate(5.0, 5.0), 10.0, 10.0); + + QCOMPARE(b1.topLeft(), QGeoCoordinate(10.0, 0.0)); + QCOMPARE(b1.bottomRight(), QGeoCoordinate(0.0, 10.0)); +} + +void tst_QGeoRectangle::corner_constructor() +{ + QGeoRectangle b1 = QGeoRectangle(QGeoCoordinate(10.0, 0.0), + QGeoCoordinate(0.0, 10.0)); + + QCOMPARE(b1.topLeft(), QGeoCoordinate(10.0, 0.0)); + QCOMPARE(b1.bottomRight(), QGeoCoordinate(0.0, 10.0)); +} + +void tst_QGeoRectangle::list_constructor() +{ + QList coordinates; + QGeoRectangle b1 = QGeoRectangle(coordinates); + QCOMPARE(b1.isValid(), false); + + coordinates << QGeoCoordinate(10.0, 0.0); + b1 = QGeoRectangle(coordinates); + QCOMPARE(b1.isValid(), true); + QCOMPARE(b1.isEmpty(), true); + + coordinates << QGeoCoordinate(0.0, 10.0) << QGeoCoordinate(0.0, 5.0); + b1 = QGeoRectangle(coordinates); + QCOMPARE(b1.topLeft(), QGeoCoordinate(10.0,0.0)); + QCOMPARE(b1.bottomRight(), QGeoCoordinate(0.0, 10.0)); +} + +void tst_QGeoRectangle::copy_constructor() +{ + QGeoRectangle b1 = QGeoRectangle(QGeoCoordinate(10.0, 0.0), + QGeoCoordinate(0.0, 10.0)); + QGeoRectangle b2 = QGeoRectangle(b1); + + QCOMPARE(b2.topLeft(), QGeoCoordinate(10.0, 0.0)); + QCOMPARE(b2.bottomRight(), QGeoCoordinate(0.0, 10.0)); + + b2.setTopLeft(QGeoCoordinate(30.0, 0.0)); + b2.setBottomRight(QGeoCoordinate(0.0, 30.0)); + QCOMPARE(b1.topLeft(), QGeoCoordinate(10.0, 0.0)); + QCOMPARE(b1.bottomRight(), QGeoCoordinate(0.0, 10.0)); + + QGeoShape area; + QGeoRectangle areaBox(area); + QVERIFY(!areaBox.isValid()); + QVERIFY(areaBox.isEmpty()); + + QGeoCircle circle; + QGeoRectangle circleBox(circle); + QVERIFY(!circleBox.isValid()); + QVERIFY(circleBox.isEmpty()); +} + +void tst_QGeoRectangle::destructor() +{ + QGeoRectangle *box = new QGeoRectangle(); + delete box; + // checking for a crash +} + +void tst_QGeoRectangle::assignment() +{ + QGeoRectangle b1 = QGeoRectangle(QGeoCoordinate(10.0, 0.0), + QGeoCoordinate(0.0, 10.0)); + QGeoRectangle b2 = QGeoRectangle(QGeoCoordinate(20.0, 0.0), + QGeoCoordinate(0.0, 20.0)); + + QVERIFY(b1 != b2); + + b2 = b1; + QCOMPARE(b2.topLeft(), QGeoCoordinate(10.0, 0.0)); + QCOMPARE(b2.bottomRight(), QGeoCoordinate(0.0, 10.0)); + QCOMPARE(b1, b2); + + b2.setTopLeft(QGeoCoordinate(30.0, 0.0)); + b2.setBottomRight(QGeoCoordinate(0.0, 30.0)); + QCOMPARE(b1.topLeft(), QGeoCoordinate(10.0, 0.0)); + QCOMPARE(b1.bottomRight(), QGeoCoordinate(0.0, 10.0)); + + // Assign b1 to an area + QGeoShape area = b1; + QCOMPARE(area.type(), b1.type()); + QVERIFY(area == b1); + + // Assign the area back to a bounding box + QGeoRectangle ba = area; + QCOMPARE(ba.topLeft(), b1.topLeft()); + QCOMPARE(ba.bottomRight(), b1.bottomRight()); + + // Check that the copy is not modified when modifying the original. + b1.setTopLeft(QGeoCoordinate(80, 30)); + QVERIFY(ba.topLeft() != b1.topLeft()); + QVERIFY(ba != b1); +} + +void tst_QGeoRectangle::equality() +{ + QFETCH(QGeoRectangle, box1); + QFETCH(QGeoRectangle, box2); + QFETCH(QGeoShape, area1); + QFETCH(QGeoShape, area2); + QFETCH(bool, equal); + + // compare boxes + QCOMPARE((box1 == box2), equal); + QCOMPARE((box1 != box2), !equal); + + // compare areas + QCOMPARE((area1 == area2), equal); + QCOMPARE((area1 != area2), !equal); + + // compare area to box + QCOMPARE((area1 == box2), equal); + QCOMPARE((area1 != box2), !equal); + + // compare box to area + QCOMPARE((box1 == area2), equal); + QCOMPARE((box1 != area2), !equal); +} + +void tst_QGeoRectangle::equality_data() +{ + QTest::addColumn("box1"); + QTest::addColumn("box2"); + QTest::addColumn("area1"); + QTest::addColumn("area2"); + QTest::addColumn("equal"); + + QGeoCoordinate c1(10, 5); + QGeoCoordinate c2(5, 10); + QGeoCoordinate c3(20, 15); + QGeoCoordinate c4(15, 20); + + QGeoRectangle b1(c1, c2); + QGeoRectangle b2(c3, c4); + QGeoRectangle b3(c3, c2); + QGeoRectangle b4(c1, c3); + QGeoRectangle b5(c1, c2); + + QGeoShape a1(b1); + QGeoShape a2(b2); + QGeoShape a3(b3); + QGeoShape a4(b4); + QGeoShape a5(b5); + + QTest::newRow("all unequal") + << b1 << b2 << a1 << a2 << false; + QTest::newRow("top left unequal") + << b1 << b3 << a1 << a3 << false; + QTest::newRow("bottom right unequal") + << b1 << b4 << a1 << a4 << false; + QTest::newRow("equal") + << b1 << b5 << a1 << a5 << true; +} + +void tst_QGeoRectangle::isValid() +{ + QFETCH(QGeoRectangle, input); + QFETCH(bool, valid); + + QCOMPARE(input.isValid(), valid); + + QGeoShape area = input; + QCOMPARE(area.isValid(), valid); +} + +void tst_QGeoRectangle::isValid_data() +{ + QTest::addColumn("input"); + QTest::addColumn("valid"); + + QGeoCoordinate c0; + QGeoCoordinate c1(10, 5); + QGeoCoordinate c2(5, 10); + + QTest::newRow("both corners invalid") + << QGeoRectangle(c0, c0) << false; + QTest::newRow("top left corner invalid") + << QGeoRectangle(c0, c2) << false; + QTest::newRow("bottom right corner invalid") + << QGeoRectangle(c1, c0) << false; + QTest::newRow("height in wrong order") + << QGeoRectangle(c2, c1) << false; + QTest::newRow("both corners valid") + << QGeoRectangle(c1, c2) << true; +} + +void tst_QGeoRectangle::isEmpty() +{ + QFETCH(QGeoRectangle, input); + QFETCH(bool, empty); + + QCOMPARE(input.isEmpty(), empty); + + QGeoShape area = input; + QCOMPARE(area.isEmpty(), empty); +} + +void tst_QGeoRectangle::isEmpty_data() +{ + QTest::addColumn("input"); + QTest::addColumn("empty"); + + QGeoCoordinate c0; + QGeoCoordinate c1(10, 5); + QGeoCoordinate c2(5, 10); + QGeoCoordinate c3(10, 10); + + QTest::newRow("both corners invalid") + << QGeoRectangle(c0, c0) << true; + QTest::newRow("top left corner invalid") + << QGeoRectangle(c0, c2) << true; + QTest::newRow("bottom right corner invalid") + << QGeoRectangle(c1, c0) << true; + QTest::newRow("zero width") + << QGeoRectangle(c1, c3) << true; + QTest::newRow("zero height") + << QGeoRectangle(c3, c2) << true; + QTest::newRow("zero width and height") + << QGeoRectangle(c1, c1) << true; + QTest::newRow("non-zero width and height") + << QGeoRectangle(c1, c2) << false; +} + +void tst_QGeoRectangle::corners() +{ + QFETCH(QGeoRectangle, box); + QFETCH(QGeoCoordinate, topLeft); + QFETCH(QGeoCoordinate, topRight); + QFETCH(QGeoCoordinate, bottomLeft); + QFETCH(QGeoCoordinate, bottomRight); + + QCOMPARE(box.topLeft(), topLeft); + QCOMPARE(box.topRight(), topRight); + QCOMPARE(box.bottomLeft(), bottomLeft); + QCOMPARE(box.bottomRight(), bottomRight); +} + +void tst_QGeoRectangle::corners_data() +{ + QTest::addColumn("box"); + QTest::addColumn("topLeft"); + QTest::addColumn("topRight"); + QTest::addColumn("bottomLeft"); + QTest::addColumn("bottomRight"); + + QGeoCoordinate c0; + QGeoCoordinate tl(10, 5); + QGeoCoordinate br(5, 10); + QGeoCoordinate tr(10, 10); + QGeoCoordinate bl(5, 5); + + QTest::newRow("both invalid") + << QGeoRectangle(c0, c0) + << c0 + << c0 + << c0 + << c0; + QTest::newRow("top left invalid") + << QGeoRectangle(c0, br) + << c0 + << c0 + << c0 + << br; + QTest::newRow("bottom right invalid") + << QGeoRectangle(tl, c0) + << tl + << c0 + << c0 + << c0; + QTest::newRow("both valid") + << QGeoRectangle(tl, br) + << tl + << tr + << bl + << br; +} + +void tst_QGeoRectangle::setCorners() +{ + QGeoRectangle box(QGeoCoordinate(10.0, 0.0), + QGeoCoordinate(0.0, 10.0)); + + box.setTopLeft(QGeoCoordinate(20.0, -10.0)); + + QCOMPARE(box.topLeft(), QGeoCoordinate(20.0, -10.0)); + QCOMPARE(box.topRight(), QGeoCoordinate(20.0, 10.0)); + QCOMPARE(box.bottomLeft(), QGeoCoordinate(0.0, -10.0)); + QCOMPARE(box.bottomRight(), QGeoCoordinate(0.0, 10.0)); + + box.setTopRight(QGeoCoordinate(30.0, 20.0)); + + QCOMPARE(box.topLeft(), QGeoCoordinate(30.0, -10.0)); + QCOMPARE(box.topRight(), QGeoCoordinate(30.0, 20.0)); + QCOMPARE(box.bottomLeft(), QGeoCoordinate(0.0, -10.0)); + QCOMPARE(box.bottomRight(), QGeoCoordinate(0.0, 20.0)); + + box.setBottomRight(QGeoCoordinate(-10.0, 30.0)); + + QCOMPARE(box.topLeft(), QGeoCoordinate(30.0, -10.0)); + QCOMPARE(box.topRight(), QGeoCoordinate(30.0, 30.0)); + QCOMPARE(box.bottomLeft(), QGeoCoordinate(-10.0, -10.0)); + QCOMPARE(box.bottomRight(), QGeoCoordinate(-10.0, 30.0)); + + box.setBottomLeft(QGeoCoordinate(-20.0, -20.0)); + + QCOMPARE(box.topLeft(), QGeoCoordinate(30.0, -20.0)); + QCOMPARE(box.topRight(), QGeoCoordinate(30.0, 30.0)); + QCOMPARE(box.bottomLeft(), QGeoCoordinate(-20.0, -20.0)); + QCOMPARE(box.bottomRight(), QGeoCoordinate(-20.0, 30.0)); + + +} + +void tst_QGeoRectangle::width() +{ + QFETCH(QGeoRectangle, box); + QFETCH(double, oldWidth); + QFETCH(double, newWidth); + QFETCH(QGeoRectangle, newBox); + + if (qIsNaN(oldWidth)) + QVERIFY(qIsNaN(box.width())); + else + QCOMPARE(box.width(), oldWidth); + + box.setWidth(newWidth); + + QCOMPARE(box, newBox); +} + +void tst_QGeoRectangle::width_data() +{ + QTest::addColumn("box"); + QTest::addColumn("oldWidth"); + QTest::addColumn("newWidth"); + QTest::addColumn("newBox"); + + QTest::newRow("invalid box") + << QGeoRectangle() + << qQNaN() + << 100.0 + << QGeoRectangle(); + + QTest::newRow("0 width -> negative width") + << QGeoRectangle(QGeoCoordinate(10.0, 90.0), + QGeoCoordinate(5.0, 90.0)) + << 0.0 + << -1.0 + << QGeoRectangle(QGeoCoordinate(10.0, 90.0), + QGeoCoordinate(5.0, 90.0)); + + QTest::newRow("0 width -> 0 width") + << QGeoRectangle(QGeoCoordinate(10.0, 90.0), + QGeoCoordinate(5.0, 90.0)) + << 0.0 + << 0.0 + << QGeoRectangle(QGeoCoordinate(10.0, 90.0), + QGeoCoordinate(5.0, 90.0)); + + QTest::newRow("0 width -> non wrapping width") + << QGeoRectangle(QGeoCoordinate(10.0, 90.0), + QGeoCoordinate(5.0, 90.0)) + << 0.0 + << 10.0 + << QGeoRectangle(QGeoCoordinate(10.0, 85.0), + QGeoCoordinate(5.0, 95.0)); + + QTest::newRow("0 width -> wrapping width positive") + << QGeoRectangle(QGeoCoordinate(10.0, 90.0), + QGeoCoordinate(5.0, 90.0)) + << 0.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(10.0, -5.0), + QGeoCoordinate(5.0, -175.0)); + + QTest::newRow("0 width -> wrapping width negative") + << QGeoRectangle(QGeoCoordinate(10.0, -90.0), + QGeoCoordinate(5.0, -90.0)) + << 0.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(10.0, 175.0), + QGeoCoordinate(5.0, 5.0)); + + QTest::newRow("0 width -> 360 width") + << QGeoRectangle(QGeoCoordinate(10.0, 90.0), + QGeoCoordinate(5.0, 90.0)) + << 0.0 + << 360.0 + << QGeoRectangle(QGeoCoordinate(10.0, -180.0), + QGeoCoordinate(5.0, 180.0)); + + QTest::newRow("0 width -> 360+ width") + << QGeoRectangle(QGeoCoordinate(10.0, 90.0), + QGeoCoordinate(5.0, 90.0)) + << 0.0 + << 370.0 + << QGeoRectangle(QGeoCoordinate(10.0, -180.0), + QGeoCoordinate(5.0, 180.0)); + + QTest::newRow("non wrapping width -> negative width") + << QGeoRectangle(QGeoCoordinate(10.0, 85.0), + QGeoCoordinate(5.0, 95.0)) + << 10.0 + << -1.0 + << QGeoRectangle(QGeoCoordinate(10.0, 85.0), + QGeoCoordinate(5.0, 95.0)); + + QTest::newRow("non wrapping width -> 0 width") + << QGeoRectangle(QGeoCoordinate(10.0, 85.0), + QGeoCoordinate(5.0, 95.0)) + << 10.0 + << 0.0 + << QGeoRectangle(QGeoCoordinate(10.0, 90.0), + QGeoCoordinate(5.0, 90.0)); + + QTest::newRow("non wrapping width -> non wrapping width") + << QGeoRectangle(QGeoCoordinate(10.0, 85.0), + QGeoCoordinate(5.0, 95.0)) + << 10.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(10.0, 80.0), + QGeoCoordinate(5.0, 100.0)); + + QTest::newRow("non wrapping width -> wrapping width positive") + << QGeoRectangle(QGeoCoordinate(10.0, 85.0), + QGeoCoordinate(5.0, 95.0)) + << 10.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(10.0, -5.0), + QGeoCoordinate(5.0, -175.0)); + + QTest::newRow("non wrapping width -> wrapping width negative") + << QGeoRectangle(QGeoCoordinate(10.0, -95.0), + QGeoCoordinate(5.0, -85.0)) + << 10.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(10.0, 175.0), + QGeoCoordinate(5.0, 5.0)); + + QTest::newRow("non wrapping width -> 360 width") + << QGeoRectangle(QGeoCoordinate(10.0, 85.0), + QGeoCoordinate(5.0, 95.0)) + << 10.0 + << 360.0 + << QGeoRectangle(QGeoCoordinate(10.0, -180.0), + QGeoCoordinate(5.0, 180.0)); + + QTest::newRow("non wrapping width width -> 360+ width") + << QGeoRectangle(QGeoCoordinate(10.0, 85.0), + QGeoCoordinate(5.0, 95.0)) + << 10.0 + << 370.0 + << QGeoRectangle(QGeoCoordinate(10.0, -180.0), + QGeoCoordinate(5.0, 180.0)); + + QTest::newRow("wrapping width -> negative width") + << QGeoRectangle(QGeoCoordinate(10.0, 175.0), + QGeoCoordinate(5.0, -85.0)) + << 100.0 + << -1.0 + << QGeoRectangle(QGeoCoordinate(10.0, 175.0), + QGeoCoordinate(5.0, -85.0)); + + QTest::newRow("wrapping width -> 0 width") + << QGeoRectangle(QGeoCoordinate(10.0, 175.0), + QGeoCoordinate(5.0, -85.0)) + << 100.0 + << 0.0 + << QGeoRectangle(QGeoCoordinate(10.0, -135.0), + QGeoCoordinate(5.0, -135.0)); + + QTest::newRow("wrapping width -> non wrapping width") + << QGeoRectangle(QGeoCoordinate(10.0, 175.0), + QGeoCoordinate(5.0, -85.0)) + << 100.0 + << 80.0 + << QGeoRectangle(QGeoCoordinate(10.0, -175.0), + QGeoCoordinate(5.0, -95.0)); + + QTest::newRow("wrapping width -> wrapping width") + << QGeoRectangle(QGeoCoordinate(10.0, 175.0), + QGeoCoordinate(5.0, -85.0)) + << 100.0 + << 120.0 + << QGeoRectangle(QGeoCoordinate(10.0, 165.0), + QGeoCoordinate(5.0, -75.0)); + + QTest::newRow("wrapping width -> 360 width") + << QGeoRectangle(QGeoCoordinate(10.0, 175.0), + QGeoCoordinate(5.0, -85.0)) + << 100.0 + << 360.0 + << QGeoRectangle(QGeoCoordinate(10.0, -180.0), + QGeoCoordinate(5.0, 180.0)); + + QTest::newRow("wrapping width width -> 360+ width") + << QGeoRectangle(QGeoCoordinate(10.0, 175.0), + QGeoCoordinate(5.0, -85.0)) + << 100.0 + << 370.0 + << QGeoRectangle(QGeoCoordinate(10.0, -180.0), + QGeoCoordinate(5.0, 180.0)); +} + +void tst_QGeoRectangle::height() +{ + QFETCH(QGeoRectangle, box); + QFETCH(double, oldHeight); + QFETCH(double, newHeight); + QFETCH(QGeoRectangle, newBox); + + if (qIsNaN(oldHeight)) + QVERIFY(qIsNaN(box.height())); + else + QCOMPARE(box.height(), oldHeight); + + box.setHeight(newHeight); + QCOMPARE(box, newBox); +} + +void tst_QGeoRectangle::height_data() +{ + QTest::addColumn("box"); + QTest::addColumn("oldHeight"); + QTest::addColumn("newHeight"); + QTest::addColumn("newBox"); + + QTest::newRow("invalid box") + << QGeoRectangle() + << qQNaN() + << 100.0 + << QGeoRectangle(); + + QTest::newRow("0 height -> negative height") + << QGeoRectangle(QGeoCoordinate(10.0, 5.0), + QGeoCoordinate(10.0, 10.0)) + << 0.0 + << -1.0 + << QGeoRectangle(QGeoCoordinate(10.0, 5.0), + QGeoCoordinate(10.0, 10.0)); + + QTest::newRow("0 height -> 0 height") + << QGeoRectangle(QGeoCoordinate(10.0, 5.0), + QGeoCoordinate(10.0, 10.0)) + << 0.0 + << 0.0 + << QGeoRectangle(QGeoCoordinate(10.0, 5.0), + QGeoCoordinate(10.0, 10.0)); + + QTest::newRow("0 height -> non zero height") + << QGeoRectangle(QGeoCoordinate(10.0, 5.0), + QGeoCoordinate(10.0, 10.0)) + << 0.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(20.0, 5.0), + QGeoCoordinate(0.0, 10.0)); + + QTest::newRow("0 height -> squash top") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(70.0, 70.0)) + << 0.0 + << 60.0 + << QGeoRectangle(QGeoCoordinate(90.0, 30.0), + QGeoCoordinate(50.0, 70.0)); + + QTest::newRow("0 height -> squash bottom") + << QGeoRectangle(QGeoCoordinate(-70.0, 30.0), + QGeoCoordinate(-70.0, 70.0)) + << 0.0 + << 60.0 + << QGeoRectangle(QGeoCoordinate(-50.0, 30.0), + QGeoCoordinate(-90.0, 70.0)); + + QTest::newRow("0 height -> 180") + << QGeoRectangle(QGeoCoordinate(0.0, 5.0), + QGeoCoordinate(0.0, 10.0)) + << 0.0 + << 180.0 + << QGeoRectangle(QGeoCoordinate(90.0, 5.0), + QGeoCoordinate(-90.0, 10.0)); + + QTest::newRow("0 height -> 180 squash top") + << QGeoRectangle(QGeoCoordinate(20.0, 5.0), + QGeoCoordinate(20.0, 10.0)) + << 0.0 + << 180.0 + << QGeoRectangle(QGeoCoordinate(90.0, 5.0), + QGeoCoordinate(-50.0, 10.0)); + + QTest::newRow("0 height -> 180 squash bottom") + << QGeoRectangle(QGeoCoordinate(-20.0, 5.0), + QGeoCoordinate(-20.0, 10.0)) + << 0.0 + << 180.0 + << QGeoRectangle(QGeoCoordinate(50.0, 5.0), + QGeoCoordinate(-90.0, 10.0)); + + QTest::newRow("0 height -> 180+") + << QGeoRectangle(QGeoCoordinate(0.0, 5.0), + QGeoCoordinate(0.0, 10.0)) + << 0.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(90.0, 5.0), + QGeoCoordinate(-90.0, 10.0)); + + QTest::newRow("0 height -> 180+ squash top") + << QGeoRectangle(QGeoCoordinate(20.0, 5.0), + QGeoCoordinate(20.0, 10.0)) + << 0.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(90.0, 5.0), + QGeoCoordinate(-50.0, 10.0)); + + QTest::newRow("0 height -> 180+ squash bottom") + << QGeoRectangle(QGeoCoordinate(-20.0, 5.0), + QGeoCoordinate(-20.0, 10.0)) + << 0.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(50.0, 5.0), + QGeoCoordinate(-90.0, 10.0)); + + QTest::newRow("non zero height -> negative height") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << 40.0 + << -1.0 + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)); + + QTest::newRow("non zero height -> 0 height") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << 40.0 + << 0.0 + << QGeoRectangle(QGeoCoordinate(50.0, 30.0), + QGeoCoordinate(50.0, 70.0)); + + QTest::newRow("non zero height -> non zero height") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << 40.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(60.0, 30.0), + QGeoCoordinate(40.0, 70.0)); + + QTest::newRow("non zero height -> squash top") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << 40.0 + << 100.0 + << QGeoRectangle(QGeoCoordinate(90.0, 30.0), + QGeoCoordinate(10.0, 70.0)); + + QTest::newRow("non zero height -> squash bottom") + << QGeoRectangle(QGeoCoordinate(-30.0, 30.0), + QGeoCoordinate(-70.0, 70.0)) + << 40.0 + << 100.0 + << QGeoRectangle(QGeoCoordinate(-10.0, 30.0), + QGeoCoordinate(-90.0, 70.0)); + + QTest::newRow("non zero height -> 180") + << QGeoRectangle(QGeoCoordinate(20.0, 30.0), + QGeoCoordinate(-20.0, 70.0)) + << 40.0 + << 180.0 + << QGeoRectangle(QGeoCoordinate(90.0, 30.0), + QGeoCoordinate(-90.0, 70.0)); + + QTest::newRow("non zero height -> 180 squash top") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << 40.0 + << 180.0 + << QGeoRectangle(QGeoCoordinate(90.0, 30.0), + QGeoCoordinate(10.0, 70.0)); + + QTest::newRow("non zero height -> 180 squash bottom") + << QGeoRectangle(QGeoCoordinate(-30.0, 30.0), + QGeoCoordinate(-70.0, 70.0)) + << 40.0 + << 180.0 + << QGeoRectangle(QGeoCoordinate(-10.0, 30.0), + QGeoCoordinate(-90.0, 70.0)); + + QTest::newRow("non zero height -> 180+") + << QGeoRectangle(QGeoCoordinate(20.0, 30.0), + QGeoCoordinate(-20.0, 70.0)) + << 40.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(90.0, 30.0), + QGeoCoordinate(-90.0, 70.0)); + + QTest::newRow("non zero height -> 180+ squash top") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << 40.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(90.0, 30.0), + QGeoCoordinate(10.0, 70.0)); + + QTest::newRow("non zero height -> 180+ squash bottom") + << QGeoRectangle(QGeoCoordinate(-30.0, 30.0), + QGeoCoordinate(-70.0, 70.0)) + << 40.0 + << 190.0 + << QGeoRectangle(QGeoCoordinate(-10.0, 30.0), + QGeoCoordinate(-90.0, 70.0)); +} + +void tst_QGeoRectangle::center() +{ + QFETCH(QGeoRectangle, box); + QFETCH(QGeoCoordinate, oldCenter); + QFETCH(QGeoCoordinate, newCenter); + QFETCH(QGeoRectangle, newBox); + + QGeoShape shape = box; + QCOMPARE(box.center(), oldCenter); + QCOMPARE(shape.center(), oldCenter); + box.setCenter(newCenter); + QCOMPARE(box, newBox); +} + +void tst_QGeoRectangle::center_data() +{ + QTest::addColumn("box"); + QTest::addColumn("oldCenter"); + QTest::addColumn("newCenter"); + QTest::addColumn("newBox"); + + QTest::newRow("invalid") + << QGeoRectangle() + << QGeoCoordinate() + << QGeoCoordinate(0.0, 0.0) + << QGeoRectangle(QGeoCoordinate(0.0, 0.0), 0.0, 0.0); + + QTest::newRow("zero width") + << QGeoRectangle(QGeoCoordinate(10.0, 5.0), + QGeoCoordinate(5.0, 5.0)) + << QGeoCoordinate(7.5, 5.0) + << QGeoCoordinate(20.0, 20.0) + << QGeoRectangle(QGeoCoordinate(22.5, 20.0), + QGeoCoordinate(17.5, 20.0)); + + QTest::newRow("360 width") + << QGeoRectangle(QGeoCoordinate(10.0, -180.0), + QGeoCoordinate(5.0, 180.0)) + << QGeoCoordinate(7.5, 0.0) + << QGeoCoordinate(20.0, 20.0) + << QGeoRectangle(QGeoCoordinate(22.5, -180.0), + QGeoCoordinate(17.5, 180.0)); + + QTest::newRow("zero height") + << QGeoRectangle(QGeoCoordinate(5.0, 5.0), + QGeoCoordinate(5.0, 10.0)) + << QGeoCoordinate(5.0, 7.5) + << QGeoCoordinate(20.0, 20.0) + << QGeoRectangle(QGeoCoordinate(20.0, 17.5), + QGeoCoordinate(20.0, 22.5)); + + QTest::newRow("180 height -> move") + << QGeoRectangle(QGeoCoordinate(90.0, 5.0), + QGeoCoordinate(-90.0, 10.0)) + << QGeoCoordinate(0.0, 7.5) + << QGeoCoordinate(0.0, 20.0) + << QGeoRectangle(QGeoCoordinate(90.0, 17.5), + QGeoCoordinate(-90.0, 22.5)); + + QTest::newRow("180 height -> squash top") + << QGeoRectangle(QGeoCoordinate(90.0, 5.0), + QGeoCoordinate(-90.0, 10.0)) + << QGeoCoordinate(0.0, 7.5) + << QGeoCoordinate(-20.0, 20.0) + << QGeoRectangle(QGeoCoordinate(50.0, 17.5), + QGeoCoordinate(-90.0, 22.5)); + + QTest::newRow("180 height -> squash bottom") + << QGeoRectangle(QGeoCoordinate(90.0, 5.0), + QGeoCoordinate(-90.0, 10.0)) + << QGeoCoordinate(0.0, 7.5) + << QGeoCoordinate(20.0, 20.0) + << QGeoRectangle(QGeoCoordinate(90.0, 17.5), + QGeoCoordinate(-50.0, 22.5)); + + QTest::newRow("non wrapping -> non wrapping") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << QGeoCoordinate(50.0, 50.0) + << QGeoCoordinate(10.0, 10.0) + << QGeoRectangle(QGeoCoordinate(30.0, -10.0), + QGeoCoordinate(-10.0, 30.0)); + + QTest::newRow("non wrapping -> wrapping") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << QGeoCoordinate(50.0, 50.0) + << QGeoCoordinate(10.0, 170.0) + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-10.0, -170.0)); + + QTest::newRow("non wrapping -> squash top") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << QGeoCoordinate(50.0, 50.0) + << QGeoCoordinate(80.0, 50.0) + << QGeoRectangle(QGeoCoordinate(90.0, 30.0), + QGeoCoordinate(70.0, 70.0)); + + QTest::newRow("non wrapping -> squash bottom") + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)) + << QGeoCoordinate(50.0, 50.0) + << QGeoCoordinate(-80.0, 50.0) + << QGeoRectangle(QGeoCoordinate(-70.0, 30.0), + QGeoCoordinate(-90.0, 70.0)); + + QTest::newRow("wrapping -> non wrapping") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-10.0, -170.0)) + << QGeoCoordinate(10.0, 170.0) + << QGeoCoordinate(50.0, 50.0) + << QGeoRectangle(QGeoCoordinate(70.0, 30.0), + QGeoCoordinate(30.0, 70.0)); + + QTest::newRow("wrapping -> wrapping") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-10.0, -170.0)) + << QGeoCoordinate(10.0, 170.0) + << QGeoCoordinate(10.0, -170.0) + << QGeoRectangle(QGeoCoordinate(30.0, 170.0), + QGeoCoordinate(-10.0, -150.0)); + + QTest::newRow("wrapping -> squash top") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-10.0, -170.0)) + << QGeoCoordinate(10.0, 170.0) + << QGeoCoordinate(80.0, 170.0) + << QGeoRectangle(QGeoCoordinate(90.0, 150.0), + QGeoCoordinate(70.0, -170.0)); + + QTest::newRow("wrapping -> squash bottom") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-10.0, -170.0)) + << QGeoCoordinate(10.0, 170.0) + << QGeoCoordinate(-80.0, 170.0) + << QGeoRectangle(QGeoCoordinate(-70.0, 150.0), + QGeoCoordinate(-90.0, -170.0)); +} + + +void tst_QGeoRectangle::containsCoord() +{ + QFETCH(QGeoRectangle, box); + QFETCH(QGeoCoordinate, coord); + QFETCH(bool, contains); + + QCOMPARE(box.contains(coord), contains); + + QGeoShape area = box; + QCOMPARE(area.contains(coord), contains); +} + +void tst_QGeoRectangle::containsCoord_data() +{ + QTest::addColumn("box"); + QTest::addColumn("coord"); + QTest::addColumn("contains"); + + QGeoRectangle b1(QGeoCoordinate(70, 30), QGeoCoordinate(30, 70)); + + double lonLO1 = 20.0; + double lonL1 = 30.0; + double lonLI1 = 40.0; + double lonC1 = 50.0; + double lonRI1 = 60.0; + double lonR1 = 70.0; + double lonRO1 = 80.0; + + double latTO1 = 80.0; + double latT1 = 70.0; + double latTI1 = 60.0; + double latC1 = 50.0; + double latBI1 = 40.0; + double latB1 = 30.0; + double latBO1 = 20.0; + + QTest::newRow("non wrapped - in center") + << b1 << QGeoCoordinate(latC1, lonC1) << true; + QTest::newRow("non wrapped - left edge - inside") + << b1 << QGeoCoordinate(latC1, lonLI1) << true; + QTest::newRow("non wrapped - left edge") + << b1 << QGeoCoordinate(latC1, lonL1) << true; + QTest::newRow("non wrapped - left edge - outside") + << b1 << QGeoCoordinate(latC1, lonLO1) << false; + QTest::newRow("non wrapped - right edge - inside") + << b1 << QGeoCoordinate(latC1, lonRI1) << true; + QTest::newRow("non wrapped - right edge") + << b1 << QGeoCoordinate(latC1, lonR1) << true; + QTest::newRow("non wrapped - right edge - outside") + << b1 << QGeoCoordinate(latC1, lonRO1) << false; + QTest::newRow("non wrapped - top edge - inside") + << b1 << QGeoCoordinate(latTI1, lonC1) << true; + QTest::newRow("non wrapped - top edge") + << b1 << QGeoCoordinate(latT1, lonC1) << true; + QTest::newRow("non wrapped - top edge - outside") + << b1 << QGeoCoordinate(latTO1, lonC1) << false; + QTest::newRow("non wrapped - bottom edge - inside") + << b1 << QGeoCoordinate(latBI1, lonC1) << true; + QTest::newRow("non wrapped - bottom edge") + << b1 << QGeoCoordinate(latB1, lonC1) << true; + QTest::newRow("non wrapped - bottom edge - outside") + << b1 << QGeoCoordinate(latBO1, lonC1) << false; + QTest::newRow("non wrapped - top left - inside") + << b1 << QGeoCoordinate(latTI1, lonLI1) << true; + QTest::newRow("non wrapped - top left") + << b1 << QGeoCoordinate(latT1, lonL1) << true; + QTest::newRow("non wrapped - top left - outside") + << b1 << QGeoCoordinate(latTO1, lonLO1) << false; + QTest::newRow("non wrapped - top right - inside") + << b1 << QGeoCoordinate(latTI1, lonRI1) << true; + QTest::newRow("non wrapped - top right") + << b1 << QGeoCoordinate(latT1, lonR1) << true; + QTest::newRow("non wrapped - top right - outside") + << b1 << QGeoCoordinate(latTO1, lonRO1) << false; + QTest::newRow("non wrapped - bottom left - inside") + << b1 << QGeoCoordinate(latBI1, lonLI1) << true; + QTest::newRow("non wrapped - bottom left") + << b1 << QGeoCoordinate(latB1, lonL1) << true; + QTest::newRow("non wrapped - bottom left - outside") + << b1 << QGeoCoordinate(latBO1, lonLO1) << false; + QTest::newRow("non wrapped - bottom right - inside") + << b1 << QGeoCoordinate(latBI1, lonRI1) << true; + QTest::newRow("non wrapped - bottom right") + << b1 << QGeoCoordinate(latB1, lonR1) << true; + QTest::newRow("non wrapped - bottom right - outside") + << b1 << QGeoCoordinate(latBO1, lonRO1) << false; + + QGeoRectangle b2(QGeoCoordinate(70, 150), QGeoCoordinate(30, -170)); + + double lonLO2 = 140.0; + double lonL2 = 150.0; + double lonLI2 = 160.0; + double lonC2 = 170.0; + double lonRI2 = 180.0; + double lonR2 = -170.0; + double lonRO2 = -160.0; + + double latTO2 = 80.0; + double latT2 = 70.0; + double latTI2 = 60.0; + double latC2 = 50.0; + double latBI2 = 40.0; + double latB2 = 30.0; + double latBO2 = 20.0; + + QTest::newRow("wrapped - in center") + << b2 << QGeoCoordinate(latC2, lonC2) << true; + QTest::newRow("wrapped - left edge - inside") + << b2 << QGeoCoordinate(latC2, lonLI2) << true; + QTest::newRow("wrapped - left edge") + << b2 << QGeoCoordinate(latC2, lonL2) << true; + QTest::newRow("wrapped - left edge - outside") + << b2 << QGeoCoordinate(latC2, lonLO2) << false; + QTest::newRow("wrapped - right edge - inside") + << b2 << QGeoCoordinate(latC2, lonRI2) << true; + QTest::newRow("wrapped - right edge") + << b2 << QGeoCoordinate(latC2, lonR2) << true; + QTest::newRow("wrapped - right edge - outside") + << b2 << QGeoCoordinate(latC2, lonRO2) << false; + QTest::newRow("wrapped - top edge - inside") + << b2 << QGeoCoordinate(latTI2, lonC2) << true; + QTest::newRow("wrapped - top edge") + << b2 << QGeoCoordinate(latT2, lonC2) << true; + QTest::newRow("wrapped - top edge - outside") + << b2 << QGeoCoordinate(latTO2, lonC2) << false; + QTest::newRow("wrapped - bottom edge - inside") + << b2 << QGeoCoordinate(latBI2, lonC2) << true; + QTest::newRow("wrapped - bottom edge") + << b2 << QGeoCoordinate(latB2, lonC2) << true; + QTest::newRow("wrapped - bottom edge - outside") + << b2 << QGeoCoordinate(latBO2, lonC2) << false; + QTest::newRow("wrapped - top left - inside") + << b2 << QGeoCoordinate(latTI2, lonLI2) << true; + QTest::newRow("wrapped - top left") + << b2 << QGeoCoordinate(latT2, lonL2) << true; + QTest::newRow("wrapped - top left - outside") + << b2 << QGeoCoordinate(latTO2, lonLO2) << false; + QTest::newRow("wrapped - top right - inside") + << b2 << QGeoCoordinate(latTI2, lonRI2) << true; + QTest::newRow("wrapped - top right") + << b2 << QGeoCoordinate(latT2, lonR2) << true; + QTest::newRow("wrapped - top right - outside") + << b2 << QGeoCoordinate(latTO2, lonRO2) << false; + QTest::newRow("wrapped - bottom left - inside") + << b2 << QGeoCoordinate(latBI2, lonLI2) << true; + QTest::newRow("wrapped - bottom left") + << b2 << QGeoCoordinate(latB2, lonL2) << true; + QTest::newRow("wrapped - bottom left - outside") + << b2 << QGeoCoordinate(latBO2, lonLO2) << false; + QTest::newRow("wrapped - bottom right - inside") + << b2 << QGeoCoordinate(latBI2, lonRI2) << true; + QTest::newRow("wrapped - bottom right") + << b2 << QGeoCoordinate(latB2, lonR2) << true; + QTest::newRow("wrapped - bottom right - outside") + << b2 << QGeoCoordinate(latBO2, lonRO2) << false; + + QGeoRectangle b3(QGeoCoordinate(90, 30), QGeoCoordinate(50, 70)); + + double lonLO3 = 20.0; + double lonL3 = 30.0; + double lonLI3 = 40.0; + double lonC3 = 50.0; + double lonRI3 = 60.0; + double lonR3 = 70.0; + double lonRO3 = 80.0; + + double latT3 = 90.0; + double latTI3 = 80.0; + double latC3 = 70.0; + /* current unused: + double latBI3 = 60.0; + double latB3 = 50.0; + double latBO3 = 40.0; + */ + + QTest::newRow("north pole - in center") + << b3 << QGeoCoordinate(latC3, lonC3) << true; + QTest::newRow("north pole - left edge - inside") + << b3 << QGeoCoordinate(latC3, lonLI3) << true; + QTest::newRow("north pole - left edge") + << b3 << QGeoCoordinate(latC3, lonL3) << true; + QTest::newRow("north pole - left edge - outside") + << b3 << QGeoCoordinate(latC3, lonLO3) << false; + QTest::newRow("north pole - right edge - inside") + << b3 << QGeoCoordinate(latC3, lonRI3) << true; + QTest::newRow("north pole - right edge") + << b3 << QGeoCoordinate(latC3, lonR3) << true; + QTest::newRow("north pole - right edge - outside") + << b3 << QGeoCoordinate(latC3, lonRO3) << false; + QTest::newRow("north pole - top edge - inside") + << b3 << QGeoCoordinate(latTI3, lonC3) << true; + QTest::newRow("north pole - top edge") + << b3 << QGeoCoordinate(latT3, lonC3) << true; + QTest::newRow("north pole - top left - inside") + << b3 << QGeoCoordinate(latTI3, lonLI3) << true; + QTest::newRow("north pole - top left") + << b3 << QGeoCoordinate(latT3, lonL3) << true; + QTest::newRow("north pole - top left - outside") + << b3 << QGeoCoordinate(latT3, lonLO3) << true; + QTest::newRow("north pole - top right - inside") + << b3 << QGeoCoordinate(latTI3, lonRI3) << true; + QTest::newRow("north pole - top right") + << b3 << QGeoCoordinate(latT3, lonR3) << true; + QTest::newRow("north pole - top right - outside") + << b3 << QGeoCoordinate(latT3, lonRO3) << true; + + QGeoRectangle b4(QGeoCoordinate(-50, 30), QGeoCoordinate(-90, 70)); + + double lonLO4 = 20.0; + double lonL4 = 30.0; + double lonLI4 = 40.0; + double lonC4 = 50.0; + double lonRI4 = 60.0; + double lonR4 = 70.0; + double lonRO4 = 80.0; + + /* currently unused: + double latTO4 = -40.0; + double latT4 = -50.0; + double latTI4 = -60.0; + */ + double latC4 = -70.0; + double latBI4 = -80.0; + double latB4 = -90.0; + + QTest::newRow("south pole - in center") + << b4 << QGeoCoordinate(latC4, lonC4) << true; + QTest::newRow("south pole - left edge - inside") + << b4 << QGeoCoordinate(latC4, lonLI4) << true; + QTest::newRow("south pole - left edge") + << b4 << QGeoCoordinate(latC4, lonL4) << true; + QTest::newRow("south pole - left edge - outside") + << b4 << QGeoCoordinate(latC4, lonLO4) << false; + QTest::newRow("south pole - right edge - inside") + << b4 << QGeoCoordinate(latC4, lonRI4) << true; + QTest::newRow("south pole - right edge") + << b4 << QGeoCoordinate(latC4, lonR4) << true; + QTest::newRow("south pole - right edge - outside") + << b4 << QGeoCoordinate(latC4, lonRO4) << false; + QTest::newRow("south pole - bottom edge - inside") + << b4 << QGeoCoordinate(latBI4, lonC4) << true; + QTest::newRow("south pole - bottom edge") + << b4 << QGeoCoordinate(latB4, lonC4) << true; + QTest::newRow("south pole - bottom left - inside") + << b4 << QGeoCoordinate(latBI4, lonLI4) << true; + QTest::newRow("south pole - bottom left") + << b4 << QGeoCoordinate(latB4, lonL4) << true; + QTest::newRow("south pole - bottom left - outside") + << b4 << QGeoCoordinate(latB4, lonLO4) << true; + QTest::newRow("south pole - bottom right - inside") + << b4 << QGeoCoordinate(latBI4, lonRI4) << true; + QTest::newRow("south pole - bottom right") + << b4 << QGeoCoordinate(latB4, lonR4) << true; + QTest::newRow("south pole - bottom right - outside") + << b4 << QGeoCoordinate(latB4, lonRO4) << true; +} + +void tst_QGeoRectangle::containsBoxAndIntersects() +{ + QFETCH(QGeoRectangle, box1); + QFETCH(QGeoRectangle, box2); + QFETCH(bool, contains); + QFETCH(bool, intersects); + + QCOMPARE(box1.contains(box2), contains); + QCOMPARE(box1.intersects(box2), intersects); +} + +void tst_QGeoRectangle::containsBoxAndIntersects_data() +{ + QTest::addColumn("box1"); + QTest::addColumn("box2"); + QTest::addColumn("contains"); + QTest::addColumn("intersects"); + + QGeoRectangle b1(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)); + + QTest::newRow("non wrapped same") + << b1 + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << true << true; + + QTest::newRow("non wrapped smaller") + << b1 + << QGeoRectangle(QGeoCoordinate(20.0, -20.0), + QGeoCoordinate(-20.0, 20.0)) + << true << true; + + QTest::newRow("non wrapped larger") + << b1 + << QGeoRectangle(QGeoCoordinate(40.0, -40.0), + QGeoCoordinate(-40.0, 40.0)) + << false << true; + + QTest::newRow("non wrapped outside top") + << b1 + << QGeoRectangle(QGeoCoordinate(80.0, -30.0), + QGeoCoordinate(50.0, 30.0)) + << false << false; + + QTest::newRow("non wrapped outside bottom") + << b1 + << QGeoRectangle(QGeoCoordinate(-50.0, -30.0), + QGeoCoordinate(-80.0, 30.0)) + << false << false; + + QTest::newRow("non wrapped outside left") + << b1 + << QGeoRectangle(QGeoCoordinate(30.0, -80.0), + QGeoCoordinate(-30.0, -50.0)) + << false << false; + + QTest::newRow("non wrapped outside wrapped") + << b1 + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << false << false; + + QTest::newRow("non wrapped outside right") + << b1 + << QGeoRectangle(QGeoCoordinate(30.0, 50.0), + QGeoCoordinate(-30.0, 80.0)) + << false << false; + + QTest::newRow("non wrapped top left cross") + << b1 + << QGeoRectangle(QGeoCoordinate(40.0, -40.0), + QGeoCoordinate(20.0, -20.0)) + << false << true; + + QTest::newRow("non wrapped top cross") + << b1 + << QGeoRectangle(QGeoCoordinate(40.0, -10.0), + QGeoCoordinate(20.0, 10.0)) + << false << true; + + QTest::newRow("non wrapped top right cross") + << b1 + << QGeoRectangle(QGeoCoordinate(40.0, 20.0), + QGeoCoordinate(20.0, 40.0)) + << false << true; + + QTest::newRow("non wrapped left cross") + << b1 + << QGeoRectangle(QGeoCoordinate(10.0, -40.0), + QGeoCoordinate(-10.0, -20.0)) + << false << true; + + QTest::newRow("non wrapped right cross") + << b1 + << QGeoRectangle(QGeoCoordinate(10.0, 20.0), + QGeoCoordinate(-10.0, 40.0)) + << false << true; + + QTest::newRow("non wrapped bottom left cross") + << b1 + << QGeoRectangle(QGeoCoordinate(-20.0, -40.0), + QGeoCoordinate(-40.0, -20.0)) + << false << true; + + QTest::newRow("non wrapped bottom cross") + << b1 + << QGeoRectangle(QGeoCoordinate(-20.0, -10.0), + QGeoCoordinate(-40.0, 10.0)) + << false << true; + + QTest::newRow("non wrapped bottom right cross") + << b1 + << QGeoRectangle(QGeoCoordinate(-20.0, 20.0), + QGeoCoordinate(-40.0, 40.0)) + << false << true; + + QTest::newRow("non wrapped top left touch outside") + << b1 + << QGeoRectangle(QGeoCoordinate(50.0, -50.0), + QGeoCoordinate(30.0, -30.0)) + << false << true; + + QTest::newRow("non wrapped top touch outside") + << b1 + << QGeoRectangle(QGeoCoordinate(50.0, -10.0), + QGeoCoordinate(30.0, 10.0)) + << false << true; + + QTest::newRow("non wrapped top right touch outside") + << b1 + << QGeoRectangle(QGeoCoordinate(50.0, 30.0), + QGeoCoordinate(30.0, 50.0)) + << false << true; + + QTest::newRow("non wrapped left touch outside") + << b1 + << QGeoRectangle(QGeoCoordinate(10.0, -50.0), + QGeoCoordinate(-10.0, -30.0)) + << false << true; + + QTest::newRow("non wrapped right touch outside") + << b1 + << QGeoRectangle(QGeoCoordinate(10.0, 30.0), + QGeoCoordinate(-10.0, 50.0)) + << false << true; + + QTest::newRow("non wrapped bottom left touch outside") + << b1 + << QGeoRectangle(QGeoCoordinate(-30.0, -30.0), + QGeoCoordinate(-50.0, -50.0)) + << false << true; + + QTest::newRow("non wrapped bottom touch outside") + << b1 + << QGeoRectangle(QGeoCoordinate(-30.0, -10.0), + QGeoCoordinate(-50.0, 10.0)) + << false << true; + + QTest::newRow("non wrapped bottom right touch outside") + << b1 + << QGeoRectangle(QGeoCoordinate(-30.0, 30.0), + QGeoCoordinate(-50.0, 50.0)) + << false << true; + + QTest::newRow("non wrapped top left touch inside") + << b1 + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(10.0, -10.0)) + << true << true; + + QTest::newRow("non wrapped top touch inside") + << b1 + << QGeoRectangle(QGeoCoordinate(30.0, -10.0), + QGeoCoordinate(10.0, 10.0)) + << true << true; + + QTest::newRow("non wrapped top right touch inside") + << b1 + << QGeoRectangle(QGeoCoordinate(30.0, 10.0), + QGeoCoordinate(10.0, 30.0)) + << true << true; + + QTest::newRow("non wrapped left touch inside") + << b1 + << QGeoRectangle(QGeoCoordinate(10.0, -30.0), + QGeoCoordinate(-10.0, -10.0)) + << true << true; + + QTest::newRow("non wrapped right touch inside") + << b1 + << QGeoRectangle(QGeoCoordinate(10.0, 10.0), + QGeoCoordinate(-10.0, 30.0)) + << true << true; + + QTest::newRow("non wrapped bottom left touch inside") + << b1 + << QGeoRectangle(QGeoCoordinate(-10.0, -30.0), + QGeoCoordinate(-30.0, -10.0)) + << true << true; + + QTest::newRow("non wrapped bottom touch inside") + << b1 + << QGeoRectangle(QGeoCoordinate(-10.0, -10.0), + QGeoCoordinate(-30.0, 10.0)) + << true << true; + + QTest::newRow("non wrapped bottom right touch inside") + << b1 + << QGeoRectangle(QGeoCoordinate(-10.0, 10.0), + QGeoCoordinate(-30.0, 30.0)) + << true << true; + + QTest::newRow("non wrapped top lon strip") + << b1 + << QGeoRectangle(QGeoCoordinate(40.0, -40.0), + QGeoCoordinate(20.0, 40.0)) + << false << true; + + QTest::newRow("non wrapped center lon strip") + << b1 + << QGeoRectangle(QGeoCoordinate(10.0, -40.0), + QGeoCoordinate(-10.0, 40.0)) + << false << true; + + QTest::newRow("non wrapped bottom lon strip") + << b1 + << QGeoRectangle(QGeoCoordinate(-20.0, -40.0), + QGeoCoordinate(-40.0, 40.0)) + << false << true; + + QTest::newRow("non wrapped left lat strip") + << b1 + << QGeoRectangle(QGeoCoordinate(40.0, -40.0), + QGeoCoordinate(-40.0, -20.0)) + << false << true; + + QTest::newRow("non wrapped center lat strip") + << b1 + << QGeoRectangle(QGeoCoordinate(40.0, -10.0), + QGeoCoordinate(-40.0, 10.0)) + << false << true; + + QTest::newRow("non wrapped right lat strip") + << b1 + << QGeoRectangle(QGeoCoordinate(40.0, 20.0), + QGeoCoordinate(-40.0, 40.0)) + << false << true; + + QGeoRectangle b2(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)); + + QTest::newRow("wrapped same") + << b2 + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << true << true; + + QTest::newRow("wrapped smaller") + << b2 + << QGeoRectangle(QGeoCoordinate(20.0, 160.0), + QGeoCoordinate(-20.0, -160.0)) + << true << true; + + QTest::newRow("wrapped larger") + << b2 + << QGeoRectangle(QGeoCoordinate(40.0, 140.0), + QGeoCoordinate(-40.0, -140.0)) + << false << true; + + QTest::newRow("wrapped outside top") + << b2 + << QGeoRectangle(QGeoCoordinate(80.0, 150.0), + QGeoCoordinate(50.0, -150.0)) + << false << false; + + QTest::newRow("wrapped outside bottom") + << b2 + << QGeoRectangle(QGeoCoordinate(-50.0, 150.0), + QGeoCoordinate(-80.0, -150.0)) + << false << false; + + QTest::newRow("wrapped outside left") + << b2 + << QGeoRectangle(QGeoCoordinate(30.0, 70.0), + QGeoCoordinate(-30.0, 130.0)) + << false << false; + + QTest::newRow("wrapped outside right") + << b2 + << QGeoRectangle(QGeoCoordinate(30.0, -130.0), + QGeoCoordinate(-30.0, -70.0)) + << false << false; + + QTest::newRow("wrapped top left cross") + << b2 + << QGeoRectangle(QGeoCoordinate(40.0, 140.0), + QGeoCoordinate(20.0, 160.0)) + << false << true; + + QTest::newRow("wrapped top cross") + << b2 + << QGeoRectangle(QGeoCoordinate(40.0, 170.0), + QGeoCoordinate(20.0, -170.0)) + << false << true; + + QTest::newRow("wrapped top right cross") + << b2 + << QGeoRectangle(QGeoCoordinate(40.0, -160.0), + QGeoCoordinate(20.0, -140.0)) + << false << true; + + QTest::newRow("wrapped left cross") + << b2 + << QGeoRectangle(QGeoCoordinate(10.0, 140.0), + QGeoCoordinate(-10.0, 160.0)) + << false << true; + + QTest::newRow("wrapped right cross") + << b2 + << QGeoRectangle(QGeoCoordinate(10.0, -160.0), + QGeoCoordinate(-10.0, -140.0)) + << false << true; + + QTest::newRow("wrapped bottom left cross") + << b2 + << QGeoRectangle(QGeoCoordinate(-20.0, 140.0), + QGeoCoordinate(-40.0, 160.0)) + << false << true; + + QTest::newRow("wrapped bottom cross") + << b2 + << QGeoRectangle(QGeoCoordinate(-20.0, 170.0), + QGeoCoordinate(-40.0, -170.0)) + << false << true; + + QTest::newRow("wrapped bottom right cross") + << b2 + << QGeoRectangle(QGeoCoordinate(-20.0, -160.0), + QGeoCoordinate(-40.0, -140.0)) + << false << true; + + QTest::newRow("wrapped top left touch outside") + << b2 + << QGeoRectangle(QGeoCoordinate(50.0, 130.0), + QGeoCoordinate(30.0, 150.0)) + << false << true; + + QTest::newRow("wrapped top touch outside") + << b2 + << QGeoRectangle(QGeoCoordinate(50.0, 170.0), + QGeoCoordinate(30.0, -170.0)) + << false << true; + + QTest::newRow("wrapped top right touch outside") + << b2 + << QGeoRectangle(QGeoCoordinate(50.0, -150.0), + QGeoCoordinate(30.0, -130.0)) + << false << true; + + QTest::newRow("wrapped left touch outside") + << b2 + << QGeoRectangle(QGeoCoordinate(10.0, 130.0), + QGeoCoordinate(-10.0, 150.0)) + << false << true; + + QTest::newRow("wrapped right touch outside") + << b2 + << QGeoRectangle(QGeoCoordinate(10.0, -150.0), + QGeoCoordinate(-10.0, -130.0)) + << false << true; + + QTest::newRow("wrapped bottom left touch outside") + << b2 + << QGeoRectangle(QGeoCoordinate(-30.0, 150.0), + QGeoCoordinate(-50.0, 130.0)) + << false << true; + + QTest::newRow("wrapped bottom touch outside") + << b2 + << QGeoRectangle(QGeoCoordinate(-30.0, 170.0), + QGeoCoordinate(-50.0, -170.0)) + << false << true; + + QTest::newRow("wrapped bottom right touch outside") + << b2 + << QGeoRectangle(QGeoCoordinate(-30.0, -150.0), + QGeoCoordinate(-50.0, -130.0)) + << false << true; + + QTest::newRow("wrapped top left touch inside") + << b2 + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(10.0, 170.0)) + << true << true; + + QTest::newRow("wrapped top touch inside") + << b2 + << QGeoRectangle(QGeoCoordinate(30.0, 170.0), + QGeoCoordinate(10.0, -170.0)) + << true << true; + + QTest::newRow("wrapped top right touch inside") + << b2 + << QGeoRectangle(QGeoCoordinate(30.0, -170.0), + QGeoCoordinate(10.0, -150.0)) + << true << true; + + QTest::newRow("wrapped left touch inside") + << b2 + << QGeoRectangle(QGeoCoordinate(10.0, 150.0), + QGeoCoordinate(-10.0, 170.0)) + << true << true; + + QTest::newRow("wrapped right touch inside") + << b2 + << QGeoRectangle(QGeoCoordinate(10.0, -170.0), + QGeoCoordinate(-10.0, -150.0)) + << true << true; + + QTest::newRow("wrapped bottom left touch inside") + << b2 + << QGeoRectangle(QGeoCoordinate(-10.0, 150.0), + QGeoCoordinate(-30.0, 170.0)) + << true << true; + + QTest::newRow("wrapped bottom touch inside") + << b2 + << QGeoRectangle(QGeoCoordinate(-10.0, 170.0), + QGeoCoordinate(-30.0, -170.0)) + << true << true; + + QTest::newRow("wrapped bottom right touch inside") + << b2 + << QGeoRectangle(QGeoCoordinate(-10.0, -170.0), + QGeoCoordinate(-30.0, -150.0)) + << true << true; + + QTest::newRow("wrapped top lon strip") + << b2 + << QGeoRectangle(QGeoCoordinate(40.0, 140.0), + QGeoCoordinate(20.0, -140.0)) + << false << true; + + QTest::newRow("wrapped center lon strip") + << b2 + << QGeoRectangle(QGeoCoordinate(10.0, 140.0), + QGeoCoordinate(-10.0, -140.0)) + << false << true; + + QTest::newRow("wrapped bottom lon strip") + << b2 + << QGeoRectangle(QGeoCoordinate(-20.0, 140.0), + QGeoCoordinate(-40.0, -140.0)) + << false << true; + + QTest::newRow("wrapped left lat strip") + << b2 + << QGeoRectangle(QGeoCoordinate(40.0, 140.0), + QGeoCoordinate(-40.0, 160.0)) + << false << true; + + QTest::newRow("wrapped center lat strip") + << b2 + << QGeoRectangle(QGeoCoordinate(40.0, 170.0), + QGeoCoordinate(-40.0, -170.0)) + << false << true; + + QTest::newRow("wrapped right lat strip") + << b2 + << QGeoRectangle(QGeoCoordinate(40.0, -160.0), + QGeoCoordinate(-40.0, -140.0)) + << false << true; + + QTest::newRow("north pole touching") + << QGeoRectangle(QGeoCoordinate(90.0, 20.0), + QGeoCoordinate(40.0, 40.0)) + << QGeoRectangle(QGeoCoordinate(90.0, 60.0), + QGeoCoordinate(30.0, 80.0)) + << false << true; + + QTest::newRow("south pole touching") + << QGeoRectangle(QGeoCoordinate(40.0, 20.0), + QGeoCoordinate(-90.0, 40.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 60.0), + QGeoCoordinate(-90.0, 80.0)) + << false << true; +} + +void tst_QGeoRectangle::translate() +{ + QFETCH(QGeoRectangle, box); + QFETCH(double, degreesLatitude); + QFETCH(double, degreesLongitude); + QFETCH(QGeoRectangle, newBox); + + QGeoRectangle test = box.translated(degreesLatitude, degreesLongitude); + QCOMPARE(test, newBox); + box.translate(degreesLatitude, degreesLongitude); + QCOMPARE(box, newBox); + +} + +void tst_QGeoRectangle::translate_data() +{ + QTest::addColumn("box"); + QTest::addColumn("degreesLatitude"); + QTest::addColumn("degreesLongitude"); + QTest::addColumn("newBox"); + + QTest::newRow("invalid") + << QGeoRectangle() + << 20.0 + << 20.0 + << QGeoRectangle(); + + QTest::newRow("360 width") + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)) + << 20.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(50.0, -180.0), + QGeoCoordinate(-10.0, 180.0)); + + QTest::newRow("180 height") + << QGeoRectangle(QGeoCoordinate(90.0, -30.0), + QGeoCoordinate(-90.0, 30.0)) + << 20.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(90.0, -10.0), + QGeoCoordinate(-90.0, 50.0)); + + QTest::newRow("non wrapping -> non wrapping") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << 20.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(50.0, -10.0), + QGeoCoordinate(-10.0, 50.0)); + + QTest::newRow("non wrapping -> wrapping") + << QGeoRectangle(QGeoCoordinate(30.0, 110.0), + QGeoCoordinate(-30.0, 170.0)) + << 20.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(50.0, 130.0), + QGeoCoordinate(-10.0, -170.0)); + + QTest::newRow("non wrapping -> north clip") + << QGeoRectangle(QGeoCoordinate(80.0, -30.0), + QGeoCoordinate(20.0, 30.0)) + << 20.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(90.0, -10.0), + QGeoCoordinate(40.0, 50.0)); + + QTest::newRow("non wrapping -> south clip") + << QGeoRectangle(QGeoCoordinate(-20.0, -30.0), + QGeoCoordinate(-80.0, 30.0)) + << -20.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(-40.0, -10.0), + QGeoCoordinate(-90.0, 50.0)); + + QTest::newRow("wrapping -> non wrapping") + << QGeoRectangle(QGeoCoordinate(30.0, 130.0), + QGeoCoordinate(-30.0, -170.0)) + << 20.0 + << -20.0 + << QGeoRectangle(QGeoCoordinate(50.0, 110.0), + QGeoCoordinate(-10.0, 170.0)); + + QTest::newRow("wrapping -> wrapping") + << QGeoRectangle(QGeoCoordinate(30.0, 130.0), + QGeoCoordinate(-30.0, -170.0)) + << 20.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(50.0, 150.0), + QGeoCoordinate(-10.0, -150.0)); + + QTest::newRow("wrapping -> north clip") + << QGeoRectangle(QGeoCoordinate(80.0, 130.0), + QGeoCoordinate(20.0, -170.0)) + << 20.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(90.0, 150.0), + QGeoCoordinate(40.0, -150.0)); + + QTest::newRow("wrapping -> south clip") + << QGeoRectangle(QGeoCoordinate(-20.0, 130.0), + QGeoCoordinate(-80.0, -170.0)) + << -20.0 + << 20.0 + << QGeoRectangle(QGeoCoordinate(-40.0, 150.0), + QGeoCoordinate(-90.0, -150.0)); +} + +void tst_QGeoRectangle::unite() +{ + QFETCH(QGeoRectangle, in1); + QFETCH(QGeoRectangle, in2); + QFETCH(QGeoRectangle, out); + + QCOMPARE(in1.united(in2), out); + QCOMPARE(in2.united(in1), out); + + QCOMPARE(in1 | in2, out); + QCOMPARE(in2 | in1, out); + + QGeoRectangle united1 = QGeoRectangle(in1); + united1 |= in2; + QCOMPARE(united1, out); + + QGeoRectangle united2 = QGeoRectangle(in2); + united2 |= in1; + QCOMPARE(united2, out); +} + +void tst_QGeoRectangle::unite_data() +{ + QTest::addColumn("in1"); + QTest::addColumn("in2"); + QTest::addColumn("out"); + + QTest::newRow("central and taller") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(50.0, -30.0), + QGeoCoordinate(-50.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(50.0, -30.0), + QGeoCoordinate(-50.0, 30.0)); + + QTest::newRow("central and 180 high") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(90.0, -30.0), + QGeoCoordinate(-90.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(90.0, -30.0), + QGeoCoordinate(-90.0, 30.0)); + + QTest::newRow("central and non overlapping higher") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(60.0, -30.0), + QGeoCoordinate(50.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(60.0, -30.0), + QGeoCoordinate(-30.0, 30.0)); + + QTest::newRow("central and overlapping higher") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(60.0, -30.0), + QGeoCoordinate(0.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(60.0, -30.0), + QGeoCoordinate(-30.0, 30.0)); + + QTest::newRow("central and touching higher") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(60.0, -30.0), + QGeoCoordinate(30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(60.0, -30.0), + QGeoCoordinate(-30.0, 30.0)); + + QTest::newRow("central and non overlapping lower") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(-50.0, -30.0), + QGeoCoordinate(-60.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-60.0, 30.0)); + + QTest::newRow("central and overlapping lower") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(0.0, -30.0), + QGeoCoordinate(-60.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-60.0, 30.0)); + + QTest::newRow("central and touching lower") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(-30.0, -30.0), + QGeoCoordinate(-60.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-60.0, 30.0)); + + QTest::newRow("non wrapping central and wider") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -50.0), + QGeoCoordinate(-30.0, 50.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -50.0), + QGeoCoordinate(-30.0, 50.0)); + + QTest::newRow("non wrapping central and 360 width") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)); + + QTest::newRow("non wrapping central and non overlapping non wrapping left") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -110.0), + QGeoCoordinate(-30.0, -50.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -110.0), + QGeoCoordinate(-30.0, 30.0)); + + QTest::newRow("non wrapping central and overlapping non wrapping left") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -80.0), + QGeoCoordinate(-30.0, -20.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -80.0), + QGeoCoordinate(-30.0, 30.0)); + + QTest::newRow("non wrapping central and touching non wrapping left") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -90.0), + QGeoCoordinate(-30.0, -30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -90.0), + QGeoCoordinate(-30.0, 30.0)); + + QTest::newRow("non wrapping central and non overlapping non wrapping right") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 50.0), + QGeoCoordinate(-30.0, 110.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 110.0)); + + QTest::newRow("non wrapping central and overlapping non wrapping right") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 20.0), + QGeoCoordinate(-30.0, 80.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 80.0)); + + QTest::newRow("non wrapping central and touching non wrapping right") + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 30.0), + QGeoCoordinate(-30.0, 90.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 90.0)); + + QTest::newRow("wrapping and wider") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 130.0), + QGeoCoordinate(-30.0, -130.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 130.0), + QGeoCoordinate(-30.0, -130.0)); + + QTest::newRow("wrapping and 360 width") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)); + + QTest::newRow("wrapping and non overlapping right") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -130.0), + QGeoCoordinate(-30.0, -70.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -70.0)); + + QTest::newRow("wrapping and overlapping right") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -160.0), + QGeoCoordinate(-30.0, -70.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -70.0)); + + QTest::newRow("wrapping and touching right") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -150.0), + QGeoCoordinate(-30.0, -90.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -90.0)); + + QTest::newRow("wrapping and non overlapping left") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 70.0), + QGeoCoordinate(-30.0, 130.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 70.0), + QGeoCoordinate(-30.0, -150.0)); + + QTest::newRow("wrapping and overlapping left") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 100.0), + QGeoCoordinate(-30.0, 160.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 100.0), + QGeoCoordinate(-30.0, -150.0)); + + QTest::newRow("wrapping and touching left") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 90.0), + QGeoCoordinate(-30.0, 150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 90.0), + QGeoCoordinate(-30.0, -150.0)); + + QTest::newRow("wrapping and non overlapping center") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -30.0), + QGeoCoordinate(-30.0, 30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)); + + QTest::newRow("wrapping and overlapping center") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -160.0), + QGeoCoordinate(-30.0, 160.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)); + + QTest::newRow("wrapping and touching center") + << QGeoRectangle(QGeoCoordinate(30.0, 150.0), + QGeoCoordinate(-30.0, -150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -150.0), + QGeoCoordinate(-30.0, 150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)); + + QTest::newRow("small gap over zero line") + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, -10.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 10.0), + QGeoCoordinate(-30.0, 20.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, 20.0)); + + QTest::newRow("small gap before zero line") + << QGeoRectangle(QGeoCoordinate(30.0, -40.0), + QGeoCoordinate(-30.0, -30.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, -10.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -40.0), + QGeoCoordinate(-30.0, -10.0)); + + QTest::newRow("small gap after zero line") + << QGeoRectangle(QGeoCoordinate(30.0, 10.0), + QGeoCoordinate(-30.0, 20.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 30.0), + QGeoCoordinate(-30.0, 40.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 10.0), + QGeoCoordinate(-30.0, 40.0)); + + QTest::newRow("small gap over dateline") + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, 170.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -170.0), + QGeoCoordinate(-30.0, -160.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, -160.0)); + + QTest::newRow("small gap before dateline") + << QGeoRectangle(QGeoCoordinate(30.0, 140.0), + QGeoCoordinate(-30.0, 150.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, 170.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 140.0), + QGeoCoordinate(-30.0, 170.0)); + + QTest::newRow("small gap after dateline") + << QGeoRectangle(QGeoCoordinate(30.0, -170.0), + QGeoCoordinate(-30.0, -160.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -150.0), + QGeoCoordinate(-30.0, -140.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -170.0), + QGeoCoordinate(-30.0, -140.0)); + + QTest::newRow("90-degree inner gap over zero line") + << QGeoRectangle(QGeoCoordinate(30.0, -55.0), + QGeoCoordinate(-30.0, -45.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 45.0), + QGeoCoordinate(-30.0, 55.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -55.0), + QGeoCoordinate(-30.0, 55.0)); + + QTest::newRow("90-degree inner gap before zero line") + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, -10.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -65.0), + QGeoCoordinate(-30.0, -55.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -65.0), + QGeoCoordinate(-30.0, -10.0)); + + QTest::newRow("90-degree inner gap after zero line") + << QGeoRectangle(QGeoCoordinate(30.0, 65.0), + QGeoCoordinate(-30.0, 75.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 10.0), + QGeoCoordinate(-30.0, 20.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 10.0), + QGeoCoordinate(-30.0, 75.0)); + + QTest::newRow("90-degree inner gap over dateline") + << QGeoRectangle(QGeoCoordinate(30.0, 125.0), + QGeoCoordinate(-30.0, 135.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -135.0), + QGeoCoordinate(-30.0, -125.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 125.0), + QGeoCoordinate(-30.0, -125.0)); + + QTest::newRow("90-degree inner gap before dateline") + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, 170.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 50.0), + QGeoCoordinate(-30.0, 60.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 50.0), + QGeoCoordinate(-30.0, 170.0)); + + QTest::newRow("90-degree inner gap after dateline") + << QGeoRectangle(QGeoCoordinate(30.0, -170.0), + QGeoCoordinate(-30.0, -160.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -60.0), + QGeoCoordinate(-30.0, -50.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -170.0), + QGeoCoordinate(-30.0, -50.0)); + + QTest::newRow("180-degree inner gap centered on zero line") + << QGeoRectangle(QGeoCoordinate(30.0, -100.0), + QGeoCoordinate(-30.0, -90.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 90.0), + QGeoCoordinate(-30.0, 100.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 90.0), + QGeoCoordinate(-30.0, -90.0)); + + QTest::newRow("180-degree outer gap cenetered on zero line") + << QGeoRectangle(QGeoCoordinate(30.0, -90.0), + QGeoCoordinate(-30.0, -80.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 80.0), + QGeoCoordinate(-30.0, 90.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -90.0), + QGeoCoordinate(-30.0, 90.0)); + + QTest::newRow("180-degree shift centered on zero line") + << QGeoRectangle(QGeoCoordinate(30.0, -100.0), + QGeoCoordinate(-30.0, -80.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 80.0), + QGeoCoordinate(-30.0, 100.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)); + + QTest::newRow("180-degree inner gap centered on dateline") + << QGeoRectangle(QGeoCoordinate(30.0, 80.0), + QGeoCoordinate(-30.0, 90.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -90.0), + QGeoCoordinate(-30.0, -80.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -90.0), + QGeoCoordinate(-30.0, 90.0)); + + QTest::newRow("180-degree outer gap centered on dateline") + << QGeoRectangle(QGeoCoordinate(30.0, 90.0), + QGeoCoordinate(-30.0, 100.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -100.0), + QGeoCoordinate(-30.0, -90.0)) + << QGeoRectangle(QGeoCoordinate(30.0, 90.0), + QGeoCoordinate(-30.0, -90.0)); + + QTest::newRow("180-degree shift centered on dateline") + << QGeoRectangle(QGeoCoordinate(30.0, 80.0), + QGeoCoordinate(-30.0, 100.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -100.0), + QGeoCoordinate(-30.0, -80.0)) + << QGeoRectangle(QGeoCoordinate(30.0, -180.0), + QGeoCoordinate(-30.0, 180.0)); +} + + +void tst_QGeoRectangle::extendShape() +{ + QFETCH(QGeoRectangle, box); + QFETCH(QGeoCoordinate, coord); + QFETCH(QGeoRectangle, out); + + box.extendShape(coord); + QCOMPARE(box, out); +} + +void tst_QGeoRectangle::extendShape_data() +{ + QTest::addColumn("box"); + QTest::addColumn("coord"); + QTest::addColumn("out"); + + QTest::newRow("valid rect - invalid coordinate") + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, 20.0)) + << QGeoCoordinate(100.0, 190.0) + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, 20)); + QTest::newRow("invalid rect - valid coordinate") + << QGeoRectangle() + << QGeoCoordinate(10.0, 10.0) + << QGeoRectangle(); + QTest::newRow("inside rect - not wrapped") + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, 20.0)) + << QGeoCoordinate(10.0, 10.0) + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, 20)); + QTest::newRow("lat outside rect - not wrapped") + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, 20.0)) + << QGeoCoordinate(40.0, 10.0) + << QGeoRectangle(QGeoCoordinate(40.0, -20.0), + QGeoCoordinate(-30.0, 20)); + QTest::newRow("positive lon outside rect - not wrapped") + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, 20.0)) + << QGeoCoordinate(10.0, 40.0) + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, 40)); + QTest::newRow("negative lon outside rect - not wrapped") + << QGeoRectangle(QGeoCoordinate(30.0, -20.0), + QGeoCoordinate(-30.0, 20.0)) + << QGeoCoordinate(10.0, -40.0) + << QGeoRectangle(QGeoCoordinate(30.0, -40.0), + QGeoCoordinate(-30.0, 20.0)); + QTest::newRow("inside rect - wrapped") + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, -160.0)) + << QGeoCoordinate(10.0, -170.0) + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, -160.0)); + QTest::newRow("lat outside rect - wrapped") + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, -160.0)) + << QGeoCoordinate(-40.0, -170.0) + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-40.0, -160.0)); + QTest::newRow("positive lon outside rect - wrapped") + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, -160.0)) + << QGeoCoordinate(10.0, 140.0) + << QGeoRectangle(QGeoCoordinate(30.0, 140.0), + QGeoCoordinate(-30.0, -160.0)); + QTest::newRow("negative lon outside rect - wrapped") + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, -160.0)) + << QGeoCoordinate(10.0, -140.0) + << QGeoRectangle(QGeoCoordinate(30.0, 160.0), + QGeoCoordinate(-30.0, -140.0)); + QTest::newRow("extending over 180 degree line eastward") + << QGeoRectangle(QGeoCoordinate(30.0, 130.0), + QGeoCoordinate(-30.0, 160.0)) + << QGeoCoordinate(10.0, -170.0) + << QGeoRectangle(QGeoCoordinate(30.0, 130.0), + QGeoCoordinate(-30.0, -170)); + QTest::newRow("extending over -180 degree line westward") + << QGeoRectangle(QGeoCoordinate(30.0, -160.0), + QGeoCoordinate(-30.0, -130.0)) + << QGeoCoordinate(10.0, 170.0) + << QGeoRectangle(QGeoCoordinate(30.0, 170.0), + QGeoCoordinate(-30.0, -130)); +} + +void tst_QGeoRectangle::areaComparison_data() +{ + QTest::addColumn("area"); + QTest::addColumn("box"); + QTest::addColumn("equal"); + + QGeoRectangle b1(QGeoCoordinate(10.0, 0.0), QGeoCoordinate(0.0, 10.0)); + QGeoRectangle b2(QGeoCoordinate(20.0, 0.0), QGeoCoordinate(0.0, 20.0)); + QGeoCircle c(QGeoCoordinate(0.0, 0.0), 10); + + QTest::newRow("default constructed") << QGeoShape() << QGeoRectangle() << false; + QTest::newRow("b1 b1") << QGeoShape(b1) << b1 << true; + QTest::newRow("b1 b2") << QGeoShape(b1) << b2 << false; + QTest::newRow("b2 b1") << QGeoShape(b2) << b1 << false; + QTest::newRow("b2 b2") << QGeoShape(b2) << b2 << true; + QTest::newRow("c b1") << QGeoShape(c) << b1 << false; +} + +void tst_QGeoRectangle::areaComparison() +{ + QFETCH(QGeoShape, area); + QFETCH(QGeoRectangle, box); + QFETCH(bool, equal); + + QCOMPARE((area == box), equal); + QCOMPARE((area != box), !equal); + + QCOMPARE((box == area), equal); + QCOMPARE((box != area), !equal); +} + +void tst_QGeoRectangle::circleComparison_data() +{ + QTest::addColumn("circle"); + QTest::addColumn("box"); + QTest::addColumn("equal"); + + QGeoRectangle b(QGeoCoordinate(10.0, 0.0), QGeoCoordinate(0.0, 10.0)); + QGeoCircle c(QGeoCoordinate(0.0, 0.0), 10); + + QTest::newRow("default constructed") << QGeoCircle() << QGeoRectangle() << false; + QTest::newRow("c b") << c << b << false; +} + +void tst_QGeoRectangle::circleComparison() +{ + QFETCH(QGeoCircle, circle); + QFETCH(QGeoRectangle, box); + QFETCH(bool, equal); + + QCOMPARE((circle == box), equal); + QCOMPARE((circle != box), !equal); + + QCOMPARE((box == circle), equal); + QCOMPARE((box != circle), !equal); +} + +QTEST_MAIN(tst_QGeoRectangle) +#include "tst_qgeorectangle.moc" + diff --git a/tests/auto/qgeoroute/qgeoroute.pro b/tests/auto/qgeoroute/qgeoroute.pro new file mode 100644 index 0000000..87ace5c --- /dev/null +++ b/tests/auto/qgeoroute/qgeoroute.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeoroute + +# Input +HEADERS += tst_qgeoroute.h +SOURCES += tst_qgeoroute.cpp + +QT += location testlib diff --git a/tests/auto/qgeoroute/tst_qgeoroute.cpp b/tests/auto/qgeoroute/tst_qgeoroute.cpp new file mode 100644 index 0000000..6cef986 --- /dev/null +++ b/tests/auto/qgeoroute/tst_qgeoroute.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tst_qgeoroute.h" + + +tst_QGeoRoute::tst_QGeoRoute() +{ +} + +void tst_QGeoRoute::initTestCase() +{ +} + +void tst_QGeoRoute::cleanupTestCase() +{ +} + +void tst_QGeoRoute::init() +{ + qgeoroute = new QGeoRoute(); + qgeocoordinate = new QGeoCoordinate(); +} + +void tst_QGeoRoute::cleanup() +{ + delete qgeoroute; + delete qgeocoordinate; +} + +void tst_QGeoRoute::constructor() +{ + QString empty = ""; + QGeoRectangle *boundingbox = new QGeoRectangle(); + + QCOMPARE(qgeoroute->bounds(), *boundingbox); + QCOMPARE(qgeoroute->distance(), qreal(0.0)); + QCOMPARE(qgeoroute->path().size(), 0); + QCOMPARE(qgeoroute->routeId(), empty); + QCOMPARE(qgeoroute->travelTime(), 0); + + delete boundingbox; +} + +void tst_QGeoRoute::copy_constructor() +{ + QGeoRoute *qgeoroutecopy = new QGeoRoute(*qgeoroute); + QCOMPARE(*qgeoroute, *qgeoroutecopy); + delete qgeoroutecopy; +} + +void tst_QGeoRoute::destructor() +{ + QGeoRoute *qgeoroutecopy; + + qgeoroutecopy = new QGeoRoute(); + delete qgeoroutecopy; + + qgeoroutecopy = new QGeoRoute(*qgeoroute); + delete qgeoroutecopy; +} + +void tst_QGeoRoute::bounds() +{ + qgeocoordinate->setLatitude(13.3851); + qgeocoordinate->setLongitude(52.5312); + + QGeoRectangle *qgeoboundingbox = new QGeoRectangle(*qgeocoordinate,0.4,0.4); + + qgeoroute->setBounds(*qgeoboundingbox); + + QCOMPARE(qgeoroute->bounds(), *qgeoboundingbox); + + qgeoboundingbox->setWidth(23.1); + + QVERIFY(qgeoroute->bounds().width() != qgeoboundingbox->width()); + + delete qgeoboundingbox; +} + +void tst_QGeoRoute::distance() +{ + qreal distance = 0.0; + + qgeoroute->setDistance(distance); + QCOMPARE(qgeoroute->distance(), distance); + + distance = 34.4324; + QVERIFY(qgeoroute->distance() != distance); + + qgeoroute->setDistance(distance); + QCOMPARE(qgeoroute->distance(), distance); +} + +void tst_QGeoRoute::path() +{ + QFETCH(QList, coordinates); + + QList path; + + for (int i = 0; i < coordinates.size(); i += 2) { + path.append(QGeoCoordinate(coordinates.at(i),coordinates.at(i+1))); + } + + qgeoroute->setPath(path); + + QList pathRetrieved = qgeoroute->path(); + QCOMPARE(pathRetrieved, path); + + for (int i = 0; i < pathRetrieved.size(); i++) { + QCOMPARE(pathRetrieved.at(i), path.at(i)); + } +} + +void tst_QGeoRoute::path_data() +{ + QTest::addColumn >("coordinates"); + + QList coordinates; + + coordinates << 0.0 << 0.0; + QTest::newRow("path1") << coordinates ; + + coordinates << -23.23 << 54.45345; + QTest::newRow("path2") << coordinates ; + + coordinates << -85.4324 << -121.343; + QTest::newRow("path3") << coordinates ; + + coordinates << 1.323 << 12.323; + QTest::newRow("path4") << coordinates ; + + coordinates << 1324.323 << 143242.323; + QTest::newRow("path5") << coordinates ; +} + +void tst_QGeoRoute::request() +{ + qgeocoordinate->setLatitude(65.654); + qgeocoordinate->setLongitude(0.4324); + + QGeoCoordinate *qgeocoordinatecopy = new QGeoCoordinate(34.54 , -21.32); + + QList path; + path.append(*qgeocoordinate); + path.append(*qgeocoordinatecopy); + + qgeorouterequest = new QGeoRouteRequest(path); + + qgeoroute->setRequest(*qgeorouterequest); + + QCOMPARE(qgeoroute->request(), *qgeorouterequest); + + QGeoCoordinate *qgeocoordinatecopy2 = new QGeoCoordinate(4.7854 , -121.32); + path.append(*qgeocoordinatecopy2); + + QGeoRouteRequest *qgeorouterequestcopy = new QGeoRouteRequest(path); + + QVERIFY(qgeoroute->request() != *qgeorouterequestcopy); + + delete qgeocoordinatecopy; + delete qgeocoordinatecopy2; + delete qgeorouterequest; + delete qgeorouterequestcopy; +} + +void tst_QGeoRoute::routeId() +{ + QString text = "routeId 4504"; + + qgeoroute->setRouteId(text); + + QCOMPARE(qgeoroute->routeId(), text); + + text = "routeId 1111"; + QVERIFY(qgeoroute->routeId() != text); + +} + +void tst_QGeoRoute::firstrouteSegments() +{ + qgeoroutesegment = new QGeoRouteSegment(); + qgeoroutesegment->setDistance(35.453); + qgeoroutesegment->setTravelTime(56); + + qgeoroute->setFirstRouteSegment(*qgeoroutesegment); + + QCOMPARE(qgeoroute->firstRouteSegment(), *qgeoroutesegment); + + QGeoRouteSegment *qgeoroutesegmentcopy = new QGeoRouteSegment (); + qgeoroutesegmentcopy->setDistance(435.432); + qgeoroutesegmentcopy->setTravelTime(786); + + QVERIFY(qgeoroute->firstRouteSegment() != *qgeoroutesegmentcopy); + + delete qgeoroutesegment; + delete qgeoroutesegmentcopy; + +} + +void tst_QGeoRoute::travelMode() +{ + QFETCH(QGeoRouteRequest::TravelMode, mode); + + qgeoroute->setTravelMode(mode); + QCOMPARE(qgeoroute->travelMode(), mode); +} +void tst_QGeoRoute::travelMode_data() +{ + QTest::addColumn("mode"); + + QTest::newRow("mode1") << QGeoRouteRequest::CarTravel; + QTest::newRow("mode2") << QGeoRouteRequest::PedestrianTravel; + QTest::newRow("mode3") << QGeoRouteRequest::BicycleTravel; + QTest::newRow("mode4") << QGeoRouteRequest::PublicTransitTravel; + QTest::newRow("mode5") << QGeoRouteRequest::TruckTravel; +} + +void tst_QGeoRoute::travelTime() +{ + int time = 0; + qgeoroute->setTravelTime(time); + + QCOMPARE (qgeoroute->travelTime(), time); + + time = 35; + + QVERIFY (qgeoroute->travelTime() != time); + + qgeoroute->setTravelTime(time); + QCOMPARE (qgeoroute->travelTime(), time); +} + +void tst_QGeoRoute::operators() +{ + QGeoRoute *qgeoroutecopy = new QGeoRoute(*qgeoroute); + + QVERIFY(qgeoroute->operator ==(*qgeoroutecopy)); + QVERIFY(!qgeoroute->operator !=(*qgeoroutecopy)); + + qgeoroute->setDistance(543.324); + qgeoroute->setRouteId("RouteId 111"); + qgeoroute->setTravelMode(QGeoRouteRequest::PedestrianTravel); + qgeoroute->setTravelTime(10); + + qgeoroutecopy->setDistance(12.21); + qgeoroutecopy->setRouteId("RouteId 666"); + qgeoroutecopy->setTravelMode(QGeoRouteRequest::BicycleTravel); + qgeoroutecopy->setTravelTime(99); + + QEXPECT_FAIL("", "QGeoRoute equality operators broken", Continue); + QVERIFY(!(qgeoroute->operator ==(*qgeoroutecopy))); + QEXPECT_FAIL("", "QGeoRoute equality operators broken", Continue); + QVERIFY(qgeoroute->operator !=(*qgeoroutecopy)); + + *qgeoroutecopy = qgeoroutecopy->operator =(*qgeoroute); + QVERIFY(qgeoroute->operator ==(*qgeoroutecopy)); + QVERIFY(!qgeoroute->operator !=(*qgeoroutecopy)); + + delete qgeoroutecopy; +} + + + +QTEST_APPLESS_MAIN(tst_QGeoRoute); diff --git a/tests/auto/qgeoroute/tst_qgeoroute.h b/tests/auto/qgeoroute/tst_qgeoroute.h new file mode 100644 index 0000000..ace9095 --- /dev/null +++ b/tests/auto/qgeoroute/tst_qgeoroute.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_QGEOROUTE_H +#define TST_QGEOROUTE_H + +#include +#include +#include + +#include +#include +#include +#include +#include + + +QT_USE_NAMESPACE + +class tst_QGeoRoute : public QObject +{ + Q_OBJECT + +public: + tst_QGeoRoute(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + //Start unit test for QGeoRoute + void constructor(); + void copy_constructor(); + void destructor(); + void bounds(); + void distance(); + void path(); + void path_data(); + void request(); + void routeId(); + void firstrouteSegments(); + void travelMode(); + void travelMode_data(); + void travelTime(); + void operators(); + //End Unit Test for QGeoRoute + +private: + QGeoRoute *qgeoroute; + QGeoRectangle *qgeoboundingbox; + QGeoCoordinate *qgeocoordinate; + QGeoRouteRequest *qgeorouterequest; + QGeoRouteSegment *qgeoroutesegment; + + +}; + +Q_DECLARE_METATYPE( QList); +Q_DECLARE_METATYPE( QList); +Q_DECLARE_METATYPE( QGeoRouteRequest::TravelMode); + + +#endif // TST_QGEOROUTE_H diff --git a/tests/auto/qgeoroutereply/qgeoroutereply.pro b/tests/auto/qgeoroutereply/qgeoroutereply.pro new file mode 100644 index 0000000..29f8480 --- /dev/null +++ b/tests/auto/qgeoroutereply/qgeoroutereply.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeoroutereply + +# Input +HEADERS += tst_qgeoroutereply.h +SOURCES += tst_qgeoroutereply.cpp + +QT += location testlib diff --git a/tests/auto/qgeoroutereply/tst_qgeoroutereply.cpp b/tests/auto/qgeoroutereply/tst_qgeoroutereply.cpp new file mode 100644 index 0000000..447181f --- /dev/null +++ b/tests/auto/qgeoroutereply/tst_qgeoroutereply.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tst_qgeoroutereply.h" + +QT_USE_NAMESPACE + +void tst_QGeoRouteReply::initTestCase() +{ + qgeocoordinate1 = new QGeoCoordinate(43.5435 , 76.342); + qgeocoordinate2 = new QGeoCoordinate(-43.5435 , 176.342); + qgeocoordinate3 = new QGeoCoordinate(-13.5435 , +76.342); + + waypoints.append(*qgeocoordinate1); + waypoints.append(*qgeocoordinate2); + waypoints.append(*qgeocoordinate3); + + qgeorouterequest = new QGeoRouteRequest(waypoints); + reply = new SubRouteReply(*qgeorouterequest); +} + +void tst_QGeoRouteReply::cleanupTestCase() +{ + delete qgeocoordinate1; + delete qgeocoordinate2; + delete qgeocoordinate3; + delete qgeorouterequest; + delete reply; +} + +void tst_QGeoRouteReply::init() +{ + qRegisterMetaType(); + signalerror = new QSignalSpy(reply, SIGNAL(error(QGeoRouteReply::Error,QString))); + signalfinished = new QSignalSpy(reply, SIGNAL(finished())); +} + +void tst_QGeoRouteReply::cleanup() +{ + delete signalerror; + delete signalfinished; +} + +void tst_QGeoRouteReply::constructor() +{ + QVERIFY(!reply->isFinished()); + QCOMPARE(reply->error(), QGeoRouteReply::NoError); + QCOMPARE(reply->request(), *qgeorouterequest); + + QVERIFY(signalerror->isValid()); + QVERIFY(signalfinished->isValid()); + + QCOMPARE(signalerror->count(),0); + QCOMPARE(signalfinished->count(),0); +} + +void tst_QGeoRouteReply::constructor_error() +{ + QFETCH(QGeoRouteReply::Error,error); + QFETCH(QString,msg); + + QVERIFY(signalerror->isValid()); + QVERIFY(signalfinished->isValid()); + + QGeoRouteReply *qgeoroutereplycopy = new QGeoRouteReply(error, msg, 0); + + QCOMPARE(signalerror->count(), 0); + QCOMPARE(signalfinished->count(), 0); + + QVERIFY(qgeoroutereplycopy->isFinished()); + QCOMPARE(qgeoroutereplycopy->error(), error); + QCOMPARE(qgeoroutereplycopy->errorString(), msg); + + delete qgeoroutereplycopy; +} + +void tst_QGeoRouteReply::constructor_error_data() +{ + QTest::addColumn("error"); + QTest::addColumn("msg"); + + QTest::newRow("error1") << QGeoRouteReply::NoError << "No error."; + QTest::newRow("error2") << QGeoRouteReply::EngineNotSetError << "Engine Not Set Error."; + QTest::newRow("error3") << QGeoRouteReply::CommunicationError << "Communication Error."; + QTest::newRow("error4") << QGeoRouteReply::ParseError << "Parse Error."; + QTest::newRow("error5") << QGeoRouteReply::UnsupportedOptionError << "Unsupported Option Error."; + QTest::newRow("error6") << QGeoRouteReply::UnknownError << "Unknown Error."; + +} + +void tst_QGeoRouteReply::destructor() +{ + QGeoRouteReply *qgeoroutereplycopy; + + QFETCH(QGeoRouteReply::Error, error); + QFETCH(QString, msg); + + qgeoroutereplycopy = new QGeoRouteReply(error, msg, 0); + delete qgeoroutereplycopy; + +} + +void tst_QGeoRouteReply::destructor_data() +{ + tst_QGeoRouteReply::constructor_error_data(); +} + +void tst_QGeoRouteReply::routes() +{ + QList routes; + QGeoRoute *route1 = new QGeoRoute(); + QGeoRoute *route2 = new QGeoRoute(); + + route1->setDistance(15.12); + route2->setDistance(20.12); + + routes.append(*route1); + routes.append(*route2); + + reply->callSetRoutes(routes); + + QList routescopy; + routescopy = reply->routes(); + QCOMPARE(routescopy,routes); + + QCOMPARE(routescopy.at(0).distance(),route1->distance()); + QCOMPARE(routescopy.at(1).distance(),route2->distance()); + + delete route1; + delete route2; +} + +void tst_QGeoRouteReply::finished() +{ + QVERIFY(signalerror->isValid()); + QVERIFY(signalfinished->isValid()); + + QCOMPARE(signalerror->count(), 0); + QCOMPARE(signalfinished->count(), 0); + + reply->callSetFinished(true); + + QCOMPARE(signalerror->count(), 0); + QCOMPARE(signalfinished->count(), 1); + + reply->callSetFinished(false); + + QCOMPARE(signalerror->count(), 0); + QCOMPARE(signalfinished->count(), 1); + + reply->callSetFinished(true); + + QCOMPARE(signalerror->count(), 0); + QCOMPARE(signalfinished->count(), 2); +} + +void tst_QGeoRouteReply::abort() +{ + QVERIFY(signalerror->isValid()); + QVERIFY(signalfinished->isValid()); + + QCOMPARE(signalerror->count(), 0); + QCOMPARE(signalfinished->count(), 0); + + reply->abort(); + + QCOMPARE(signalerror->count(), 0); + QCOMPARE(signalfinished->count(), 0); + + reply->abort(); + reply->callSetFinished(false); + reply->abort(); + + QCOMPARE(signalerror->count(), 0); + QCOMPARE(signalfinished->count(), 1); +} + +void tst_QGeoRouteReply::error() +{ + QFETCH(QGeoRouteReply::Error, error); + QFETCH(QString, msg); + + QVERIFY(signalerror->isValid()); + QVERIFY(signalfinished->isValid()); + QCOMPARE(signalerror->count(), 0); + + reply->callSetError(error,msg); + + QCOMPARE(signalerror->count(), 1); + QCOMPARE(signalfinished->count(), 1); + QCOMPARE(reply->errorString(), msg); + QCOMPARE(reply->error(), error); +} + +void tst_QGeoRouteReply::error_data() +{ + QTest::addColumn("error"); + QTest::addColumn("msg"); + + QTest::newRow("error1") << QGeoRouteReply::NoError << "No error."; + QTest::newRow("error2") << QGeoRouteReply::EngineNotSetError << "Engine Not Set Error."; + QTest::newRow("error3") << QGeoRouteReply::CommunicationError << "Communication Error."; + QTest::newRow("error4") << QGeoRouteReply::ParseError << "Parse Error."; + QTest::newRow("error5") << QGeoRouteReply::UnsupportedOptionError << "Unsupported Option Error."; + QTest::newRow("error6") << QGeoRouteReply::UnknownError << "Unknown Error."; +} + +void tst_QGeoRouteReply::request() +{ + SubRouteReply *rr = new SubRouteReply(*qgeorouterequest); + + QCOMPARE(rr->request(), *qgeorouterequest); + + delete rr; +} + +QTEST_APPLESS_MAIN(tst_QGeoRouteReply); diff --git a/tests/auto/qgeoroutereply/tst_qgeoroutereply.h b/tests/auto/qgeoroutereply/tst_qgeoroutereply.h new file mode 100644 index 0000000..aa08d72 --- /dev/null +++ b/tests/auto/qgeoroutereply/tst_qgeoroutereply.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_QGEOROUTEREPLY_H +#define TST_QGEOROUTEREPLY_H + +#include +#include +#include +#include + +#include +#include +#include +#include + +QT_USE_NAMESPACE +class SubRouteReply :public QGeoRouteReply +{ + Q_OBJECT +public: + SubRouteReply(QGeoRouteRequest request):QGeoRouteReply(request) {} + void callSetError(QGeoRouteReply::Error error, QString msg) {setError(error,msg);} + void callSetFinished(bool finished) {setFinished(finished);} + void callSetRoutes(const QList & routes ) {setRoutes(routes);} +}; + +class tst_QGeoRouteReply :public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + //Start Unit Test for QGeoRouteReply +private slots: + void constructor(); + void constructor_error(); + void constructor_error_data(); + void destructor(); + void destructor_data(); + void routes(); + void finished(); + void abort(); + void error(); + void error_data(); + void request(); + //End Unit Test for QGeoRouteReply + + +private: + QGeoCoordinate *qgeocoordinate1; + QGeoCoordinate *qgeocoordinate2; + QGeoCoordinate *qgeocoordinate3; + QGeoRouteRequest *qgeorouterequest; + QSignalSpy *signalerror; + QSignalSpy *signalfinished; + QList waypoints; + SubRouteReply* reply; +}; + +Q_DECLARE_METATYPE( QList); +Q_DECLARE_METATYPE( QList); +Q_DECLARE_METATYPE( QList); +Q_DECLARE_METATYPE( QGeoRouteReply::Error); + +#endif // TST_QGEOROUTEREPLY_H + diff --git a/tests/auto/qgeorouterequest/qgeorouterequest.pro b/tests/auto/qgeorouterequest/qgeorouterequest.pro new file mode 100644 index 0000000..1fc897c --- /dev/null +++ b/tests/auto/qgeorouterequest/qgeorouterequest.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeorouterequest + +# Input +HEADERS += tst_qgeorouterequest.h +SOURCES += tst_qgeorouterequest.cpp + +QT += location testlib diff --git a/tests/auto/qgeorouterequest/tst_qgeorouterequest.cpp b/tests/auto/qgeorouterequest/tst_qgeorouterequest.cpp new file mode 100644 index 0000000..5c43de6 --- /dev/null +++ b/tests/auto/qgeorouterequest/tst_qgeorouterequest.cpp @@ -0,0 +1,323 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tst_qgeorouterequest.h" + +#include + +QT_USE_NAMESPACE + +tst_QGeoRouteRequest::tst_QGeoRouteRequest() +{ +} + +void tst_QGeoRouteRequest::initTestCase() +{ +} + +void tst_QGeoRouteRequest::cleanupTestCase() +{ +} + +void tst_QGeoRouteRequest::init() +{ + qgeocoordinate = new QGeoCoordinate(); + qgeoboundingbox = new QGeoRectangle(); + qgeorouterequest = new QGeoRouteRequest(); +} + +void tst_QGeoRouteRequest::cleanup() +{ + delete qgeocoordinate; + delete qgeoboundingbox; + delete qgeorouterequest; +} + +void tst_QGeoRouteRequest::constructor_waypoints() +{ + QGeoCoordinate *qgeocoord1 = new QGeoCoordinate(43.5435, 76.342); + QGeoCoordinate *qgeocoord2 = new QGeoCoordinate(-43.5435, 176.342); + QGeoCoordinate *qgeocoord3 = new QGeoCoordinate(-13.5435, +76.342); + + QList waypoints; + waypoints.append(*qgeocoord1); + waypoints.append(*qgeocoord2); + waypoints.append(*qgeocoord3); + + QGeoRouteRequest *copy = new QGeoRouteRequest(waypoints); + + QCOMPARE(copy->waypoints(), waypoints); + QCOMPARE(copy->numberAlternativeRoutes(), 0); + QCOMPARE(copy->routeOptimization(), QGeoRouteRequest::FastestRoute); + QCOMPARE(copy->segmentDetail(), QGeoRouteRequest::BasicSegmentData); + QCOMPARE(copy->travelModes(), QGeoRouteRequest::CarTravel); + QCOMPARE(copy->maneuverDetail(), QGeoRouteRequest::BasicManeuvers); + + delete qgeocoord1; + delete qgeocoord2; + delete qgeocoord3; + delete copy; +} + +void tst_QGeoRouteRequest::constructor_orig_dest() +{ + QGeoCoordinate *qgeocoord1 = new QGeoCoordinate(43.5435, 76.342); + QGeoCoordinate *qgeocoord2 = new QGeoCoordinate(-43.5435, 176.342); + + QGeoRouteRequest *copy = new QGeoRouteRequest(*qgeocoord1, *qgeocoord2); + + QList waypoints; + waypoints.append(*qgeocoord1); + waypoints.append(*qgeocoord2); + + QCOMPARE(copy->waypoints(), waypoints); + QCOMPARE(copy->numberAlternativeRoutes(), 0); + QCOMPARE(copy->routeOptimization(), QGeoRouteRequest::FastestRoute); + QCOMPARE(copy->segmentDetail(), QGeoRouteRequest::BasicSegmentData); + QCOMPARE(copy->travelModes(), QGeoRouteRequest::CarTravel); + QCOMPARE(copy->maneuverDetail(), QGeoRouteRequest::BasicManeuvers); + + delete qgeocoord1; + delete qgeocoord2; + delete copy; +} + +void tst_QGeoRouteRequest::copy_constructor() +{ + QGeoRouteRequest *qgeorouterequestcopy = new QGeoRouteRequest(*qgeorouterequest); + QCOMPARE(*qgeorouterequest, *qgeorouterequestcopy); + delete qgeorouterequestcopy; +} + +void tst_QGeoRouteRequest::destructor() +{ + QGeoRouteRequest *qgeorouterequestcopy; + + qgeorouterequestcopy = new QGeoRouteRequest(); + delete qgeorouterequestcopy; + + qgeorouterequestcopy = new QGeoRouteRequest(*qgeorouterequest); + delete qgeorouterequestcopy; +} + +void tst_QGeoRouteRequest::excludeAreas() +{ + qgeocoordinate->setLatitude(13.3851); + qgeocoordinate->setLongitude(52.5312); + + QGeoCoordinate *qgeocoordinatecopy = new QGeoCoordinate(34.324 , -110.32); + + QGeoRectangle *qgeoboundingboxcopy = new QGeoRectangle(*qgeocoordinate, 0.4, 0.4); + QGeoRectangle *qgeoboundingboxcopy2 = new QGeoRectangle(*qgeocoordinatecopy, 1.2, 0.9); + QList areas; + areas.append(*qgeoboundingboxcopy); + areas.append(*qgeoboundingboxcopy2); + + qgeorouterequest->setExcludeAreas(areas); + + QCOMPARE(qgeorouterequest->excludeAreas(), areas); + + delete qgeoboundingboxcopy; + delete qgeoboundingboxcopy2; + delete qgeocoordinatecopy; +} + +void tst_QGeoRouteRequest::numberAlternativeRoutes() +{ + qgeorouterequest->setNumberAlternativeRoutes(0); + QCOMPARE(qgeorouterequest->numberAlternativeRoutes(), 0); + + qgeorouterequest->setNumberAlternativeRoutes(24); + QCOMPARE(qgeorouterequest->numberAlternativeRoutes(), 24); + + qgeorouterequest->setNumberAlternativeRoutes(-12); + + QCOMPARE(qgeorouterequest->numberAlternativeRoutes(), 0); +} + +void tst_QGeoRouteRequest::routeOptimization() +{ + QFETCH(QGeoRouteRequest::RouteOptimization, optimization); + + QCOMPARE(qgeorouterequest->routeOptimization(),QGeoRouteRequest::FastestRoute); + + qgeorouterequest->setRouteOptimization(optimization); + QCOMPARE(qgeorouterequest->routeOptimization(), optimization); +} + +void tst_QGeoRouteRequest::routeOptimization_data() +{ + QTest::addColumn("optimization"); + + QTest::newRow("optimization1") << QGeoRouteRequest::FastestRoute; + QTest::newRow("optimization2") << QGeoRouteRequest::ShortestRoute; + QTest::newRow("optimization3") << QGeoRouteRequest::MostEconomicRoute; + QTest::newRow("optimization4") << QGeoRouteRequest::MostScenicRoute; + +} + +void tst_QGeoRouteRequest::segmentDetail() +{ + QFETCH(QGeoRouteRequest::SegmentDetail, detail); + + QCOMPARE(qgeorouterequest->segmentDetail(), QGeoRouteRequest::BasicSegmentData); + + qgeorouterequest->setSegmentDetail(detail); + QCOMPARE(qgeorouterequest->segmentDetail(), detail); +} + +void tst_QGeoRouteRequest::segmentDetail_data() +{ + QTest::addColumn("detail"); + + QTest::newRow("detail1") << QGeoRouteRequest::NoSegmentData; + QTest::newRow("detail2") << QGeoRouteRequest::BasicSegmentData; +} + +void tst_QGeoRouteRequest::travelModes() +{ + QFETCH(QGeoRouteRequest::TravelMode,mode); + + QCOMPARE(qgeorouterequest->travelModes(), QGeoRouteRequest::CarTravel); + + qgeorouterequest->setTravelModes(mode); + QCOMPARE(qgeorouterequest->travelModes(), mode); +} + +void tst_QGeoRouteRequest::travelModes_data() +{ + QTest::addColumn("mode"); + + QTest::newRow("mode1") << QGeoRouteRequest::CarTravel; + QTest::newRow("mode2") << QGeoRouteRequest::PedestrianTravel; + QTest::newRow("mode3") << QGeoRouteRequest::BicycleTravel; + QTest::newRow("mode4") << QGeoRouteRequest::PublicTransitTravel; + QTest::newRow("mode5") << QGeoRouteRequest::TruckTravel; +} + +void tst_QGeoRouteRequest::waypoints() +{ + QFETCH(QList, coordinates); + + QList waypoints; + + for (int i = 0; i < coordinates.size(); i += 2) { + waypoints.append(QGeoCoordinate(coordinates.at(i), coordinates.at(i+1))); + } + + qgeorouterequest->setWaypoints(waypoints); + + QList waypointsRetrieved = qgeorouterequest->waypoints(); + QCOMPARE(waypointsRetrieved, waypoints); + + for (int i=0; i < waypointsRetrieved.size(); i++) { + QCOMPARE(waypointsRetrieved.at(i), waypoints.at(i)); + } +} + +void tst_QGeoRouteRequest::waypoints_data() +{ + QTest::addColumn >("coordinates"); + + QList coordinates; + + coordinates << 0.0 << 0.0; + QTest::newRow("path1") << coordinates ; + + coordinates << -23.23 << 54.45345; + QTest::newRow("path2") << coordinates ; + + coordinates << -85.4324 << -121.343; + QTest::newRow("path3") << coordinates ; + + coordinates << 1.323 << 12.323; + QTest::newRow("path4") << coordinates ; + + coordinates << 1324.323 << 143242.323; + QTest::newRow("path5") << coordinates ; +} + +void tst_QGeoRouteRequest::maneuverDetail() +{ + QFETCH(QGeoRouteRequest::ManeuverDetail,maneuver); + + QCOMPARE(qgeorouterequest->maneuverDetail(), QGeoRouteRequest::BasicManeuvers); + + qgeorouterequest->setManeuverDetail(maneuver); + QCOMPARE(qgeorouterequest->maneuverDetail(), maneuver); +} + +void tst_QGeoRouteRequest::maneuverDetail_data() +{ + QTest::addColumn("maneuver"); + + QTest::newRow("maneuver1") << QGeoRouteRequest::NoManeuvers; + QTest::newRow("maneuver2") << QGeoRouteRequest::BasicManeuvers; + +} + +void tst_QGeoRouteRequest::featureWeight_data() +{ + QTest::addColumn("type"); + QTest::addColumn("checkTypes"); + QTest::addColumn("initialWeight"); + QTest::addColumn("newWeight"); + QTest::addColumn("expectWeight"); + + QTest::newRow("NoFeature") << QGeoRouteRequest::NoFeature << false + << QGeoRouteRequest::NeutralFeatureWeight + << QGeoRouteRequest::PreferFeatureWeight + << QGeoRouteRequest::NeutralFeatureWeight; + QTest::newRow("TollFeature") << QGeoRouteRequest::TollFeature << true + << QGeoRouteRequest::NeutralFeatureWeight + << QGeoRouteRequest::PreferFeatureWeight + << QGeoRouteRequest::PreferFeatureWeight; + QTest::newRow("HighwayFeature") << QGeoRouteRequest::HighwayFeature << true + << QGeoRouteRequest::NeutralFeatureWeight + << QGeoRouteRequest::RequireFeatureWeight + << QGeoRouteRequest::RequireFeatureWeight; +} + +void tst_QGeoRouteRequest::featureWeight() +{ + QFETCH(QGeoRouteRequest::FeatureType, type); + QFETCH(bool, checkTypes); + QFETCH(QGeoRouteRequest::FeatureWeight, initialWeight); + QFETCH(QGeoRouteRequest::FeatureWeight, newWeight); + QFETCH(QGeoRouteRequest::FeatureWeight, expectWeight); + + QCOMPARE(qgeorouterequest->featureWeight(type), initialWeight); + qgeorouterequest->setFeatureWeight(type, newWeight); + QCOMPARE(qgeorouterequest->featureWeight(type), expectWeight); + + if (checkTypes) + QVERIFY(qgeorouterequest->featureTypes().contains(type)); +} + + +QTEST_APPLESS_MAIN(tst_QGeoRouteRequest); diff --git a/tests/auto/qgeorouterequest/tst_qgeorouterequest.h b/tests/auto/qgeorouterequest/tst_qgeorouterequest.h new file mode 100644 index 0000000..736510f --- /dev/null +++ b/tests/auto/qgeorouterequest/tst_qgeorouterequest.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_QGEOROUTEREQUEST_H +#define TST_QGEOROUTEREQUEST_H + +#include +#include +#include + +#include +#include +#include + + +QT_USE_NAMESPACE + +class tst_QGeoRouteRequest : public QObject +{ + Q_OBJECT + +public: + tst_QGeoRouteRequest(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + //Start Unit Test for QGeoRouteRequest + void constructor_waypoints(); + void constructor_orig_dest(); + void copy_constructor(); + void destructor(); + void excludeAreas(); + void numberAlternativeRoutes(); + void routeOptimization(); + void routeOptimization_data(); + void segmentDetail(); + void segmentDetail_data(); + void travelModes(); + void travelModes_data(); + void waypoints(); + void waypoints_data(); + void maneuverDetail(); + void maneuverDetail_data(); + void featureWeight(); + void featureWeight_data(); + //End Unit Test for QGeoRouteRequest + +private: + QGeoCoordinate *qgeocoordinate; + QGeoRectangle *qgeoboundingbox; + QGeoRouteRequest *qgeorouterequest; + +}; + +Q_DECLARE_METATYPE( QList); +Q_DECLARE_METATYPE( QGeoRouteRequest::RouteOptimization ); +Q_DECLARE_METATYPE( QGeoRouteRequest::SegmentDetail ); +Q_DECLARE_METATYPE( QGeoRouteRequest::TravelMode ); +Q_DECLARE_METATYPE( QGeoRouteRequest::FeatureType); +Q_DECLARE_METATYPE( QGeoRouteRequest::FeatureWeight); +Q_DECLARE_METATYPE( QGeoRouteRequest::ManeuverDetail ); + +#endif // TST_QGEOROUTEREQUEST_H + diff --git a/tests/auto/qgeoroutesegment/qgeoroutesegment.pro b/tests/auto/qgeoroutesegment/qgeoroutesegment.pro new file mode 100644 index 0000000..413363f --- /dev/null +++ b/tests/auto/qgeoroutesegment/qgeoroutesegment.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeoroutesegment + +# Input +HEADERS += tst_qgeoroutesegment.h +SOURCES += tst_qgeoroutesegment.cpp + +QT += location testlib diff --git a/tests/auto/qgeoroutesegment/tst_qgeoroutesegment.cpp b/tests/auto/qgeoroutesegment/tst_qgeoroutesegment.cpp new file mode 100644 index 0000000..ebe2b56 --- /dev/null +++ b/tests/auto/qgeoroutesegment/tst_qgeoroutesegment.cpp @@ -0,0 +1,302 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tst_qgeoroutesegment.h" + +QT_USE_NAMESPACE + +tst_QGeoRouteSegment::tst_QGeoRouteSegment() +{ +} + +void tst_QGeoRouteSegment::initTestCase() +{ +} + +void tst_QGeoRouteSegment::cleanupTestCase() +{ +} + +void tst_QGeoRouteSegment::init() +{ + qgeocoordinate = new QGeoCoordinate(); + qgeoroutesegment = new QGeoRouteSegment(); + qgeomaneuver = new QGeoManeuver(); +} + +void tst_QGeoRouteSegment::cleanup() +{ + delete qgeocoordinate; + delete qgeoroutesegment; +} + +void tst_QGeoRouteSegment::constructor() +{ + QVERIFY(!qgeoroutesegment->isValid()); + QCOMPARE(qgeoroutesegment->distance(), qreal(0.0)); + QCOMPARE(qgeoroutesegment->maneuver(),*qgeomaneuver); + QCOMPARE(qgeoroutesegment->travelTime(),0); +} + +void tst_QGeoRouteSegment::copy_constructor() +{ + QGeoRouteSegment *qgeoroutesegmentcopy = new QGeoRouteSegment(*qgeoroutesegment); + + QCOMPARE(*qgeoroutesegment, *qgeoroutesegmentcopy); + + QVERIFY(!qgeoroutesegmentcopy->isValid()); + QCOMPARE(qgeoroutesegmentcopy->distance(), qreal(0.0)); + QCOMPARE(qgeoroutesegmentcopy->maneuver(), *qgeomaneuver); + QCOMPARE(qgeoroutesegmentcopy->travelTime(), 0); + + delete qgeoroutesegmentcopy; +} + +void tst_QGeoRouteSegment::destructor() +{ + QGeoRouteSegment *qgeoroutesegmentcopy; + + qgeoroutesegmentcopy = new QGeoRouteSegment(); + delete qgeoroutesegmentcopy; + + qgeoroutesegmentcopy = new QGeoRouteSegment(*qgeoroutesegment); + delete qgeoroutesegmentcopy; +} + + +void tst_QGeoRouteSegment::travelTime() +{ + QFETCH(int, traveltime); + + QGeoRouteSegment sgmt; + QVERIFY(!sgmt.isValid()); + + sgmt.setTravelTime(traveltime); + + QVERIFY(sgmt.isValid()); + QCOMPARE(sgmt.travelTime(), traveltime); +} + +void tst_QGeoRouteSegment::travelTime_data() +{ + QTest::addColumn("traveltime"); + + QTest::newRow("travel1") << 0; + QTest::newRow("travel2") << -50; + QTest::newRow("travel3") << 324556; +} + +void tst_QGeoRouteSegment::distance() +{ + QFETCH(qreal, distance); + + QGeoRouteSegment sgmt; + QVERIFY(!sgmt.isValid()); + + sgmt.setDistance(distance); + + QVERIFY(sgmt.isValid()); + QCOMPARE(sgmt.distance(), distance); +} + +void tst_QGeoRouteSegment::distance_data() +{ + QTest::addColumn("distance"); + + QTest::newRow("distance1") << qreal(0.0) ; + QTest::newRow("distance2") << qreal(-50.3435) ; + QTest::newRow("distance3") << qreal(324556.543534) ; +} + + +void tst_QGeoRouteSegment::path() +{ + QFETCH(QList, coordinates); + + QGeoRouteSegment sgmt; + QVERIFY(!sgmt.isValid()); + + QList path; + + for (int i = 0; i < coordinates.size(); i += 2) { + path.append(QGeoCoordinate(coordinates.at(i), coordinates.at(i+1))); + } + + sgmt.setPath(path); + QVERIFY(sgmt.isValid()); + + QList pathretrieved = sgmt.path(); + QCOMPARE(pathretrieved, path); + + for (int i = 0; i < pathretrieved.size(); i++) { + QCOMPARE(pathretrieved.at(i), path.at(i)); + } +} + +void tst_QGeoRouteSegment::path_data() +{ + QTest::addColumn >("coordinates"); + + QList coordinates; + + coordinates << 0.0 << 0.0; + QTest::newRow("path1") << coordinates; + + coordinates << -23.23 << 54.45345; + QTest::newRow("path2") << coordinates; + + coordinates << -85.4324 << -121.343; + QTest::newRow("path3") << coordinates; + + coordinates << 1.323 << 12.323; + QTest::newRow("path4") << coordinates; + + coordinates << 1324.323 << 143242.323; + QTest::newRow("path5") << coordinates; +} + +void tst_QGeoRouteSegment::nextroutesegment() +{ + QGeoRouteSegment sgmt; + QVERIFY(!sgmt.isValid()); + + QGeoRouteSegment *qgeoroutesegmentcopy = new QGeoRouteSegment(); + qgeoroutesegmentcopy->setDistance(45.34); + + sgmt.setNextRouteSegment(*qgeoroutesegmentcopy); + + QVERIFY(sgmt.isValid()); + QCOMPARE(sgmt.nextRouteSegment(), *qgeoroutesegmentcopy); + + QCOMPARE((sgmt.nextRouteSegment()).distance(), + qgeoroutesegmentcopy->distance()); + delete qgeoroutesegmentcopy; + +} + +void tst_QGeoRouteSegment::maneuver() +{ + QGeoRouteSegment sgmt; + QVERIFY(!sgmt.isValid()); + + sgmt.setManeuver(*qgeomaneuver); + QCOMPARE(sgmt.maneuver(), *qgeomaneuver); + QVERIFY(sgmt.isValid()); +} + +void tst_QGeoRouteSegment::operators() +{ + //Create a copy and see that they are the same + QGeoRouteSegment *qgeoroutesegmentcopy = new QGeoRouteSegment(*qgeoroutesegment); + QGeoRouteSegment *trueSgmtCopy = new QGeoRouteSegment(); + + QVERIFY(qgeoroutesegment->operator ==(*qgeoroutesegmentcopy)); + QVERIFY(!qgeoroutesegment->operator !=(*qgeoroutesegmentcopy)); + QVERIFY(!qgeoroutesegment->isValid()); + QVERIFY(!qgeoroutesegmentcopy->isValid()); + + //Same segment ? content is the same but pointer different + QVERIFY(qgeoroutesegment->operator ==(*trueSgmtCopy)); + QVERIFY(!qgeoroutesegment->operator !=(*trueSgmtCopy)); + QVERIFY(!trueSgmtCopy->isValid()); + + QFETCH(double, distance); + QFETCH(int, traveltime); + QFETCH(QList, coordinates); + + QList path; + + for (int i = 0; i < coordinates.size(); i += 2) { + path.append(QGeoCoordinate(coordinates.at(i), coordinates.at(i+1))); + } + + qgeoroutesegment->setDistance(distance); + qgeoroutesegment->setTravelTime(traveltime); + qgeoroutesegment->setPath(path); + + trueSgmtCopy->setDistance(distance); + trueSgmtCopy->setTravelTime(traveltime); + trueSgmtCopy->setPath(path); + + QCOMPARE(qgeoroutesegment->distance(), distance); + QCOMPARE(qgeoroutesegment->travelTime(), traveltime); + QCOMPARE(qgeoroutesegment->path(), path); + + QCOMPARE(qgeoroutesegmentcopy->distance(), distance); + QCOMPARE(qgeoroutesegmentcopy->travelTime(), traveltime); + QCOMPARE(qgeoroutesegmentcopy->path(), path); + + QCOMPARE(trueSgmtCopy->distance(), distance); + QCOMPARE(trueSgmtCopy->travelTime(), traveltime); + QCOMPARE(trueSgmtCopy->path(), path); + + //Same as based off copy constructor (d-pointer shared) + QVERIFY(qgeoroutesegment->operator==(*qgeoroutesegmentcopy)); + QVERIFY(!qgeoroutesegment->operator!=(*qgeoroutesegmentcopy)); + + //Same as based off same content although different d-pointer + QVERIFY(qgeoroutesegment->operator==(*trueSgmtCopy)); + QVERIFY(!qgeoroutesegment->operator!=(*trueSgmtCopy)); + + const int newTravelTime = 111; + trueSgmtCopy->setTravelTime(newTravelTime); + QCOMPARE(trueSgmtCopy->travelTime(), newTravelTime); + + //different d-pointer and different content + QVERIFY(!qgeoroutesegment->operator==(*trueSgmtCopy)); + QVERIFY(qgeoroutesegment->operator!=(*trueSgmtCopy)); + + //Assign one segment to the other and test that they are the same again + *qgeoroutesegmentcopy = qgeoroutesegmentcopy->operator =(*qgeoroutesegment); + QVERIFY(qgeoroutesegment->operator==(*qgeoroutesegmentcopy)); + QVERIFY(!qgeoroutesegment->operator!=(*qgeoroutesegmentcopy)); + + *qgeoroutesegmentcopy = qgeoroutesegmentcopy->operator =(*trueSgmtCopy); + QVERIFY(trueSgmtCopy->operator==(*qgeoroutesegmentcopy)); + QVERIFY(!trueSgmtCopy->operator!=(*qgeoroutesegmentcopy)); + + delete trueSgmtCopy; + delete qgeoroutesegmentcopy; +} + +void tst_QGeoRouteSegment::operators_data() +{ + QTest::addColumn("distance"); + QTest::addColumn("traveltime"); + QTest::addColumn >("coordinates"); + + QList coordinates; + + coordinates << 0.0 << 0.0 << 23.234 << -121.767 << 8.43534 << 32.789; + QTest::newRow("set1") << 143545.43 << 45665 << coordinates; + + coordinates << 42.343 << -38.657; + QTest::newRow("set2") << 745654.43 << 786585 << coordinates; +} + +QTEST_APPLESS_MAIN(tst_QGeoRouteSegment); diff --git a/tests/auto/qgeoroutesegment/tst_qgeoroutesegment.h b/tests/auto/qgeoroutesegment/tst_qgeoroutesegment.h new file mode 100644 index 0000000..628293d --- /dev/null +++ b/tests/auto/qgeoroutesegment/tst_qgeoroutesegment.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_QGEOROUTESEGMENT_H +#define TST_QGEOROUTESEGMENT_H + +#include +#include +#include + +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QGeoRouteSegment : public QObject +{ + Q_OBJECT + +public: + tst_QGeoRouteSegment(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + //Start unit test for QGeoRouteSegment + void constructor(); + void copy_constructor(); + void destructor(); + void travelTime(); + void travelTime_data(); + void distance(); + void distance_data(); + void path(); + void path_data(); + void maneuver(); + void nextroutesegment(); + void operators(); + void operators_data(); + //End Unit Test for QGeoRouteSegment + +private: + + QGeoCoordinate *qgeocoordinate; + QGeoRouteSegment *qgeoroutesegment; + QGeoManeuver *qgeomaneuver; + +}; + +Q_DECLARE_METATYPE( QList); + +#endif // TST_GEOROUTESEGMENT_H + diff --git a/tests/auto/qgeoroutexmlparser/fixtures.qrc b/tests/auto/qgeoroutexmlparser/fixtures.qrc new file mode 100644 index 0000000..8288ea0 --- /dev/null +++ b/tests/auto/qgeoroutexmlparser/fixtures.qrc @@ -0,0 +1,6 @@ + + + route1.xml + route2.xml + + diff --git a/tests/auto/qgeoroutexmlparser/qgeoroutexmlparser.pro b/tests/auto/qgeoroutexmlparser/qgeoroutexmlparser.pro new file mode 100644 index 0000000..f9da965 --- /dev/null +++ b/tests/auto/qgeoroutexmlparser/qgeoroutexmlparser.pro @@ -0,0 +1,13 @@ +CONFIG += testcase +TARGET = tst_qgeoroutexmlparser + +plugin.path = ../../../src/plugins/geoservices/nokia/ + +SOURCES += tst_qgeoroutexmlparser.cpp \ + $$plugin.path/qgeoroutexmlparser.cpp +HEADERS += $$plugin.path/qgeoroutexmlparser.h +INCLUDEPATH += $$plugin.path +RESOURCES += fixtures.qrc + +QT += location testlib + diff --git a/tests/auto/qgeoroutexmlparser/route1.xml b/tests/auto/qgeoroutexmlparser/route1.xml new file mode 100644 index 0000000..a66f4b4 --- /dev/null +++ b/tests/auto/qgeoroutexmlparser/route1.xml @@ -0,0 +1 @@ +2012-02-21T02:51:16.997+01:002012-02-21T02:50:00.025+010046415962012-02-21T02:50:02.008+0100143512012-02-21T02:50:02.008+010045802011Q2_DICIrouteserver,9.1-2011.12.20-hotfix6.2.11.151routing-route-service,6.2.11.2REMuJj4AAAAzMzMzM5M7wIlBYOXQImNAAAAAQEGTO8AAAACg0CJjQAAAAAAAAPB_AAAAAAAA8H9PWzP4XI_C9Sjc7QBv5_up8YKMAQEAAIAr3O0AAwAAgPKCjAEBAAAAAADA_wEAAAAAAMD_gTMrH2wAy2s1l8HnuszFwwBp-130852017-27.5752144153.0879669-27.575153.088stopOver+130731232-27.4650097153.0230255-27.465153.023stopOverfastestNowcarenabled-27.5752144,153.0879669 -27.5752602,153.0882263 -27.5753899,153.0891418 -27.5754299,153.089447 -27.5755901,153.0905914 -27.5756607,153.0911255 -27.5757198,153.091568 -27.5757504,153.0918121 -27.5757809,153.0920258 -27.5752907,153.0918121 -27.5749302,153.0916748 -27.5740795,153.0913239 -27.5734901,153.091095 -27.5731201,153.0909119 -27.5728893,153.0908051 -27.5723991,153.0906067 -27.5722103,153.0904999 -27.5719509,153.0903625 -27.5717106,153.0902557 -27.5714703,153.0901337 -27.5711498,153.0900116 -27.5710392,153.0898895 -27.5704498,153.0897064 -27.5699806,153.0894012 -27.5698109,153.0892334 -27.5696507,153.0890503 -27.5693398,153.0885468 -27.5685005,153.0870361 -27.5683002,153.0866852 -27.5681305,153.0865479 -27.5675297,153.0855865 -27.5662403,153.0835724 -27.5645599,153.0809937 -27.5645103,153.0809174 -27.5644493,153.0808258 -27.5643902,153.080719 -27.5632801,153.0790863 -27.5629597,153.0786438 -27.5626793,153.0782623 -27.5623398,153.0778046 -27.5618191,153.0771027 -27.5615292,153.0767517 -27.56147,153.0766754 -27.5613995,153.0765839 -27.5612907,153.0764771 -27.5612202,153.0764008 -27.5611191,153.0762939 -27.5605106,153.0756226 -27.5587692,153.0739288 -27.5560703,153.0716248 -27.5530605,153.0691223 -27.5518303,153.0680542 -27.5516701,153.0679169 -27.5500202,153.0665436 -27.5492992,153.0659485 -27.5465107,153.0635986 -27.5454407,153.0627136 -27.5446301,153.062027 -27.5444107,153.0618439 -27.5436707,153.0612946 -27.5428104,153.0607452 -27.5418606,153.0602264 -27.5410309,153.0598297 -27.5407505,153.0596924 -27.5401402,153.0594635 -27.5396996,153.0593262 -27.5380306,153.0588379 -27.5377598,153.0587616 -27.5372505,153.0586548 -27.5360794,153.0584106 -27.5345192,153.058075 -27.5335693,153.0578766 -27.5287495,153.0568542 -27.5279198,153.0566559 -27.5272694,153.0564575 -27.52668,153.0562439 -27.5265102,153.0561676 -27.5260201,153.055954 -27.5256195,153.0557709 -27.5253601,153.0556335 -27.5246906,153.0552826 -27.5240498,153.0548706 -27.5235901,153.0545044 -27.5233498,153.0543213 -27.5231991,153.0542145 -27.5209904,153.052475 -27.5201492,153.0517731 -27.5198994,153.0515747 -27.5198002,153.0514832 -27.5197201,153.0514374 -27.5196705,153.0513916 -27.5188999,153.0507507 -27.51824,153.0500336 -27.5175304,153.0490723 -27.5173092,153.0487061 -27.5169201,153.0479431 -27.5146999,153.0434113 -27.5142193,153.0424347 -27.5138206,153.0417633 -27.5135002,153.0413666 -27.5131302,153.0409546 -27.5129299,153.0407715 -27.5126896,153.0405731 -27.5122299,153.0402832 -27.5098591,153.0390167 -27.5095406,153.0388641 -27.5092793,153.0387726 -27.5090008,153.038681 -27.5088291,153.0386353 -27.5083199,153.0385437 -27.5077591,153.0385132 -27.5072899,153.0385437 -27.5068703,153.0386047 -27.5041294,153.0391083 -27.50317,153.0392914 -27.5017509,153.0395508 -27.5009995,153.0397034 -27.5007401,153.0397186 -27.5005703,153.0397339 -27.500351,153.0397339 -27.5001106,153.0397339 -27.4993591,153.0396729 -27.4989605,153.039566 -27.4988594,153.0395508 -27.49823,153.0393066 -27.4977093,153.0390167 -27.4974995,153.0388794 -27.4974003,153.0388031 -27.4970894,153.0386047 -27.4968204,153.0384064 -27.4967098,153.0383148 -27.4961395,153.0379028 -27.4959297,153.037735 -27.4958897,153.0377045 -27.4957695,153.0376129 -27.4948807,153.0368958 -27.4944096,153.0365143 -27.4940605,153.0361481 -27.4939404,153.0359955 -27.4934292,153.0354004 -27.4932709,153.0351868 -27.4930305,153.0348358 -27.4929104,153.0346222 -27.4927597,153.0343933 -27.4926701,153.0342712 -27.4923592,153.033844 -27.4920998,153.0335999 -27.4918404,153.0334167 -27.4914608,153.0332336 -27.4911499,153.0330963 -27.4907398,153.0330048 -27.4899998,153.0329742 -27.48983,153.0329437 -27.4895992,153.0329132 -27.48946,153.0328827 -27.4889603,153.0328369 -27.4886894,153.0327454 -27.4882698,153.032608 -27.4881802,153.0325928 -27.4880905,153.0325623 -27.4880009,153.032547 -27.4879494,153.0325165 -27.4859409,153.0318909 -27.4850197,153.031601 -27.4841309,153.031311 -27.4839497,153.03125 -27.4838505,153.0312195 -27.4837608,153.031189 -27.4836502,153.0311432 -27.4832993,153.0309906 -27.4827995,153.0307312 -27.4824696,153.0305176 -27.4823093,153.0303955 -27.4822197,153.0303345 -27.4821301,153.0302429 -27.4794807,153.0281525 -27.4792404,153.0279846 -27.4785404,153.0274506 -27.4784508,153.0273743 -27.4780502,153.0270691 -27.4775295,153.0266724 -27.4773006,153.026474 -27.4769592,153.0261993 -27.4766197,153.0259247 -27.4762897,153.0256653 -27.4761295,153.0255432 -27.4759293,153.0253906 -27.4754696,153.0250244 -27.4750309,153.0246735 -27.4747601,153.0244446 -27.4745407,153.0242767 -27.4742794,153.0240784 -27.4738808,153.0237732 -27.4737606,153.0236969 -27.4730091,153.0231171 -27.4729099,153.0230408 -27.4728107,153.0229645 -27.47258,153.0227966 -27.4724197,153.0226593 -27.4721909,153.0224609 -27.4719391,153.0222473 -27.4718609,153.022171 -27.4718399,153.0221558 -27.4718094,153.0221252 -27.4717293,153.0220337 -27.4714603,153.0217743 -27.4713306,153.021637 -27.47122,153.0215912 -27.4705105,153.0209045 -27.4703693,153.0207672 -27.4703102,153.0206757 -27.4700508,153.0203094 -27.4700203,153.0202637 -27.46982,153.0201416 -27.46978,153.0201263 -27.4697304,153.0201263 -27.4696808,153.0201263 -27.4696007,153.0201569 -27.4695091,153.0202332 -27.4692593,153.0205231 -27.4690895,153.0207825 -27.4690208,153.0209045 -27.46875,153.0212402 -27.4686909,153.0213165 -27.4685402,153.0215149 -27.4682808,153.0218353 -27.4678001,153.0224457 -27.46772,153.0225525 -27.4676704,153.0226288 -27.4676208,153.0226898 -27.4674492,153.0229187 -27.4673805,153.0230103 -27.46735,153.023056 -27.4669609,153.0235596 -27.4666996,153.0239258 -27.4664497,153.0242615 -27.4662895,153.0244598 -27.4661503,153.0246735 -27.4660702,153.024765 -27.4658794,153.0247192 -27.4658508,153.024704 -27.4657001,153.024704 -27.4656696,153.024704 -27.4654598,153.0247345 -27.4650002,153.0249329 -27.4648304,153.0250244 -27.4649105,153.024765 -27.4649601,153.0246735 -27.4653893,153.0240021 -27.4654293,153.0239258 -27.4655704,153.0236359 -27.46562,153.0235291 -27.4656105,153.0233459 -27.4655991,153.0231628 -27.4652405,153.0231628 -27.4652004,153.0231476 -27.4651394,153.0230408 -27.4650898,153.0230103 -27.4650307,153.0230103 -27.4640903,153.0233917-27.4640903153.0201263-27.5757809153.0920258-130852017-27.5752144153.0879669-27.575153.088stopOver+130731232-27.4650097153.0230255-27.465153.023stopOver15895.0812.2-27.5752144153.0879669Head toward Logan Rd (95) on Padstow Rd (56). Go for 0.3 miles.24.2403.0-130852017forward-27.5757809153.0920258Turn left onto Logan Rd (95). Go for 0.3 miles.54.8546.0+130851941left-27.5711498153.0900116Take exit #14/M3/City onto M3, Pacific Mtwy. Go for 8.5 miles.556.513578.0+778753942lightLeft-27.4713306153.021637Take exit #2/Turbot Street to the right onto Turbot St. Go for 0.5 miles.65.5840.0+778426174lightRight-27.4660702153.024765Turn left onto Edward St. Go for 450 feet.27.9141.0+840906308left-27.4648304153.0250244Turn sharp left onto Wickham Ter. Go for 0.1 miles.42.8206.0-842383988hardLeft-27.4655991153.0231628Turn right onto Bartley St. Go for 0.1 miles.40.6181.0+130731232right-27.4650097153.0230255Arrive at Bartley St. The trip takes 10 miles and 14 mins.0.00.0forward-130852017-27.5752144,153.0879669 -27.5752602,153.088226326.016.670.016.671.6
AUQueenslandBrisbaneEight Mile PlainsPadstow Rd
-848019289-27.5752602,153.0882263 -27.5753899,153.089141891.016.670.016.675.5
AUQueenslandBrisbaneEight Mile PlainsPadstow Rd
-848019288-27.5753899,153.0891418 -27.5754299,153.08944730.016.670.016.671.8
AUQueenslandBrisbaneEight Mile PlainsPadstow Rd
-848019287-27.5754299,153.089447 -27.5755901,153.0905914114.016.670.016.676.8
AUQueenslandBrisbaneEight Mile PlainsPadstow Rd
-848019299-27.5755901,153.0905914 -27.5756607,153.091125553.016.670.016.673.2
AUQueenslandBrisbaneEight Mile PlainsPadstow Rd
-848019298-27.5756607,153.0911255 -27.5757198,153.09156844.016.670.016.672.6
AUQueenslandBrisbaneEight Mile PlainsPadstow Rd
-736514351-27.5757198,153.091568 -27.5757504,153.091812124.016.670.016.671.4
AUQueenslandBrisbaneEight Mile PlainsPadstow Rd
-736514350-27.5757504,153.0918121 -27.5757809,153.092025821.016.670.016.671.3
AUQueenslandBrisbaneEight Mile PlainsPadstow Rd
+130851941-27.5757809,153.0920258 -27.5752907,153.0918121 -27.5749302,153.0916748100.019.440.018.065.5
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+130851942-27.5749302,153.0916748 -27.5740795,153.0913239100.019.440.018.065.5
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+130851862-27.5740795,153.0913239 -27.5734901,153.09109569.019.440.018.063.8
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+130851861-27.5734901,153.091095 -27.5731201,153.090911944.019.440.018.062.4
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918831-27.5731201,153.0909119 -27.5728893,153.090805127.019.440.018.061.5
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918832-27.5728893,153.0908051 -27.5723991,153.0906067 -27.5722103,153.090499981.019.440.018.064.5
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918827-27.5722103,153.0904999 -27.5719509,153.090362531.019.440.018.061.7
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918833-27.5719509,153.0903625 -27.5717106,153.090255728.019.440.018.061.6
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918834-27.5717106,153.0902557 -27.5714703,153.090133729.019.440.018.061.6
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+130757981-27.5714703,153.0901337 -27.5711498,153.090011637.019.440.018.062.0
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+778753942-27.5711498,153.0900116 -27.5710392,153.0898895 -27.5704498,153.0897064 -27.5699806,153.0894012 -27.5698109,153.0892334 -27.5696507,153.0890503 -27.5693398,153.0885468256.027.780.018.0614.2
AUQueenslandBrisbaneEight Mile Plains
+778753943-27.5693398,153.0885468 -27.5685005,153.0870361 -27.5683002,153.0866852 -27.5681305,153.0865479240.027.780.026.399.1
AUQueenslandBrisbaneEight Mile Plains
+842194179-27.5681305,153.0865479 -27.5675297,153.0855865115.027.780.026.394.4
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+842194180-27.5675297,153.0855865 -27.5662403,153.0835724 -27.5645599,153.0809937 -27.5645103,153.0809174569.027.780.026.3921.6
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180257-27.5645103,153.0809174 -27.5644493,153.0808258 -27.5643902,153.08071923.027.780.026.390.9
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy, Riverside Expy
+778513858-27.5643902,153.080719 -27.5632801,153.0790863 -27.5629597,153.0786438 -27.5626793,153.0782623 -27.5623398,153.0778046366.027.780.026.3913.9
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+130848965-27.5623398,153.0778046 -27.5618191,153.077102790.027.780.026.393.4
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180252-27.5618191,153.0771027 -27.5615292,153.0767517 -27.56147,153.076675457.027.780.026.392.2
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180251-27.56147,153.0766754 -27.5613995,153.076583911.027.780.026.390.4
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180253-27.5613995,153.0765839 -27.5612907,153.0764771 -27.5612202,153.076400826.027.780.026.391.0
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180254-27.5612202,153.0764008 -27.5611191,153.0762939 -27.5605106,153.0756226 -27.5587692,153.0739288 -27.5560703,153.0716248 -27.5530605,153.06912231157.027.780.026.3943.8
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+782455208-27.5530605,153.0691223 -27.5518303,153.0680542172.027.780.026.396.5
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+782455209-27.5518303,153.0680542 -27.5516701,153.067916922.027.780.026.390.8
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+130752000-27.5516701,153.0679169 -27.5500202,153.0665436228.027.780.026.398.6
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+762719178-27.5500202,153.0665436 -27.5492992,153.065948599.027.780.026.393.8
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+762719179-27.5492992,153.0659485 -27.5465107,153.0635986387.027.780.026.3914.7
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+130852721-27.5465107,153.0635986 -27.5454407,153.0627136147.027.780.026.395.6
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+782455204-27.5454407,153.0627136 -27.5446301,153.062027112.027.780.026.394.2
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+851414677-27.5446301,153.062027 -27.5444107,153.0618439 -27.5436707,153.0612946 -27.5428104,153.0607452 -27.5418606,153.0602264 -27.5410309,153.0598297456.027.780.026.3917.3
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+851414678-27.5410309,153.0598297 -27.5407505,153.0596924 -27.5401402,153.0594635105.027.780.026.394.0
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+828675832-27.5401402,153.0594635 -27.5396996,153.0593262 -27.5380306,153.0588379242.027.780.026.399.2
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+828675833-27.5380306,153.0588379 -27.5377598,153.058761631.027.780.026.391.2
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+821207667-27.5377598,153.0587616 -27.5372505,153.0586548 -27.5360794,153.0584106190.027.780.026.397.2
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+821207668-27.5360794,153.0584106 -27.5345192,153.058075176.027.780.026.396.7
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+851414665-27.5345192,153.058075 -27.5335693,153.0578766107.027.780.026.394.1
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+851414666-27.5335693,153.0578766 -27.5287495,153.0568542 -27.5279198,153.0566559 -27.5272694,153.0564575 -27.52668,153.0562439 -27.5265102,153.0561676803.027.780.026.3930.4
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+782385629-27.5265102,153.0561676 -27.5260201,153.055954 -27.5256195,153.0557709106.027.780.026.394.0
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+130853483-27.5256195,153.0557709 -27.5253601,153.0556335 -27.5246906,153.0552826 -27.5240498,153.0548706 -27.5235901,153.0545044258.027.780.026.399.8
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+772093015-27.5235901,153.0545044 -27.5233498,153.054321332.027.780.026.391.2
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+772093016-27.5233498,153.0543213 -27.5231991,153.054214519.027.780.026.390.7
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+736390885-27.5231991,153.0542145 -27.5209904,153.052475299.027.780.026.3911.3
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+782385634-27.5209904,153.052475 -27.5201492,153.0517731116.027.780.026.394.4
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+782385635-27.5201492,153.0517731 -27.5198994,153.051574733.027.780.026.391.3
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+778520137-27.5198994,153.0515747 -27.5198002,153.051483214.027.780.026.390.5
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+791180780-27.5198002,153.0514832 -27.5197201,153.05143749.027.780.026.390.3
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+791180781-27.5197201,153.0514374 -27.5196705,153.0513916 -27.5188999,153.0507507 -27.51824,153.0500336 -27.5175304,153.0490723 -27.5173092,153.0487061 -27.5169201,153.0479431 -27.5146999,153.0434113979.027.780.026.3937.1
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+130853660-27.5146999,153.0434113 -27.5142193,153.0424347 -27.5138206,153.0417633 -27.5135002,153.0413666 -27.5131302,153.0409546 -27.5129299,153.0407715329.027.780.026.3912.5
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+833000842-27.5129299,153.0407715 -27.5126896,153.0405731 -27.5122299,153.0402832 -27.5098591,153.0390167 -27.5095406,153.0388641 -27.5092793,153.0387726452.027.780.026.3917.1
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+833000843-27.5092793,153.0387726 -27.5090008,153.038681 -27.5088291,153.0386353 -27.5083199,153.0385437109.027.780.026.394.1
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+130853471-27.5083199,153.0385437 -27.5077591,153.0385132 -27.5072899,153.0385437114.027.780.026.394.3
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+130853513-27.5072899,153.0385437 -27.5068703,153.0386047 -27.5041294,153.0391083355.027.780.026.3913.5
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+782459444-27.5041294,153.0391083 -27.50317,153.0392914108.027.780.026.394.1
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+782459445-27.50317,153.0392914 -27.5017509,153.0395508159.027.780.026.396.0
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+779045467-27.5017509,153.0395508 -27.5009995,153.0397034 -27.5007401,153.0397186113.027.780.026.394.3
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+779045468-27.5007401,153.0397186 -27.5005703,153.0397339 -27.500351,153.039733943.022.220.022.221.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+821196745-27.500351,153.0397339 -27.5001106,153.0397339 -27.4993591,153.0396729 -27.4989605,153.039566156.022.220.022.227.0
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+821196746-27.4989605,153.039566 -27.4988594,153.0395508 -27.49823,153.039306685.022.220.022.223.8
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+812250074-27.49823,153.0393066 -27.4977093,153.0390167 -27.4974995,153.038879491.022.220.022.224.1
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+826731481-27.4974995,153.0388794 -27.4974003,153.038803113.022.220.022.220.6
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+826731482-27.4974003,153.0388031 -27.4970894,153.038604739.022.220.022.221.8
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+130846576-27.4970894,153.0386047 -27.4968204,153.038406435.022.220.022.221.6
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+130738021-27.4968204,153.0384064 -27.4967098,153.038314815.022.220.022.220.7
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+778479274-27.4967098,153.0383148 -27.4961395,153.037902875.022.220.022.223.4
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+778479275-27.4961395,153.0379028 -27.4959297,153.03773528.022.220.022.221.3
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851379612-27.4959297,153.037735 -27.4958897,153.0377045 -27.4957695,153.037612921.022.220.022.220.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851460191-27.4957695,153.0376129 -27.4948807,153.0368958121.022.220.022.225.4
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851460192-27.4948807,153.0368958 -27.4944096,153.0365143 -27.4940605,153.0361481 -27.4939404,153.0359955137.022.220.022.226.2
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851414374-27.4939404,153.0359955 -27.4934292,153.0354004 -27.4932709,153.0351868109.022.220.022.224.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+812250623-27.4932709,153.0351868 -27.4930305,153.034835843.022.220.022.221.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+802502378-27.4930305,153.0348358 -27.4929104,153.034622224.022.220.022.221.1
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+811756237-27.4929104,153.0346222 -27.4927597,153.034393328.022.220.022.221.3
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+811756238-27.4927597,153.0343933 -27.4926701,153.034271215.022.220.022.220.7
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+840727547-27.4926701,153.0342712 -27.4923592,153.033844 -27.4920998,153.0335999 -27.4918404,153.0334167 -27.4914608,153.0332336 -27.4911499,153.0330963 -27.4907398,153.0330048255.022.220.022.2211.5
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+840727548-27.4907398,153.0330048 -27.4899998,153.032974282.022.220.022.223.7
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851414359-27.4899998,153.0329742 -27.48983,153.0329437 -27.4895992,153.0329132 -27.48946,153.032882760.022.220.022.222.7
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851414360-27.48946,153.0328827 -27.4889603,153.032836955.022.220.022.222.5
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+130846600-27.4889603,153.0328369 -27.4886894,153.032745431.022.220.022.221.4
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+791180777-27.4886894,153.0327454 -27.4882698,153.032608 -27.4881802,153.032592858.022.220.022.222.6
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+792771312-27.4881802,153.0325928 -27.4880905,153.0325623 -27.4880009,153.03254720.022.220.022.220.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+791180779-27.4880009,153.032547 -27.4879494,153.0325165 -27.4859409,153.0318909 -27.4850197,153.031601344.022.220.022.2215.5
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+778398386-27.4850197,153.031601 -27.4841309,153.031311102.022.220.022.224.6
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+792296089-27.4841309,153.031311 -27.4839497,153.0312521.022.220.022.220.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+792296090-27.4839497,153.03125 -27.4838505,153.031219511.022.220.022.220.5
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+792296087-27.4838505,153.0312195 -27.4837608,153.03118910.022.220.022.220.5
AUQueenslandBrisbaneKangaroo PointM3, Pacific Mtwy
+792296088-27.4837608,153.031189 -27.4836502,153.031143213.022.220.022.220.6
AUQueenslandBrisbaneKangaroo PointM3, Pacific Mtwy
+130846658-27.4836502,153.0311432 -27.4832993,153.030990641.022.220.022.221.8
AUQueenslandBrisbaneKangaroo PointM3, Pacific Mtwy
+130846657-27.4832993,153.0309906 -27.4827995,153.0307312 -27.4824696,153.0305176103.022.220.022.224.6
AUQueenslandBrisbaneKangaroo PointM3, Pacific Mtwy, Riverside Expy
+831959706-27.4824696,153.0305176 -27.4823093,153.0303955 -27.4822197,153.030334533.022.220.022.221.5
AUQueenslandBrisbaneKangaroo PointCaptain Cook Brg, M3, Pacific Mtwy, Riverside Expy
+831959707-27.4822197,153.0303345 -27.4821301,153.0302429 -27.4794807,153.0281525373.022.220.022.2216.8
AUQueenslandBrisbaneKangaroo PointCaptain Cook Brg, M3, Pacific Mtwy, Riverside Expy
+132965050-27.4794807,153.0281525 -27.4792404,153.027984631.022.220.022.221.4
AUQueenslandBrisbaneKangaroo PointCaptain Cook Brg, M3, Pacific Mtwy, Riverside Expy
+779153921-27.4792404,153.0279846 -27.4785404,153.0274506 -27.4784508,153.0273743106.022.220.022.224.8
AUQueenslandBrisbaneM3, Pacific Mtwy, Captain Cook Brg, Riverside Expy
+779153922-27.4784508,153.0273743 -27.4780502,153.027069153.022.220.022.222.4
AUQueenslandBrisbaneM3, Pacific Mtwy, Captain Cook Brg, Riverside Expy
+778599510-27.4780502,153.0270691 -27.4775295,153.026672469.022.220.022.223.1
AUQueenslandBrisbaneM3, Pacific Mtwy, Captain Cook Brg, Riverside Expy
+792648393-27.4775295,153.0266724 -27.4773006,153.02647432.019.440.018.061.8
AUQueenslandBrisbaneM3, Pacific Mtwy, Captain Cook Brg, Riverside Expy
+792648394-27.4773006,153.026474 -27.4769592,153.026199346.019.440.018.062.5
AUQueenslandBrisbaneM3, Pacific Mtwy, Captain Cook Brg, Riverside Expy
+792648392-27.4769592,153.0261993 -27.4766197,153.025924746.019.440.018.062.5
AUQueenslandBrisbaneM3, Pacific Mtwy, Captain Cook Brg, Riverside Expy
+130851656-27.4766197,153.0259247 -27.4762897,153.025665344.019.440.018.062.4
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+778829848-27.4762897,153.0256653 -27.4761295,153.025543221.019.440.018.061.2
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+779144197-27.4761295,153.0255432 -27.4759293,153.025390626.019.440.018.061.4
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+779144198-27.4759293,153.0253906 -27.4754696,153.025024462.019.440.018.063.4
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+821196747-27.4754696,153.0250244 -27.4750309,153.024673559.019.440.018.063.3
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+821196748-27.4750309,153.0246735 -27.4747601,153.024444637.019.440.018.062.0
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+779144211-27.4747601,153.0244446 -27.4745407,153.024276729.019.440.018.061.6
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+779144212-27.4745407,153.0242767 -27.4742794,153.024078435.019.440.018.061.9
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+130851752-27.4742794,153.0240784 -27.4738808,153.023773253.019.440.018.062.9
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+132965668-27.4738808,153.0237732 -27.4737606,153.023696915.019.440.018.060.8
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+778426177-27.4737606,153.0236969 -27.4730091,153.0231171101.019.440.018.065.6
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+778426178-27.4730091,153.0231171 -27.4729099,153.023040813.019.440.018.060.7
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+778426179-27.4729099,153.0230408 -27.4728107,153.022964513.019.440.018.060.7
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+841489920-27.4728107,153.0229645 -27.47258,153.0227966 -27.4724197,153.022659352.019.440.018.062.9
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+841489921-27.4724197,153.0226593 -27.4721909,153.022460932.019.440.018.061.8
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+841489915-27.4721909,153.0224609 -27.4719391,153.022247335.019.440.018.061.9
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+778398393-27.4719391,153.0222473 -27.4718609,153.02217111.019.440.018.060.6
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+782442370-27.4718609,153.022171 -27.4718399,153.02215582.019.440.018.060.1
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+782442371-27.4718399,153.0221558 -27.4718094,153.02212524.019.440.018.060.2
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+778398394-27.4718094,153.0221252 -27.4717293,153.022033712.019.440.018.060.7
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+841489916-27.4717293,153.0220337 -27.4714603,153.021774339.019.440.018.062.2
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+841489917-27.4714603,153.0217743 -27.4713306,153.02163719.019.440.018.061.1
AUQueenslandBrisbaneM3, Pacific Mtwy, Riverside Expy
+778426174-27.4713306,153.021637 -27.47122,153.0215912 -27.4705105,153.0209045117.016.670.016.677.0
AUQueenslandBrisbane
+778426175-27.4705105,153.0209045 -27.4703693,153.0207672 -27.4703102,153.020675731.016.670.016.671.9
AUQueenslandBrisbane
+840910687-27.4703102,153.0206757 -27.4700508,153.020309446.016.670.016.672.8
AUQueenslandBrisbane
+840910688-27.4700508,153.0203094 -27.4700203,153.0202637 -27.46982,153.0201416 -27.46978,153.0201263 -27.4697304,153.0201263 -27.4696808,153.020126346.016.670.016.672.8
AUQueenslandBrisbane
+779153927-27.4696808,153.0201263 -27.4696007,153.02015699.016.670.016.670.5
AUQueenslandBrisbane
+778594823-27.4696007,153.0201569 -27.4695091,153.0202332 -27.4692593,153.0205231 -27.4690895,153.0207825 -27.4690208,153.020904598.016.670.016.675.9
AUQueenslandBrisbane
+840910525-27.4690208,153.0209045 -27.46875,153.021240244.016.670.016.672.6
AUQueenslandBrisbaneTurbot St
+840910526-27.46875,153.0212402 -27.4686909,153.02131659.016.670.016.670.5
AUQueenslandBrisbaneTurbot St
+130731944-27.4686909,153.0213165 -27.4685402,153.021514925.016.670.016.671.5
AUQueenslandBrisbaneTurbot St
+840909575-27.4685402,153.0215149 -27.4682808,153.021835342.016.670.016.672.5
AUQueenslandBrisbaneTurbot St
+840909576-27.4682808,153.0218353 -27.4678001,153.022445780.016.670.016.674.8
AUQueenslandBrisbaneTurbot St
+130851044-27.4678001,153.0224457 -27.46772,153.022552513.016.670.016.670.8
AUQueenslandBrisbaneTurbot St
+840909577-27.46772,153.0225525 -27.4676704,153.02262889.016.670.016.670.5
AUQueenslandBrisbaneTurbot St
+840910689-27.4676704,153.0226288 -27.4676208,153.02268988.016.670.016.670.5
AUQueenslandBrisbaneTurbot St
+840910690-27.4676208,153.0226898 -27.4674492,153.022918729.016.670.016.671.7
AUQueenslandBrisbaneTurbot St
+744461076-27.4674492,153.0229187 -27.4673805,153.023010311.016.670.016.670.7
AUQueenslandBrisbaneTurbot St
+779115654-27.4673805,153.0230103 -27.46735,153.0230565.016.670.016.670.3
AUQueenslandBrisbaneTurbot St
+840906306-27.46735,153.023056 -27.4669609,153.023559665.016.670.016.673.9
AUQueenslandBrisbaneTurbot St
+840906305-27.4669609,153.0235596 -27.4666996,153.023925846.016.670.016.672.8
AUQueenslandBrisbaneTurbot St
+779143470-27.4666996,153.0239258 -27.4664497,153.024261543.016.670.016.672.6
AUQueenslandBrisbaneTurbot St
+779143471-27.4664497,153.0242615 -27.4662895,153.024459826.016.670.016.671.6
AUQueenslandBrisbaneTurbot St
+779114892-27.4662895,153.0244598 -27.4661503,153.024673526.016.670.016.671.6
AUQueenslandBrisbaneTurbot St
+779114893-27.4661503,153.0246735 -27.4660702,153.02476512.016.670.016.670.7
AUQueenslandBrisbaneTurbot St
+840906308-27.4660702,153.024765 -27.4658794,153.024719221.013.890.09.722.2
AUQueenslandBrisbaneEdward St
+840906309-27.4658794,153.0247192 -27.4658508,153.024704 -27.4657001,153.024704 -27.4656696,153.02470423.013.890.09.722.4
AUQueenslandBrisbaneEdward St
+840906307-27.4656696,153.024704 -27.4654598,153.024734523.013.890.09.722.4
AUQueenslandBrisbaneEdward St
+840906312-27.4654598,153.0247345 -27.4650002,153.024932954.013.890.09.725.6
AUQueenslandBrisbaneSpring HillEdward St
+840906313-27.4650002,153.0249329 -27.4648304,153.025024420.013.890.09.722.1
AUQueenslandBrisbaneSpring HillEdward St
-842383988-27.4648304,153.0250244 -27.4649105,153.024765 -27.4649601,153.024673537.013.890.09.723.8
AUQueenslandBrisbaneSpring HillWickham Ter
-842383987-27.4649601,153.0246735 -27.4653893,153.024002181.013.890.09.728.3
AUQueenslandBrisbaneSpring HillWickham Ter
-779110719-27.4653893,153.0240021 -27.4654293,153.02392588.013.890.09.720.8
AUQueenslandBrisbaneSpring HillWickham Ter
-779110718-27.4654293,153.0239258 -27.4655704,153.0236359 -27.46562,153.023529144.013.890.09.724.5
AUQueenslandBrisbaneSpring HillWickham Ter
+779110714-27.46562,153.0235291 -27.4656105,153.0233459 -27.4655991,153.023162836.013.890.09.723.7
AUQueenslandBrisbaneSpring HillWickham Ter
+130731232-27.4655991,153.0231628 -27.4652405,153.0231628 -27.4652004,153.0231476 -27.4651394,153.0230408 -27.4650898,153.0230103 -27.4650307,153.0230103 -27.4640903,153.0233917181.013.890.09.7218.6
AUQueenslandBrisbaneSpring HillBartley St
15895.0816.0812.0motorway
\ No newline at end of file diff --git a/tests/auto/qgeoroutexmlparser/route2.xml b/tests/auto/qgeoroutexmlparser/route2.xml new file mode 100644 index 0000000..60cd1de --- /dev/null +++ b/tests/auto/qgeoroutexmlparser/route2.xml @@ -0,0 +1 @@ +2012-02-21T04:31:31.963+01:002012-02-21T04:29:00.020+010046413282012-02-21T04:29:02.066+0100146312012-02-21T04:29:02.066+010049962011Q2_DICIrouteserver,9.1-2011.12.20-hotfix6.2.11.148routing-route-service,6.2.11.2REMuh0MAAAAVHcnlP5Q7wEJg5dAiI2NAAAAA4ECUO8AAAADAIiNjQAAAAAAAAPB_AAAAAAAA8H8lPMsHR9jw9ErZ7QDDMJkqGIWMAQEAAABT2e0AAwAAABiFjAEBAAAAAADA_wEAAAAAAMD_4djU4GNxAstrNZeB_hDlxQbgt2cxF1g+130759717-27.5791149153.0979919-27.5791153.098stopOver-130730440-27.4622307153.0397949-27.4622153.0398stopOverfastestNowcarenabled-27.5791149,153.0979919 -27.5790405,153.0978851 -27.5786304,153.0973816 -27.57798,153.0966034 -27.5778008,153.0964661 -27.5776005,153.0963745 -27.5773792,153.096344 -27.5764599,153.0965271 -27.5764999,153.0963898 -27.5763397,153.0951233 -27.5762405,153.0945129 -27.5761204,153.0936279 -27.5759907,153.0927582 -27.5759201,153.0922546 -27.5758991,153.0921021 -27.5757809,153.0920258 -27.5752907,153.0918121 -27.5749302,153.0916748 -27.5740795,153.0913239 -27.5734901,153.091095 -27.5731201,153.0909119 -27.5728893,153.0908051 -27.5723991,153.0906067 -27.5722103,153.0904999 -27.5719509,153.0903625 -27.5717106,153.0902557 -27.5714703,153.0901337 -27.5711498,153.0900116 -27.5710392,153.0898895 -27.5704498,153.0897064 -27.5699806,153.0894012 -27.5698109,153.0892334 -27.5696507,153.0890503 -27.5693398,153.0885468 -27.5685005,153.0870361 -27.5683002,153.0866852 -27.5681305,153.0865479 -27.5675297,153.0855865 -27.5662403,153.0835724 -27.5645599,153.0809937 -27.5645103,153.0809174 -27.5644493,153.0808258 -27.5643902,153.080719 -27.5632801,153.0790863 -27.5629597,153.0786438 -27.5626793,153.0782623 -27.5623398,153.0778046 -27.5618191,153.0771027 -27.5615292,153.0767517 -27.56147,153.0766754 -27.5613995,153.0765839 -27.5612907,153.0764771 -27.5612202,153.0764008 -27.5611191,153.0762939 -27.5605106,153.0756226 -27.5587692,153.0739288 -27.5560703,153.0716248 -27.5530605,153.0691223 -27.5518303,153.0680542 -27.5516701,153.0679169 -27.5500202,153.0665436 -27.5492992,153.0659485 -27.5465107,153.0635986 -27.5454407,153.0627136 -27.5446301,153.062027 -27.5444107,153.0618439 -27.5436707,153.0612946 -27.5428104,153.0607452 -27.5418606,153.0602264 -27.5410309,153.0598297 -27.5407505,153.0596924 -27.5401402,153.0594635 -27.5396996,153.0593262 -27.5380306,153.0588379 -27.5377598,153.0587616 -27.5372505,153.0586548 -27.5360794,153.0584106 -27.5345192,153.058075 -27.5335693,153.0578766 -27.5287495,153.0568542 -27.5279198,153.0566559 -27.5272694,153.0564575 -27.52668,153.0562439 -27.5265102,153.0561676 -27.5260201,153.055954 -27.5256195,153.0557709 -27.5253601,153.0556335 -27.5246906,153.0552826 -27.5240498,153.0548706 -27.5235901,153.0545044 -27.5233498,153.0543213 -27.5231991,153.0542145 -27.5209904,153.052475 -27.5201492,153.0517731 -27.5198994,153.0515747 -27.5198002,153.0514832 -27.5197201,153.0514374 -27.5196705,153.0513916 -27.5188999,153.0507507 -27.51824,153.0500336 -27.5175304,153.0490723 -27.5173092,153.0487061 -27.5169201,153.0479431 -27.5146999,153.0434113 -27.5142193,153.0424347 -27.5138206,153.0417633 -27.5135002,153.0413666 -27.5131302,153.0409546 -27.5129299,153.0407715 -27.5126896,153.0405731 -27.5122299,153.0402832 -27.5098591,153.0390167 -27.5095406,153.0388641 -27.5092793,153.0387726 -27.5090008,153.038681 -27.5088291,153.0386353 -27.5083199,153.0385437 -27.5077591,153.0385132 -27.5072899,153.0385437 -27.5068703,153.0386047 -27.5041294,153.0391083 -27.50317,153.0392914 -27.5017509,153.0395508 -27.5009995,153.0397034 -27.5007401,153.0397186 -27.5005703,153.0397339 -27.500351,153.0397339 -27.5001106,153.0397339 -27.4993591,153.0396729 -27.4989605,153.039566 -27.4988594,153.0395508 -27.49823,153.0393066 -27.4977093,153.0390167 -27.4974995,153.0388794 -27.4974003,153.0388031 -27.4970894,153.0386047 -27.4968204,153.0384064 -27.4967098,153.0383148 -27.4961395,153.0379028 -27.4959297,153.037735 -27.4958897,153.0377045 -27.4957695,153.0376129 -27.4948807,153.0368958 -27.4944096,153.0365143 -27.4940605,153.0361481 -27.4939404,153.0359955 -27.4934292,153.0354004 -27.4932709,153.0351868 -27.4930305,153.0348358 -27.4929104,153.0346222 -27.4927597,153.0343933 -27.4926701,153.0342712 -27.4923592,153.033844 -27.4920998,153.0335999 -27.4918404,153.0334167 -27.4914608,153.0332336 -27.4911499,153.0330963 -27.4907398,153.0330048 -27.4899998,153.0329742 -27.48983,153.0329437 -27.4895992,153.0329132 -27.48946,153.0328827 -27.4889603,153.0328369 -27.48876,153.0327148 -27.4883404,153.0325317 -27.4881706,153.0324554 -27.4880695,153.0324249 -27.4879494,153.0323639 -27.4862995,153.0316925 -27.4859505,153.0314331 -27.4858799,153.0313721 -27.4858608,153.0312653 -27.4857903,153.0307465 -27.4857407,153.0303955 -27.4856205,153.0303345 -27.4855099,153.030304 -27.4854107,153.0303192 -27.4853191,153.0303192 -27.4852009,153.0303345 -27.4847908,153.0304108 -27.4846802,153.030426 -27.4845104,153.0305481 -27.4840393,153.0306396 -27.4839497,153.0306854 -27.48386,153.030777 -27.4838104,153.0309143 -27.4838409,153.0311584 -27.4838505,153.0312195 -27.4838696,153.0313873 -27.4839096,153.0316467 -27.4839706,153.032074 -27.4839993,153.0322571 -27.4840908,153.0328674 -27.4842205,153.033844 -27.4843693,153.0347748 -27.4844799,153.0354462 -27.4845104,153.0355835 -27.4845505,153.0358429 -27.4842796,153.0358429 -27.4836693,153.0358734 -27.4832802,153.0358429 -27.4829197,153.0358429 -27.48283,153.0358429 -27.4825592,153.0358429 -27.4824104,153.0358429 -27.4821491,153.0358276 -27.4819107,153.0358124 -27.4816303,153.0358124 -27.4814301,153.0358124 -27.4812508,153.0358124 -27.4805794,153.0357819 -27.4801197,153.0357666 -27.4793091,153.0357513 -27.4792404,153.0357513 -27.47855,153.0357361 -27.4782295,153.0357361 -27.4780293,153.0357513 -27.4774399,153.0357208 -27.4769306,153.0357056 -27.4765701,153.0357056 -27.4764309,153.0357056 -27.4762497,153.0356903 -27.4758797,153.0356445 -27.4758091,153.0356445 -27.4757595,153.0356445 -27.4756107,153.0355835 -27.4752903,153.0355835 -27.4749699,153.035553 -27.4743099,153.035553 -27.4732399,153.0355377 -27.4727306,153.0355225 -27.4721909,153.0355225 -27.4716606,153.0355072 -27.4712791,153.0355072 -27.4712505,153.0355072 -27.4712105,153.0355225 -27.4710503,153.0355835 -27.4709301,153.0356293 -27.4706802,153.035675 -27.4706097,153.035675 -27.4704609,153.0357056 -27.4702797,153.0357971 -27.4698505,153.0358429 -27.4694595,153.0358734 -27.4692192,153.0358734 -27.4685898,153.0358887 -27.4680004,153.0359039 -27.4671707,153.0358582 -27.4659309,153.0358124 -27.4658508,153.0358124 -27.4657001,153.0358124 -27.4648304,153.0357819 -27.4647808,153.0357819 -27.4627304,153.0357056 -27.4624996,153.0357056 -27.4624195,153.0357056 -27.4622898,153.0357056 -27.4619904,153.0357056 -27.4617596,153.0356598 -27.4615402,153.0356445 -27.4613094,153.035614 -27.4611397,153.035553 -27.4609203,153.0354004 -27.4607296,153.0351868 -27.4606895,153.0351563 -27.4605103,153.0349731 -27.4603901,153.0348511 -27.4602909,153.0347595 -27.4601593,153.034729 -27.4600105,153.0347443 -27.4598408,153.0348969 -27.4597702,153.0349731 -27.4596596,153.03508 -27.4593391,153.0354309 -27.4590492,153.0357361 -27.4593506,153.0361176 -27.4595604,153.036377 -27.4598408,153.0367432 -27.45998,153.0369263 -27.4601803,153.0371857 -27.4603996,153.0374603 -27.4608307,153.0379944 -27.4615307,153.0388947 -27.4622307,153.0397949-27.4590492153.030304-27.5791149153.0979919+130759717-27.5791149153.0979919-27.5791153.098stopOver-130730440-27.4622307153.0397949-27.4622153.0398stopOver17283.0998.2-27.5791149153.0979919Head toward Electronics St on McKechnie Dr. Go for 0.2 miles.47.3361.0+130759717forward-27.5764599153.0965271Turn left onto Miles Platting Rd (56). Go for 0.2 miles.34.2375.0+767490982left-27.5759907153.0927582Turn right onto Logan Rd (95). Go for 0.4 miles.54.6626.0+130759055right-27.5711498153.0900116Take exit #14/M3/City onto M3, Pacific Mtwy. Go for 7 miles.446.011321.0+778753942lightLeft-27.4889603153.0328369Take exit #2/41/Stanley Street/South Bank onto Stanley St (41). Go for 0.3 miles.30.6468.0+791185396lightLeft-27.4857407153.0303955Turn right onto Allen St toward Vulture Street. Go for 400 feet.22.5118.0+130735264right-27.4846802153.030426Bear right to stay on Allen St. Go for 350 feet.11.5114.0+130735018lightRight-27.4838104153.0309143Bear right onto Vulture St (41). Go for 0.3 miles.38.7489.0-130856418lightRight-27.4845505153.0358429Turn left onto Main St (15). Go for 0.6 miles.99.0966.0+828228207left-27.4757595153.0356445Continue on Main St (15) at exit #2. Go for 1 mile.94.31572.0+811754670forward-27.4615402153.0356445Take right ramp onto McLachlan St toward 25/Eagle Farm/Brisbane Airport. Go for 0.2 miles.23.5343.0+828880864lightRight-27.4590492153.0357361Turn right onto Brunswick St. Go for 0.3 miles.95.9530.0-130729663right-27.4622307153.0397949Your destination on Brunswick St is on the left. The trip takes 11 miles and 17 mins.0.00.0forward+130759717-27.5791149,153.0979919 -27.5790405,153.0978851 -27.5786304,153.097381680.013.890.09.728.2
AUQueenslandBrisbaneEight Mile PlainsMcKechnie Dr
+130851874-27.5786304,153.0973816 -27.57798,153.0966034 -27.5778008,153.0964661 -27.5776005,153.0963745 -27.5773792,153.096344178.013.890.09.7218.3
AUQueenslandBrisbaneEight Mile PlainsMcKechnie Dr
+130851875-27.5773792,153.096344 -27.5764599,153.0965271103.013.890.09.7210.6
AUQueenslandBrisbaneEight Mile PlainsMcKechnie Dr
+767490982-27.5764599,153.0965271 -27.5764999,153.0963898 -27.5763397,153.0951233140.016.670.016.678.4
AUQueenslandBrisbaneEight Mile PlainsMiles Platting Rd
+767490983-27.5763397,153.0951233 -27.5762405,153.094512961.016.670.016.673.7
AUQueenslandBrisbaneEight Mile PlainsMiles Platting Rd
+130759112-27.5762405,153.0945129 -27.5761204,153.093627988.016.670.016.675.3
AUQueenslandBrisbaneEight Mile PlainsMiles Platting Rd
+130759082-27.5761204,153.0936279 -27.5759907,153.092758286.016.670.016.675.2
AUQueenslandBrisbaneEight Mile PlainsMiles Platting Rd
+130759055-27.5759907,153.0927582 -27.5759201,153.092254650.016.670.016.673.0
AUQueenslandBrisbaneEight Mile PlainsMiles Platting Rd
+130759043-27.5759201,153.0922546 -27.5758991,153.092102115.016.670.016.670.9
AUQueenslandBrisbaneEight Mile Plains
+130759031-27.5758991,153.0921021 -27.5757809,153.092025815.019.440.018.060.8
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+130851941-27.5757809,153.0920258 -27.5752907,153.0918121 -27.5749302,153.0916748100.019.440.018.065.5
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+130851942-27.5749302,153.0916748 -27.5740795,153.0913239100.019.440.018.065.5
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+130851862-27.5740795,153.0913239 -27.5734901,153.09109569.019.440.018.063.8
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+130851861-27.5734901,153.091095 -27.5731201,153.090911944.019.440.018.062.4
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918831-27.5731201,153.0909119 -27.5728893,153.090805127.019.440.018.061.5
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918832-27.5728893,153.0908051 -27.5723991,153.0906067 -27.5722103,153.090499981.019.440.018.064.5
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918827-27.5722103,153.0904999 -27.5719509,153.090362531.019.440.018.061.7
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918833-27.5719509,153.0903625 -27.5717106,153.090255728.019.440.018.061.6
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+846918834-27.5717106,153.0902557 -27.5714703,153.090133729.019.440.018.061.6
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+130757981-27.5714703,153.0901337 -27.5711498,153.090011637.019.440.018.062.0
AUQueenslandBrisbaneEight Mile PlainsLogan Rd
+778753942-27.5711498,153.0900116 -27.5710392,153.0898895 -27.5704498,153.0897064 -27.5699806,153.0894012 -27.5698109,153.0892334 -27.5696507,153.0890503 -27.5693398,153.0885468256.027.780.018.0614.2
AUQueenslandBrisbaneEight Mile Plains
+778753943-27.5693398,153.0885468 -27.5685005,153.0870361 -27.5683002,153.0866852 -27.5681305,153.0865479240.027.780.026.399.1
AUQueenslandBrisbaneEight Mile Plains
+842194179-27.5681305,153.0865479 -27.5675297,153.0855865115.027.780.026.394.4
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+842194180-27.5675297,153.0855865 -27.5662403,153.0835724 -27.5645599,153.0809937 -27.5645103,153.0809174569.027.780.026.3921.6
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180257-27.5645103,153.0809174 -27.5644493,153.0808258 -27.5643902,153.08071923.027.780.026.390.9
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy, Riverside Expy
+778513858-27.5643902,153.080719 -27.5632801,153.0790863 -27.5629597,153.0786438 -27.5626793,153.0782623 -27.5623398,153.0778046366.027.780.026.3913.9
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+130848965-27.5623398,153.0778046 -27.5618191,153.077102790.027.780.026.393.4
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180252-27.5618191,153.0771027 -27.5615292,153.0767517 -27.56147,153.076675457.027.780.026.392.2
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180251-27.56147,153.0766754 -27.5613995,153.076583911.027.780.026.390.4
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180253-27.5613995,153.0765839 -27.5612907,153.0764771 -27.5612202,153.076400826.027.780.026.391.0
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+791180254-27.5612202,153.0764008 -27.5611191,153.0762939 -27.5605106,153.0756226 -27.5587692,153.0739288 -27.5560703,153.0716248 -27.5530605,153.06912231157.027.780.026.3943.8
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+782455208-27.5530605,153.0691223 -27.5518303,153.0680542172.027.780.026.396.5
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+782455209-27.5518303,153.0680542 -27.5516701,153.067916922.027.780.026.390.8
AUQueenslandBrisbaneMacgregorM3, Pacific Mtwy
+130752000-27.5516701,153.0679169 -27.5500202,153.0665436228.027.780.026.398.6
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+762719178-27.5500202,153.0665436 -27.5492992,153.065948599.027.780.026.393.8
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+762719179-27.5492992,153.0659485 -27.5465107,153.0635986387.027.780.026.3914.7
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+130852721-27.5465107,153.0635986 -27.5454407,153.0627136147.027.780.026.395.6
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+782455204-27.5454407,153.0627136 -27.5446301,153.062027112.027.780.026.394.2
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+851414677-27.5446301,153.062027 -27.5444107,153.0618439 -27.5436707,153.0612946 -27.5428104,153.0607452 -27.5418606,153.0602264 -27.5410309,153.0598297456.027.780.026.3917.3
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+851414678-27.5410309,153.0598297 -27.5407505,153.0596924 -27.5401402,153.0594635105.027.780.026.394.0
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+828675832-27.5401402,153.0594635 -27.5396996,153.0593262 -27.5380306,153.0588379242.027.780.026.399.2
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+828675833-27.5380306,153.0588379 -27.5377598,153.058761631.027.780.026.391.2
AUQueenslandBrisbaneNathanM3, Pacific Mtwy
+821207667-27.5377598,153.0587616 -27.5372505,153.0586548 -27.5360794,153.0584106190.027.780.026.397.2
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+821207668-27.5360794,153.0584106 -27.5345192,153.058075176.027.780.026.396.7
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+851414665-27.5345192,153.058075 -27.5335693,153.0578766107.027.780.026.394.1
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+851414666-27.5335693,153.0578766 -27.5287495,153.0568542 -27.5279198,153.0566559 -27.5272694,153.0564575 -27.52668,153.0562439 -27.5265102,153.0561676803.027.780.026.3930.4
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+782385629-27.5265102,153.0561676 -27.5260201,153.055954 -27.5256195,153.0557709106.027.780.026.394.0
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+130853483-27.5256195,153.0557709 -27.5253601,153.0556335 -27.5246906,153.0552826 -27.5240498,153.0548706 -27.5235901,153.0545044258.027.780.026.399.8
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+772093015-27.5235901,153.0545044 -27.5233498,153.054321332.027.780.026.391.2
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+772093016-27.5233498,153.0543213 -27.5231991,153.054214519.027.780.026.390.7
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+736390885-27.5231991,153.0542145 -27.5209904,153.052475299.027.780.026.3911.3
AUQueenslandBrisbaneTarragindiM3, Pacific Mtwy
+782385634-27.5209904,153.052475 -27.5201492,153.0517731116.027.780.026.394.4
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+782385635-27.5201492,153.0517731 -27.5198994,153.051574733.027.780.026.391.3
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+778520137-27.5198994,153.0515747 -27.5198002,153.051483214.027.780.026.390.5
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+791180780-27.5198002,153.0514832 -27.5197201,153.05143749.027.780.026.390.3
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+791180781-27.5197201,153.0514374 -27.5196705,153.0513916 -27.5188999,153.0507507 -27.51824,153.0500336 -27.5175304,153.0490723 -27.5173092,153.0487061 -27.5169201,153.0479431 -27.5146999,153.0434113979.027.780.026.3937.1
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+130853660-27.5146999,153.0434113 -27.5142193,153.0424347 -27.5138206,153.0417633 -27.5135002,153.0413666 -27.5131302,153.0409546 -27.5129299,153.0407715329.027.780.026.3912.5
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+833000842-27.5129299,153.0407715 -27.5126896,153.0405731 -27.5122299,153.0402832 -27.5098591,153.0390167 -27.5095406,153.0388641 -27.5092793,153.0387726452.027.780.026.3917.1
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+833000843-27.5092793,153.0387726 -27.5090008,153.038681 -27.5088291,153.0386353 -27.5083199,153.0385437109.027.780.026.394.1
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+130853471-27.5083199,153.0385437 -27.5077591,153.0385132 -27.5072899,153.0385437114.027.780.026.394.3
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+130853513-27.5072899,153.0385437 -27.5068703,153.0386047 -27.5041294,153.0391083355.027.780.026.3913.5
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+782459444-27.5041294,153.0391083 -27.50317,153.0392914108.027.780.026.394.1
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+782459445-27.50317,153.0392914 -27.5017509,153.0395508159.027.780.026.396.0
AUQueenslandBrisbaneGreenslopesM3, Pacific Mtwy
+779045467-27.5017509,153.0395508 -27.5009995,153.0397034 -27.5007401,153.0397186113.027.780.026.394.3
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+779045468-27.5007401,153.0397186 -27.5005703,153.0397339 -27.500351,153.039733943.022.220.022.221.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+821196745-27.500351,153.0397339 -27.5001106,153.0397339 -27.4993591,153.0396729 -27.4989605,153.039566156.022.220.022.227.0
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+821196746-27.4989605,153.039566 -27.4988594,153.0395508 -27.49823,153.039306685.022.220.022.223.8
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+812250074-27.49823,153.0393066 -27.4977093,153.0390167 -27.4974995,153.038879491.022.220.022.224.1
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+826731481-27.4974995,153.0388794 -27.4974003,153.038803113.022.220.022.220.6
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+826731482-27.4974003,153.0388031 -27.4970894,153.038604739.022.220.022.221.8
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+130846576-27.4970894,153.0386047 -27.4968204,153.038406435.022.220.022.221.6
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+130738021-27.4968204,153.0384064 -27.4967098,153.038314815.022.220.022.220.7
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+778479274-27.4967098,153.0383148 -27.4961395,153.037902875.022.220.022.223.4
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+778479275-27.4961395,153.0379028 -27.4959297,153.03773528.022.220.022.221.3
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851379612-27.4959297,153.037735 -27.4958897,153.0377045 -27.4957695,153.037612921.022.220.022.220.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851460191-27.4957695,153.0376129 -27.4948807,153.0368958121.022.220.022.225.4
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851460192-27.4948807,153.0368958 -27.4944096,153.0365143 -27.4940605,153.0361481 -27.4939404,153.0359955137.022.220.022.226.2
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851414374-27.4939404,153.0359955 -27.4934292,153.0354004 -27.4932709,153.0351868109.022.220.022.224.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+812250623-27.4932709,153.0351868 -27.4930305,153.034835843.022.220.022.221.9
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+802502378-27.4930305,153.0348358 -27.4929104,153.034622224.022.220.022.221.1
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+811756237-27.4929104,153.0346222 -27.4927597,153.034393328.022.220.022.221.3
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+811756238-27.4927597,153.0343933 -27.4926701,153.034271215.022.220.022.220.7
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+840727547-27.4926701,153.0342712 -27.4923592,153.033844 -27.4920998,153.0335999 -27.4918404,153.0334167 -27.4914608,153.0332336 -27.4911499,153.0330963 -27.4907398,153.0330048255.022.220.022.2211.5
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+840727548-27.4907398,153.0330048 -27.4899998,153.032974282.022.220.022.223.7
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851414359-27.4899998,153.0329742 -27.48983,153.0329437 -27.4895992,153.0329132 -27.48946,153.032882760.022.220.022.222.7
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+851414360-27.48946,153.0328827 -27.4889603,153.032836955.022.220.022.222.5
AUQueenslandBrisbaneWoolloongabbaM3, Pacific Mtwy
+791185396-27.4889603,153.0328369 -27.48876,153.0327148 -27.4883404,153.0325317 -27.4881706,153.032455495.016.670.016.675.7
AUQueenslandBrisbaneWoolloongabba
+792771311-27.4881706,153.0324554 -27.4880695,153.0324249 -27.4879494,153.032363926.016.670.016.671.6
AUQueenslandBrisbaneWoolloongabba
+778513855-27.4879494,153.0323639 -27.4862995,153.0316925 -27.4859505,153.0314331 -27.4858799,153.0313721251.016.670.016.6715.1
AUQueenslandBrisbaneWoolloongabba
+130735305-27.4858799,153.0313721 -27.4858608,153.031265310.016.670.016.670.6
AUQueenslandBrisbaneWoolloongabbaStanley St
+130735302-27.4858608,153.0312653 -27.4857903,153.030746551.016.670.016.673.1
AUQueenslandBrisbaneWoolloongabbaStanley St
+130735282-27.4857903,153.0307465 -27.4857407,153.030395535.016.670.016.672.1
AUQueenslandBrisbaneWoolloongabbaStanley St
+130735264-27.4857407,153.0303955 -27.4856205,153.030334514.016.670.016.670.8
AUQueenslandBrisbaneWoolloongabbaAllen St
+841394290-27.4856205,153.0303345 -27.4855099,153.030304 -27.4854107,153.030319223.016.670.016.671.4
AUQueenslandBrisbaneWoolloongabbaAllen St
+841394291-27.4854107,153.0303192 -27.4853191,153.030319210.016.670.016.670.6
AUQueenslandBrisbaneWoolloongabbaAllen St
+841394292-27.4853191,153.0303192 -27.4852009,153.030334513.016.670.016.670.8
AUQueenslandBrisbaneWoolloongabbaAllen St
+130735130-27.4852009,153.0303345 -27.4847908,153.030410846.016.670.016.672.8
AUQueenslandBrisbaneWoolloongabbaAllen St
+130735029-27.4847908,153.0304108 -27.4846802,153.03042612.016.670.016.670.7
AUQueenslandBrisbaneWoolloongabbaAllen St
+130735018-27.4846802,153.030426 -27.4845104,153.0305481 -27.4840393,153.0306396 -27.4839497,153.0306854 -27.48386,153.030777 -27.4838104,153.0309143114.016.670.016.676.8
AUQueenslandBrisbaneWoolloongabbaAllen St
-130856418-27.4838104,153.0309143 -27.4838409,153.0311584 -27.4838505,153.0312195 -27.4838696,153.0313873 -27.4839096,153.031646773.016.670.016.674.4
AUQueenslandBrisbaneKangaroo PointVulture St
-842230577-27.4839096,153.0316467 -27.4839706,153.03207442.016.670.016.672.5
AUQueenslandBrisbaneKangaroo PointVulture St
-842230583-27.4839706,153.032074 -27.4839993,153.032257118.016.670.016.671.1
AUQueenslandBrisbaneKangaroo PointVulture St
-842230582-27.4839993,153.0322571 -27.4840908,153.032867461.016.670.016.673.7
AUQueenslandBrisbaneKangaroo PointVulture St
-130734905-27.4840908,153.0328674 -27.4842205,153.03384497.016.670.016.675.8
AUQueenslandBrisbaneKangaroo PointVulture St
-130734936-27.4842205,153.033844 -27.4843693,153.034774893.016.670.016.675.6
AUQueenslandBrisbaneKangaroo PointVulture St
-811701153-27.4843693,153.0347748 -27.4844799,153.035446267.016.670.016.674.0
AUQueenslandBrisbaneWoolloongabbaVulture St
-811701152-27.4844799,153.0354462 -27.4845104,153.035583513.016.670.016.670.8
AUQueenslandBrisbaneWoolloongabbaVulture St
-782798239-27.4845104,153.0355835 -27.4845505,153.035842925.016.670.016.671.5
AUQueenslandBrisbaneWoolloongabbaVulture St
+828228207-27.4845505,153.0358429 -27.4842796,153.035842930.016.670.016.671.8
AUQueenslandBrisbaneKangaroo PointMain St
+828228208-27.4842796,153.0358429 -27.4836693,153.035873467.016.670.016.674.0
AUQueenslandBrisbaneKangaroo PointMain St
+130734780-27.4836693,153.0358734 -27.4832802,153.035842943.016.670.016.672.6
AUQueenslandBrisbaneKangaroo PointMain St
+130734695-27.4832802,153.0358429 -27.4829197,153.035842940.016.670.016.672.4
AUQueenslandBrisbaneKangaroo PointMain St
+130734588-27.4829197,153.0358429 -27.48283,153.03584299.016.670.016.670.5
AUQueenslandBrisbaneKangaroo PointMain St
+130734560-27.48283,153.0358429 -27.4825592,153.035842930.016.670.016.671.8
AUQueenslandBrisbaneKangaroo PointMain St
+130734480-27.4825592,153.0358429 -27.4824104,153.035842916.016.670.016.671.0
AUQueenslandBrisbaneKangaroo PointMain St
+130734442-27.4824104,153.0358429 -27.4821491,153.035827629.016.670.016.671.7
AUQueenslandBrisbaneKangaroo PointMain St
+130734384-27.4821491,153.0358276 -27.4819107,153.035812426.016.670.016.671.6
AUQueenslandBrisbaneKangaroo PointMain St
+782798224-27.4819107,153.0358124 -27.4816303,153.035812431.016.670.016.671.9
AUQueenslandBrisbaneKangaroo PointMain St
+782798225-27.4816303,153.0358124 -27.4814301,153.035812422.016.670.016.671.3
AUQueenslandBrisbaneKangaroo PointMain St
+130734269-27.4814301,153.0358124 -27.4812508,153.035812419.016.670.016.671.1
AUQueenslandBrisbaneKangaroo PointMain St
+130734246-27.4812508,153.0358124 -27.4805794,153.035781974.016.670.016.674.4
AUQueenslandBrisbaneKangaroo PointMain St
+130734128-27.4805794,153.0357819 -27.4801197,153.035766651.016.670.016.673.1
AUQueenslandBrisbaneKangaroo PointMain St
+130734055-27.4801197,153.0357666 -27.4793091,153.035751390.016.670.016.675.4
AUQueenslandBrisbaneKangaroo PointMain St
+130733940-27.4793091,153.0357513 -27.4792404,153.03575137.016.670.016.670.4
AUQueenslandBrisbaneKangaroo PointMain St
+130733926-27.4792404,153.0357513 -27.47855,153.035736176.016.670.016.674.6
AUQueenslandBrisbaneKangaroo PointMain St
+845530476-27.47855,153.0357361 -27.4782295,153.035736135.016.670.016.672.1
AUQueenslandBrisbaneKangaroo PointMain St
+845530477-27.4782295,153.0357361 -27.4780293,153.035751322.016.670.016.671.3
AUQueenslandBrisbaneKangaroo PointMain St
+845360074-27.4780293,153.0357513 -27.4774399,153.035720865.016.670.016.673.9
AUQueenslandBrisbaneKangaroo PointMain St
+845360075-27.4774399,153.0357208 -27.4769306,153.035705656.016.670.016.673.4
AUQueenslandBrisbaneKangaroo PointMain St
+845360076-27.4769306,153.0357056 -27.4765701,153.035705640.016.670.016.672.4
AUQueenslandBrisbaneKangaroo PointMain St
+130733534-27.4765701,153.0357056 -27.4764309,153.035705615.016.670.016.670.9
AUQueenslandBrisbaneKangaroo PointMain St
+811754675-27.4764309,153.0357056 -27.4762497,153.035690320.016.670.016.671.2
AUQueenslandBrisbaneKangaroo PointMain St
+821266206-27.4762497,153.0356903 -27.4758797,153.035644541.016.670.016.672.5
AUQueenslandBrisbaneKangaroo PointMain St
+821266207-27.4758797,153.0356445 -27.4758091,153.03564457.016.670.016.670.4
AUQueenslandBrisbaneKangaroo PointMain St
+130733423-27.4758091,153.0356445 -27.4757595,153.03564455.016.670.016.670.3
AUQueenslandBrisbaneKangaroo PointMain St
+811754670-27.4757595,153.0356445 -27.4756107,153.035583517.016.670.016.671.0
AUQueenslandBrisbaneKangaroo PointMain St
+811754671-27.4756107,153.0355835 -27.4752903,153.035583535.016.670.016.672.1
AUQueenslandBrisbaneKangaroo PointMain St
+781681415-27.4752903,153.0355835 -27.4749699,153.03555335.016.670.016.672.1
AUQueenslandBrisbaneKangaroo PointMain St
+130849254-27.4749699,153.035553 -27.4743099,153.03555373.016.670.016.674.4
AUQueenslandBrisbaneKangaroo PointMain St
+845463722-27.4743099,153.035553 -27.4732399,153.0355377118.016.670.016.677.1
AUQueenslandBrisbaneKangaroo PointMain St
+845463723-27.4732399,153.0355377 -27.4727306,153.035522556.016.670.016.673.4
AUQueenslandBrisbaneKangaroo PointMain St
+845463724-27.4727306,153.0355225 -27.4721909,153.035522560.016.670.016.673.6
AUQueenslandBrisbaneKangaroo PointMain St
+845463727-27.4721909,153.0355225 -27.4716606,153.035507258.016.670.016.673.5
AUQueenslandBrisbaneKangaroo PointMain St
+845463728-27.4716606,153.0355072 -27.4712791,153.035507242.016.670.016.672.5
AUQueenslandBrisbaneKangaroo PointMain St
+781679323-27.4712791,153.0355072 -27.4712505,153.03550723.016.670.016.670.2
AUQueenslandBrisbaneKangaroo PointMain St
+811498732-27.4712505,153.0355072 -27.4712105,153.0355225 -27.4710503,153.035583523.016.670.016.671.4
AUQueenslandBrisbaneKangaroo PointMain St
+130849251-27.4710503,153.0355835 -27.4709301,153.035629314.016.670.016.670.8
AUQueenslandBrisbaneKangaroo PointBradfield Hwy
+779133869-27.4709301,153.0356293 -27.4706802,153.035675 -27.4706097,153.03567535.016.670.016.672.1
AUQueenslandBrisbaneKangaroo PointBradfield Hwy
+779133870-27.4706097,153.035675 -27.4704609,153.0357056 -27.4702797,153.035797138.016.670.016.672.3
AUQueenslandBrisbaneKangaroo PointBradfield Hwy
+130732275-27.4702797,153.0357971 -27.4698505,153.0358429 -27.4694595,153.0358734 -27.4692192,153.0358734118.016.670.016.677.1
AUQueenslandBrisbaneKangaroo PointBradfield Hwy
+130732051-27.4692192,153.0358734 -27.4685898,153.035888770.016.670.016.674.2
AUQueenslandBrisbaneKangaroo PointBradfield Hwy
+130731930-27.4685898,153.0358887 -27.4680004,153.035903965.016.670.016.673.9
AUQueenslandBrisbaneKangaroo PointBradfield Hwy
+778423229-27.4680004,153.0359039 -27.4671707,153.035858292.016.670.016.675.5
AUQueenslandBrisbaneKangaroo PointBradfield Hwy
+778423230-27.4671707,153.0358582 -27.4659309,153.0358124137.016.670.016.678.2
AUQueenslandBrisbaneKangaroo PointBradfield Hwy
+778423228-27.4659309,153.0358124 -27.4658508,153.03581248.016.670.016.670.5
AUQueenslandBrisbaneKangaroo PointBradfield Hwy
+778592178-27.4658508,153.0358124 -27.4657001,153.035812416.016.670.016.671.0
AUQueenslandBrisbaneKangaroo PointBradfield Hwy, Story Brg
+779145761-27.4657001,153.0358124 -27.4648304,153.035781996.016.670.016.675.8
AUQueenslandBrisbaneKangaroo PointBradfield Hwy, Story Brg
+779145762-27.4648304,153.0357819 -27.4647808,153.0357819 -27.4627304,153.0357056233.016.670.016.6714.0
AUQueenslandBrisbaneKangaroo PointBradfield Hwy, Story Brg
+750205884-27.4627304,153.0357056 -27.4624996,153.035705625.016.670.016.671.5
AUQueenslandBrisbaneKangaroo PointBradfield Hwy, Story Brg
+779145730-27.4624996,153.0357056 -27.4624195,153.03570568.016.670.016.670.5
AUQueenslandBrisbaneFortitude ValleyBradfield Hwy, Story Brg
+779145731-27.4624195,153.0357056 -27.4622898,153.035705614.016.670.016.670.8
AUQueenslandBrisbaneFortitude ValleyBradfield Hwy, Story Brg
+779145721-27.4622898,153.0357056 -27.4619904,153.035705633.016.670.016.672.0
AUQueenslandBrisbaneFortitude ValleyBradfield Hwy, Story Brg
+130851739-27.4619904,153.0357056 -27.4617596,153.035659826.016.670.016.671.6
AUQueenslandBrisbaneFortitude ValleyBradfield Hwy
+130851740-27.4617596,153.0356598 -27.4615402,153.035644524.016.670.016.671.4
AUQueenslandBrisbaneFortitude ValleyBradfield Hwy
+828880864-27.4615402,153.0356445 -27.4613094,153.035614 -27.4611397,153.035553 -27.4609203,153.0354004 -27.4607296,153.0351868 -27.4606895,153.0351563109.016.670.016.676.5
AUQueenslandBrisbaneFortitude Valley
+828880865-27.4606895,153.0351563 -27.4605103,153.0349731 -27.4603901,153.0348511 -27.4602909,153.0347595 -27.4601593,153.03472974.016.670.016.674.4
AUQueenslandBrisbaneFortitude Valley
+811489085-27.4601593,153.034729 -27.4600105,153.0347443 -27.4598408,153.0348969 -27.4597702,153.034973151.016.670.016.673.1
AUQueenslandBrisbaneFortitude Valley
+782798336-27.4597702,153.0349731 -27.4596596,153.0350816.016.670.016.671.0
AUQueenslandBrisbaneFortitude ValleyMcLachlan St
+782798337-27.4596596,153.03508 -27.4593391,153.035430949.016.670.016.672.9
AUQueenslandBrisbaneFortitude ValleyMcLachlan St
+130729659-27.4593391,153.0354309 -27.4590492,153.035736144.016.670.016.672.6
AUQueenslandBrisbaneFortitude ValleyMcLachlan St
-130729663-27.4590492,153.0357361 -27.4593506,153.036117650.013.890.09.725.1
AUQueenslandBrisbaneFortitude ValleyBrunswick St
-130729708-27.4593506,153.0361176 -27.4595604,153.03637734.013.890.09.723.5
AUQueenslandBrisbaneFortitude ValleyBrunswick St
-779178787-27.4595604,153.036377 -27.4598408,153.036743247.013.890.09.724.8
AUQueenslandBrisbaneFortitude ValleyBrunswick St
-779178786-27.4598408,153.0367432 -27.45998,153.036926323.013.890.09.722.4
AUQueenslandBrisbaneFortitude ValleyBrunswick St
-130729848-27.45998,153.0369263 -27.4601803,153.037185733.013.890.09.723.4
AUQueenslandBrisbaneFortitude ValleyBrunswick St
-130851715-27.4601803,153.0371857 -27.4603996,153.037460336.013.890.09.723.7
AUQueenslandBrisbaneFortitude ValleyBrunswick St
-130851714-27.4603996,153.0374603 -27.4608307,153.037994471.013.890.09.727.3
AUQueenslandBrisbaneFortitude ValleyBrunswick St
-130730226-27.4608307,153.0379944 -27.4615307,153.0388947118.013.890.09.7212.1
AUQueenslandBrisbaneFortitude ValleyBrunswick St
-130730440-27.4615307,153.0388947 -27.4622307,153.0397949118.013.890.09.7212.1
AUQueenslandBrisbaneNew FarmBrunswick St
17283.01002.0998.0motorway
\ No newline at end of file diff --git a/tests/auto/qgeoroutexmlparser/tst_qgeoroutexmlparser.cpp b/tests/auto/qgeoroutexmlparser/tst_qgeoroutexmlparser.cpp new file mode 100644 index 0000000..36d679e --- /dev/null +++ b/tests/auto/qgeoroutexmlparser/tst_qgeoroutexmlparser.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QList) + +QT_USE_NAMESPACE + +class tst_QGeoRouteXmlParser : public QObject +{ + Q_OBJECT + +public: + tst_QGeoRouteXmlParser() + : start(0.0, 0.0), + end(1.0, 1.0) + { + qRegisterMetaType >(); + } + +private: + // dummy values for creating the request object + QGeoCoordinate start; + QGeoCoordinate end; + +private slots: + void test_realData1() + { + QFile f(":/route1.xml"); + if (!f.open(QIODevice::ReadOnly)) + QFAIL("could not open route1.xml"); + + QGeoRouteRequest req(start, end); + QGeoRouteXmlParser xp(req); + xp.setAutoDelete(false); + + QSignalSpy resultsSpy(&xp, SIGNAL(results(QList))); + + xp.parse(f.readAll()); + + QTRY_COMPARE(resultsSpy.count(), 1); + + QVariantList arguments = resultsSpy.first(); + + // xml contains exactly 1 route + QList results = arguments.at(0).value >(); + QCOMPARE(results.size(), 1); + QGeoRoute route = results.first(); + + QList segments; + // get all the segments on the route + segments << route.firstRouteSegment(); + while (segments.last().isValid()) + segments << segments.last().nextRouteSegment(); + + // should be 9 segments in the list (last one invalid) + QCOMPARE(segments.size(), 9); + + // check the first maneuver is correct + QGeoManeuver first = segments.at(0).maneuver(); + QCOMPARE(first.instructionText(), QStringLiteral("Head toward Logan Rd (95) on Padstow Rd (56). Go for 0.3 miles.")); + QCOMPARE(first.position(), QGeoCoordinate(-27.5752144, 153.0879669)); + + QCOMPARE(first.timeToNextInstruction(), 24); + QCOMPARE(first.distanceToNextInstruction(), 403.0); + + // check the last two maneuvers -- route1.xml has a directionless final maneuver + QGeoManeuver secondLast = segments.at(6).maneuver(); + QVERIFY(secondLast.instructionText().contains("Turn right onto Bartley St")); + QCOMPARE(secondLast.position(), QGeoCoordinate(-27.4655991, 153.0231628)); + QCOMPARE(secondLast.distanceToNextInstruction(), 181.0); + QCOMPARE(secondLast.timeToNextInstruction(), 41); + + QGeoManeuver last = segments.at(7).maneuver(); + QVERIFY(last.instructionText().contains("Arrive at Bartley St")); + QCOMPARE(last.position(), QGeoCoordinate(-27.4650097, 153.0230255)); + QCOMPARE(last.distanceToNextInstruction(), 0.0); + QCOMPARE(last.timeToNextInstruction(), 0); + } + + void test_realData2() + { + QFile f(":/route2.xml"); + if (!f.open(QIODevice::ReadOnly)) + QFAIL("could not open route2.xml"); + + QGeoRouteRequest req(start, end); + QGeoRouteXmlParser xp(req); + xp.setAutoDelete(false); + + QSignalSpy resultsSpy(&xp, SIGNAL(results(QList))); + + xp.parse(f.readAll()); + + QTRY_COMPARE(resultsSpy.count(), 1); + + QVariantList arguments = resultsSpy.first(); + + // xml contains exactly 1 route + QList results = arguments.at(0).value >(); + QCOMPARE(results.size(), 1); + QGeoRoute route = results.first(); + + QList segments; + // get all the segments on the route + segments << route.firstRouteSegment(); + while (segments.last().isValid()) + segments << segments.last().nextRouteSegment(); + + // should be 14 segments in the list (last one invalid) + QCOMPARE(segments.size(), 14); + + QCOMPARE(route.path().size(), 284); + QCOMPARE(route.path().at(57), QGeoCoordinate(-27.5530605, 153.0691223)); + QCOMPARE(route.path().at(283), QGeoCoordinate(-27.4622307, 153.0397949)); + + QVERIFY(segments.at(0).maneuver().instructionText().contains("Head toward Electronics St")); + QCOMPARE(segments.at(0).maneuver().direction(), QGeoManeuver::DirectionForward); + QVERIFY(segments.at(1).maneuver().instructionText().contains("Turn left onto Miles Platting")); + QCOMPARE(segments.at(1).maneuver().direction(), QGeoManeuver::DirectionLeft); + QVERIFY(segments.at(2).maneuver().instructionText().contains("Turn right onto Logan Rd")); + QCOMPARE(segments.at(2).maneuver().direction(), QGeoManeuver::DirectionRight); + QVERIFY(segments.at(3).maneuver().instructionText().contains("Take exit #14/M3/City")); + QCOMPARE(segments.at(3).maneuver().direction(), QGeoManeuver::DirectionLightLeft); + QVERIFY(segments.at(4).maneuver().instructionText().contains("Take exit #2/41")); + QCOMPARE(segments.at(4).maneuver().direction(), QGeoManeuver::DirectionLightLeft); + QVERIFY(segments.at(5).maneuver().instructionText().contains("Turn right onto Allen St")); + QCOMPARE(segments.at(5).maneuver().direction(), QGeoManeuver::DirectionRight); + QVERIFY(segments.at(6).maneuver().instructionText().contains("Bear right to stay on")); + QCOMPARE(segments.at(6).maneuver().direction(), QGeoManeuver::DirectionLightRight); + QVERIFY(segments.at(7).maneuver().instructionText().contains("Bear right onto Vulture St")); + QCOMPARE(segments.at(7).maneuver().direction(), QGeoManeuver::DirectionLightRight); + } +}; + +QTEST_GUILESS_MAIN(tst_QGeoRouteXmlParser) +#include "tst_qgeoroutexmlparser.moc" + diff --git a/tests/auto/qgeoroutingmanager/qgeoroutingmanager.pro b/tests/auto/qgeoroutingmanager/qgeoroutingmanager.pro new file mode 100644 index 0000000..836d29c --- /dev/null +++ b/tests/auto/qgeoroutingmanager/qgeoroutingmanager.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeoroutingmanager + +HEADERS += tst_qgeoroutingmanager.h + +SOURCES += tst_qgeoroutingmanager.cpp + +CONFIG -= app_bundle + +QT += location testlib diff --git a/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.cpp b/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.cpp new file mode 100644 index 0000000..4dbeea5 --- /dev/null +++ b/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include "tst_qgeoroutingmanager.h" + +QT_USE_NAMESPACE + + +void tst_QGeoRoutingManager::initTestCase() +{ + /* + * Set custom path since CI doesn't install test plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif + tst_QGeoRoutingManager::loadRoutingManager(); +} + +void tst_QGeoRoutingManager::cleanupTestCase() +{ + //delete qgeoroutingmanager; + delete qgeoserviceprovider; +} + +void tst_QGeoRoutingManager::init() +{ +} + +void tst_QGeoRoutingManager::cleanup() +{ +} + +void tst_QGeoRoutingManager::loadRoutingManager() +{ + QStringList providers = QGeoServiceProvider::availableServiceProviders(); + QVERIFY(providers.contains("georoute.test.plugin")); + + qgeoserviceprovider = new QGeoServiceProvider("georoute.test.plugin"); + QVERIFY(qgeoserviceprovider); + QCOMPARE(qgeoserviceprovider->error(), QGeoServiceProvider::NotSupportedError); + qgeoserviceprovider->setAllowExperimental(true); + + QCOMPARE(qgeoserviceprovider->routingFeatures(), + QGeoServiceProvider::OfflineRoutingFeature + | QGeoServiceProvider::AlternativeRoutesFeature + | QGeoServiceProvider::RouteUpdatesFeature + | QGeoServiceProvider::ExcludeAreasRoutingFeature); + QCOMPARE(qgeoserviceprovider->error(), QGeoServiceProvider::NoError); + + qgeoroutingmanager = qgeoserviceprovider->routingManager(); + QVERIFY(qgeoroutingmanager); + +} + +void tst_QGeoRoutingManager::supports() +{ + QCOMPARE(qgeoroutingmanager->supportedTravelModes(),QGeoRouteRequest::PedestrianTravel); + QCOMPARE(qgeoroutingmanager->supportedFeatureTypes(),QGeoRouteRequest::TollFeature); + QCOMPARE(qgeoroutingmanager->supportedFeatureWeights(),QGeoRouteRequest::PreferFeatureWeight); + QCOMPARE(qgeoroutingmanager->supportedRouteOptimizations(),QGeoRouteRequest::FastestRoute); + QCOMPARE(qgeoroutingmanager->supportedSegmentDetails(),QGeoRouteRequest::BasicSegmentData); + QCOMPARE(qgeoroutingmanager->supportedManeuverDetails(),QGeoRouteRequest::BasicManeuvers); +} + +void tst_QGeoRoutingManager::locale() +{ + QLocale german = QLocale(QLocale::German, QLocale::Germany); + QLocale english = QLocale(QLocale::C, QLocale::AnyCountry); + + qgeoroutingmanager->setLocale(german); + + QCOMPARE(qgeoroutingmanager->locale(), german); + + QVERIFY(qgeoroutingmanager->locale() != english); + + QLocale en_UK = QLocale(QLocale::English, QLocale::UnitedKingdom); + qgeoroutingmanager->setLocale(en_UK); + QCOMPARE(qgeoroutingmanager->measurementSystem(), en_UK.measurementSystem()); + qgeoroutingmanager->setMeasurementSystem(QLocale::MetricSystem); + QCOMPARE(qgeoroutingmanager->measurementSystem(), QLocale::MetricSystem); + QVERIFY(qgeoroutingmanager->locale().measurementSystem() != qgeoroutingmanager->measurementSystem()); +} + +void tst_QGeoRoutingManager::name() +{ + QString name = "georoute.test.plugin"; + QCOMPARE(qgeoroutingmanager->managerName(), name); +} + +void tst_QGeoRoutingManager::version() +{ + QCOMPARE(qgeoroutingmanager->managerVersion(), 100); +} + +void tst_QGeoRoutingManager::calculate() +{ + QString error = "no error"; + origin = new QGeoCoordinate(12.12 , 23.23); + destination = new QGeoCoordinate(34.34 , 89.32); + request = new QGeoRouteRequest(*origin, *destination); + + reply = qgeoroutingmanager->calculateRoute(*request); + + QCOMPARE(reply->error(), QGeoRouteReply::NoError); + QCOMPARE(reply->errorString(), error); + + delete origin; + delete destination; + delete request; + delete reply; +} + + +void tst_QGeoRoutingManager::update() +{ + QString error = "no error"; + position = new QGeoCoordinate(34.34, 89.32); + route = new QGeoRoute(); + + reply = qgeoroutingmanager->updateRoute(*route, *position); + + QCOMPARE(reply->error(), QGeoRouteReply::CommunicationError); + QCOMPARE(reply->errorString(), error); + + delete position; + delete route; + delete reply; +} + +QTEST_MAIN(tst_QGeoRoutingManager) + diff --git a/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.h b/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.h new file mode 100644 index 0000000..8d85d47 --- /dev/null +++ b/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#ifndef TST_QGEOROUTINGMANAGER_H +#define TST_QGEOROUTINGMANAGER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QGeoRoutingManager: public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + void supports(); + void locale(); + void name(); + void version(); + void calculate(); + void update(); + +private: + QGeoServiceProvider *qgeoserviceprovider; + QGeoRoutingManager *qgeoroutingmanager; + QGeoRouteRequest *request; + QGeoRouteReply *reply; + QGeoCoordinate *origin; + QGeoCoordinate *destination; + QGeoRoute *route; + QGeoCoordinate *position; + void loadRoutingManager(); + +}; + +#endif diff --git a/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerengine_test.h b/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerengine_test.h new file mode 100644 index 0000000..cb75fec --- /dev/null +++ b/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerengine_test.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOROUTINGMANAGERENGINE_TEST_H +#define QGEOROUTINGMANAGERENGINE_TEST_H + +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class QGeoRoutingManagerEngineTest: public QGeoRoutingManagerEngine + +{ +Q_OBJECT +public: + QGeoRoutingManagerEngineTest(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) : + QGeoRoutingManagerEngine(parameters) + { + Q_UNUSED(error) + Q_UNUSED(errorString) + setSupportedTravelModes(QGeoRouteRequest::PedestrianTravel); + setSupportedFeatureTypes(QGeoRouteRequest::TollFeature); + setSupportedFeatureWeights(QGeoRouteRequest::PreferFeatureWeight); + setSupportedRouteOptimizations(QGeoRouteRequest::FastestRoute); + setSupportedSegmentDetails(QGeoRouteRequest::BasicSegmentData); + setSupportedManeuverDetails(QGeoRouteRequest::BasicManeuvers); + } + + QGeoRouteReply* calculateRoute(const QGeoRouteRequest& request) + { + Q_UNUSED(request); + return new QGeoRouteReply(QGeoRouteReply::NoError,"no error"); + } + + QGeoRouteReply* updateRoute(const QGeoRoute &route, const QGeoCoordinate &position) + { + Q_UNUSED(route); + Q_UNUSED(position); + return new QGeoRouteReply(QGeoRouteReply::CommunicationError,"no error"); + + } + + +}; + +#endif diff --git a/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerplugins.pro b/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerplugins.pro new file mode 100644 index 0000000..4222f35 --- /dev/null +++ b/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerplugins.pro @@ -0,0 +1,15 @@ +TARGET = qtgeoservices_routingplugin +QT += location + +PLUGIN_TYPE = geoservices +PLUGIN_CLASS_NAME = RoutingTestGeoServicePlugin +PLUGIN_EXTENDS = - +load(qt_plugin) + +HEADERS += qgeoroutingmanagerengine_test.h \ + qgeoserviceproviderplugin_test.h + +SOURCES += qgeoserviceproviderplugin_test.cpp + +OTHER_FILES += \ + routing_plugin.json diff --git a/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.cpp b/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.cpp new file mode 100644 index 0000000..4c35a91 --- /dev/null +++ b/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoserviceproviderplugin_test.h" +#include "qgeoroutingmanagerengine_test.h" + +#include + +QGeoServiceProviderFactoryTest::QGeoServiceProviderFactoryTest() +{ +} + +QGeoServiceProviderFactoryTest::~QGeoServiceProviderFactoryTest() +{ +} + +QGeoRoutingManagerEngine* QGeoServiceProviderFactoryTest::createRoutingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, + QString *errorString) const +{ + return new QGeoRoutingManagerEngineTest(parameters, error, errorString); +} diff --git a/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.h b/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.h new file mode 100644 index 0000000..e909b64 --- /dev/null +++ b/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSERVICEPROVIDER_TEST_H +#define QGEOSERVICEPROVIDER_TEST_H + +#include +#include + +QT_USE_NAMESPACE + +class QGeoServiceProviderFactoryTest: public QObject, public QGeoServiceProviderFactory +{ + Q_OBJECT + Q_INTERFACES(QGeoServiceProviderFactory) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0" + FILE "routing_plugin.json") + +public: + QGeoServiceProviderFactoryTest(); + ~QGeoServiceProviderFactoryTest(); + + QGeoRoutingManagerEngine* createRoutingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const; + +}; + +#endif + + diff --git a/tests/auto/qgeoroutingmanagerplugins/routing_plugin.json b/tests/auto/qgeoroutingmanagerplugins/routing_plugin.json new file mode 100644 index 0000000..25905f6 --- /dev/null +++ b/tests/auto/qgeoroutingmanagerplugins/routing_plugin.json @@ -0,0 +1,12 @@ +{ + "Keys": ["georoute.test.plugin"], + "Provider": "georoute.test.plugin", + "Version": 100, + "Experimental": true, + "Features": [ + "OfflineRoutingFeature", + "RouteUpdatesFeature", + "AlternativeRoutesFeature", + "ExcludeAreasRoutingFeature" + ] +} diff --git a/tests/auto/qgeosatelliteinfo/qgeosatelliteinfo.pro b/tests/auto/qgeosatelliteinfo/qgeosatelliteinfo.pro new file mode 100644 index 0000000..447ebdc --- /dev/null +++ b/tests/auto/qgeosatelliteinfo/qgeosatelliteinfo.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeosatelliteinfo + +SOURCES += tst_qgeosatelliteinfo.cpp + +QT += testlib positioning diff --git a/tests/auto/qgeosatelliteinfo/tst_qgeosatelliteinfo.cpp b/tests/auto/qgeosatelliteinfo/tst_qgeosatelliteinfo.cpp new file mode 100644 index 0000000..e1b0ad4 --- /dev/null +++ b/tests/auto/qgeosatelliteinfo/tst_qgeosatelliteinfo.cpp @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include + +#include +#include +#include +#include + +#include +#include + +QT_USE_NAMESPACE +Q_DECLARE_METATYPE(QGeoSatelliteInfo) +Q_DECLARE_METATYPE(QGeoSatelliteInfo::Attribute) + +QByteArray tst_qgeosatelliteinfo_debug; + +void tst_qgeosatelliteinfo_messageHandler(QtMsgType type, const QMessageLogContext &, const QString &msg) +{ + switch (type) { + case QtDebugMsg : + tst_qgeosatelliteinfo_debug = msg.toLocal8Bit(); + break; + default: + break; + } +} + + +QList tst_qgeosatelliteinfo_qrealTestValues() +{ + QList values; + + if (qreal(DBL_MIN) == DBL_MIN) + values << DBL_MIN; + + values << FLT_MIN; + values << -1.0 << 0.0 << 1.0; + values << FLT_MAX; + + if (qreal(DBL_MAX) == DBL_MAX) + values << DBL_MAX; + + return values; +} + +QList tst_qgeosatelliteinfo_intTestValues() +{ + QList values; + values << INT_MIN << -100 << 0 << 100 << INT_MAX; + return values; +} + +QList tst_qgeosatelliteinfo_getAttributes() +{ + QList attributes; + attributes << QGeoSatelliteInfo::Elevation + << QGeoSatelliteInfo::Azimuth; + return attributes; +} + + +class tst_QGeoSatelliteInfo : public QObject +{ + Q_OBJECT + +private: + QGeoSatelliteInfo updateWithAttribute(QGeoSatelliteInfo::Attribute attribute, qreal value) + { + QGeoSatelliteInfo info; + info.setAttribute(attribute, value); + return info; + } + + void addTestData_update() + { + QTest::addColumn("info"); + + QList intValues = tst_qgeosatelliteinfo_intTestValues(); + + for (int i=0; i attributes = tst_qgeosatelliteinfo_getAttributes(); + QList qrealValues = tst_qgeosatelliteinfo_qrealTestValues(); + for (int i=0; i attributes = tst_qgeosatelliteinfo_getAttributes(); + for (int i=0; i("signal"); + + QList intValues = tst_qgeosatelliteinfo_intTestValues(); + for (int i=0; i("satId"); + + QList intValues = tst_qgeosatelliteinfo_intTestValues(); + for (int i=0; i(system)); + QCOMPARE(info.satelliteSystem(), static_cast(system)); + } + + void setSatelliteSystem_data() + { + QTest::addColumn("system"); + + QTest::newRow("Sat system undefined") + << int(QGeoSatelliteInfo::Undefined); + QTest::newRow("Sat system GPS") + << int(QGeoSatelliteInfo::GPS); + QTest::newRow("Sat system GLONASS") + << int(QGeoSatelliteInfo::GLONASS); + } + + void attribute() + { + QFETCH(QGeoSatelliteInfo::Attribute, attribute); + QFETCH(qreal, value); + + QGeoSatelliteInfo u; + QCOMPARE(u.attribute(attribute), qreal(-1.0)); + + u.setAttribute(attribute, value); + QCOMPARE(u.attribute(attribute), value); + u.removeAttribute(attribute); + QCOMPARE(u.attribute(attribute), qreal(-1.0)); + } + + void attribute_data() + { + QTest::addColumn("attribute"); + QTest::addColumn("value"); + + QList props; + props << QGeoSatelliteInfo::Elevation + << QGeoSatelliteInfo::Azimuth; + for (int i=0; i> inInfo; + QCOMPARE(inInfo, info); + } + + void datastream_data() + { + addTestData_update(); + } + + void debug() + { + QFETCH(QGeoSatelliteInfo, info); + QFETCH(int, nextValue); + QFETCH(QByteArray, debugString); + + qInstallMessageHandler(tst_qgeosatelliteinfo_messageHandler); + qDebug() << info << nextValue; + qInstallMessageHandler(0); + QCOMPARE(QString(tst_qgeosatelliteinfo_debug), QString(debugString)); + } + + void debug_data() + { + QTest::addColumn("info"); + QTest::addColumn("nextValue"); + QTest::addColumn("debugString"); + + QGeoSatelliteInfo info; + + QTest::newRow("uninitialized") << info << 45 + << QByteArray("QGeoSatelliteInfo(system=0, satId=-1, signal-strength=-1) 45"); + + info = QGeoSatelliteInfo(); + info.setSignalStrength(1); + QTest::newRow("with SignalStrength") << info << 60 + << QByteArray("QGeoSatelliteInfo(system=0, satId=-1, signal-strength=1) 60"); + + info = QGeoSatelliteInfo(); + info.setSatelliteIdentifier(1); + QTest::newRow("with SatelliteIdentifier") << info << -1 + << QByteArray("QGeoSatelliteInfo(system=0, satId=1, signal-strength=-1) -1"); + + info = QGeoSatelliteInfo(); + info.setSatelliteSystem(QGeoSatelliteInfo::GPS); + QTest::newRow("with System GPS") << info << 1 + << QByteArray("QGeoSatelliteInfo(system=1, satId=-1, signal-strength=-1) 1"); + + info = QGeoSatelliteInfo(); + info.setSatelliteSystem(QGeoSatelliteInfo::GLONASS); + QTest::newRow("with System GLONASS") << info << 56 + << QByteArray("QGeoSatelliteInfo(system=2, satId=-1, signal-strength=-1) 56"); + + info = QGeoSatelliteInfo(); + info.setAttribute(QGeoSatelliteInfo::Elevation, 1.1); + QTest::newRow("with Elevation") << info << 0 + << QByteArray("QGeoSatelliteInfo(system=0, satId=-1, signal-strength=-1, Elevation=1.1) 0"); + + info = QGeoSatelliteInfo(); + info.setAttribute(QGeoSatelliteInfo::Azimuth, 1.1); + QTest::newRow("with Azimuth") << info << 45 + << QByteArray("QGeoSatelliteInfo(system=0, satId=-1, signal-strength=-1, Azimuth=1.1) 45"); + } +}; + + +QTEST_APPLESS_MAIN(tst_QGeoSatelliteInfo) +#include "tst_qgeosatelliteinfo.moc" diff --git a/tests/auto/qgeosatelliteinfosource/qgeosatelliteinfosource.pro b/tests/auto/qgeosatelliteinfosource/qgeosatelliteinfosource.pro new file mode 100644 index 0000000..4ca0f21 --- /dev/null +++ b/tests/auto/qgeosatelliteinfosource/qgeosatelliteinfosource.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +!no_system_tests:CONFIG += testcase +TARGET=tst_qgeosatelliteinfosource + +SOURCES += tst_qgeosatelliteinfosource.cpp \ + testqgeosatelliteinfosource.cpp \ + ../utils/qlocationtestutils.cpp + +HEADERS += testqgeosatelliteinfosource_p.h \ + ../utils/qlocationtestutils_p.h + +QT += positioning testlib diff --git a/tests/auto/qgeosatelliteinfosource/testqgeosatelliteinfosource.cpp b/tests/auto/qgeosatelliteinfosource/testqgeosatelliteinfosource.cpp new file mode 100644 index 0000000..0e75baa --- /dev/null +++ b/tests/auto/qgeosatelliteinfosource/testqgeosatelliteinfosource.cpp @@ -0,0 +1,767 @@ +/*********************f******************************************************* +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include +#include +#include +#include +#include + +#include +#include + +#include "testqgeosatelliteinfosource_p.h" +#include "../utils/qlocationtestutils_p.h" + +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QGeoSatelliteInfoSource::Error) + +#define MAX_WAITING_TIME 50000 + +// Must provide a valid source, unless testing the source +// returned by QGeoSatelliteInfoSource::createDefaultSource() on a system +// that has no default source +#define CHECK_SOURCE_VALID { \ + if (!m_source) { \ + if (m_testingDefaultSource && QGeoSatelliteInfoSource::createDefaultSource(0) == 0) \ + QSKIP("No default satellite source on this system"); \ + else \ + QFAIL("createTestSource() must return a valid source!"); \ + } \ + } + +class MySatelliteSource : public QGeoSatelliteInfoSource +{ + Q_OBJECT +public: + MySatelliteSource(QObject *parent = 0) + : QGeoSatelliteInfoSource(parent) { + } + virtual void startUpdates() {} + virtual void stopUpdates() {} + virtual void requestUpdate(int) {} + virtual int minimumUpdateInterval() const { + return 0; + } + Error error() const { return QGeoSatelliteInfoSource::NoError; } +}; + + +class DefaultSourceTest : public TestQGeoSatelliteInfoSource +{ + Q_OBJECT +protected: + QGeoSatelliteInfoSource *createTestSource() { + return QGeoSatelliteInfoSource::createDefaultSource(0); + } +}; + +TestQGeoSatelliteInfoSource::TestQGeoSatelliteInfoSource(QObject *parent) + : QObject(parent) +{ + qRegisterMetaType(); + + m_testingDefaultSource = false; +} + +TestQGeoSatelliteInfoSource *TestQGeoSatelliteInfoSource::createDefaultSourceTest() +{ + DefaultSourceTest *test = new DefaultSourceTest; + test->m_testingDefaultSource = true; + return test; +} + +void TestQGeoSatelliteInfoSource::base_initTestCase() +{ + qRegisterMetaType >(); +} + +void TestQGeoSatelliteInfoSource::base_init() +{ + m_source = createTestSource(); + m_testSlot2Called = false; +} + +void TestQGeoSatelliteInfoSource::base_cleanup() +{ + delete m_source; + m_source = 0; +} + +void TestQGeoSatelliteInfoSource::base_cleanupTestCase() +{ +} + +void TestQGeoSatelliteInfoSource::initTestCase() +{ + base_initTestCase(); +} + +void TestQGeoSatelliteInfoSource::init() +{ + base_init(); +} + +void TestQGeoSatelliteInfoSource::cleanup() +{ + base_cleanup(); +} + +void TestQGeoSatelliteInfoSource::cleanupTestCase() +{ + base_cleanupTestCase(); +} + +void TestQGeoSatelliteInfoSource::test_slot1() +{ +} + +void TestQGeoSatelliteInfoSource::test_slot2() +{ + m_testSlot2Called = true; +} + +void TestQGeoSatelliteInfoSource::constructor_withParent() +{ + QObject *parent = new QObject(); + new MySatelliteSource(parent); + delete parent; +} + +void TestQGeoSatelliteInfoSource::constructor_noParent() +{ + MySatelliteSource *obj = new MySatelliteSource(); + delete obj; +} + +void TestQGeoSatelliteInfoSource::createDefaultSource() +{ + QObject *parent = new QObject; + QGeoSatelliteInfoSource *source = QGeoSatelliteInfoSource::createDefaultSource(parent); + + // Check that default satellite source is successfully created. + if (!QGeoSatelliteInfoSource::availableSources().isEmpty()) + QVERIFY(source); + else + QVERIFY(!source); + + delete parent; +} + +void TestQGeoSatelliteInfoSource::createDefaultSource_noParent() +{ + QGeoSatelliteInfoSource *source = QGeoSatelliteInfoSource::createDefaultSource(0); + + // Check that default satellite source is successfully created. + if (!QGeoSatelliteInfoSource::availableSources().isEmpty()) + QVERIFY(source); + else + QVERIFY(!source); + + delete source; +} + +void TestQGeoSatelliteInfoSource::updateInterval() +{ + MySatelliteSource s; + QCOMPARE(s.updateInterval(), 0); +} + +void TestQGeoSatelliteInfoSource::setUpdateInterval() +{ + CHECK_SOURCE_VALID; + + QFETCH(int, interval); + QFETCH(int, expectedInterval); + + m_source->setUpdateInterval(interval); + QCOMPARE(m_source->updateInterval(), expectedInterval); +} + +void TestQGeoSatelliteInfoSource::setUpdateInterval_data() +{ + QTest::addColumn("interval"); + QTest::addColumn("expectedInterval"); + QGeoSatelliteInfoSource *source = createTestSource(); + int minUpdateInterval = source ? source->minimumUpdateInterval() : -1; + if (source) + delete source; + + QTest::newRow("0") << 0 << 0; + + if (minUpdateInterval > -1) { + QTest::newRow("INT_MIN") << INT_MIN << minUpdateInterval; + QTest::newRow("-1") << -1 << minUpdateInterval; + } + + if (minUpdateInterval > 0) { + QTest::newRow("more than minInterval") << minUpdateInterval + 1 << minUpdateInterval + 1; + QTest::newRow("equal to minInterval") << minUpdateInterval << minUpdateInterval; + } + + if (minUpdateInterval > 1) { + QTest::newRow("less then minInterval") << minUpdateInterval - 1 << minUpdateInterval; + QTest::newRow("in btw zero and minInterval") << 1 << minUpdateInterval; + } +} + +void TestQGeoSatelliteInfoSource::minimumUpdateInterval() +{ + CHECK_SOURCE_VALID; + + QVERIFY(m_source->minimumUpdateInterval() > 0); +} + +void TestQGeoSatelliteInfoSource::startUpdates_testIntervals() +{ + CHECK_SOURCE_VALID; + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy timeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->setUpdateInterval(7000); + int interval = m_source->updateInterval(); + + m_source->startUpdates(); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1), 9500); + for (int i = 0; i < 6; i++) { + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1) && (timeout.count() == 0), (interval*2)); + spyView.clear(); + spyUse.clear(); + } + m_source->stopUpdates(); +} + + +void TestQGeoSatelliteInfoSource::startUpdates_testIntervalChangesWhileRunning() +{ + // There are two ways of dealing with an interval change, and we have left it system dependent. + // The interval can be changed will running or after the next update. + // WinCE uses the first method, S60 uses the second method. + + // The minimum interval on the symbian emulator is 5000 msecs, which is why the times in + // this test are as high as they are. + + CHECK_SOURCE_VALID; + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy timeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->setUpdateInterval(0); + m_source->startUpdates(); + m_source->setUpdateInterval(0); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() > 0) && (spyUse.count() > 0), 7000); + QCOMPARE(timeout.count(), 0); + spyView.clear(); + spyUse.clear(); + + m_source->setUpdateInterval(5000); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 2) && (spyUse.count() == 2) && (timeout.count() == 0), 15000); + spyView.clear(); + spyUse.clear(); + + m_source->setUpdateInterval(10000); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 2) && (spyUse.count() == 2) && (timeout.count() == 0), 30000); + spyView.clear(); + spyUse.clear(); + + m_source->setUpdateInterval(5000); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 2) && (spyUse.count() == 2) && (timeout.count() == 0), 15000); + spyView.clear(); + spyUse.clear(); + + m_source->setUpdateInterval(5000); + + QTRY_VERIFY_WITH_TIMEOUT( (spyView.count() == 2) && (spyUse.count() == 2) && (timeout.count() == 0), 15000); + spyView.clear(); + spyUse.clear(); + + m_source->setUpdateInterval(0); + + QTRY_VERIFY_WITH_TIMEOUT( (spyView.count() > 0 ) && (spyUse.count() > 0) && (timeout.count() == 0), 7000); + spyView.clear(); + spyUse.clear(); + + m_source->setUpdateInterval(0); + + QTRY_VERIFY_WITH_TIMEOUT( (spyView.count() > 0 ) && (spyUse.count() > 0) && (timeout.count() == 0), 7000); + spyView.clear(); + spyUse.clear(); + m_source->stopUpdates(); +} + +void TestQGeoSatelliteInfoSource::startUpdates_testDefaultInterval() +{ + CHECK_SOURCE_VALID; + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy timeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->startUpdates(); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + for (int i = 0; i < 3; i++) { + QTRY_VERIFY_WITH_TIMEOUT( (spyView.count() > 0 ) && (spyUse.count() > 0) && (timeout.count() == 0), 7000); + spyView.clear(); + spyUse.clear(); + } + m_source->stopUpdates(); +} + +void TestQGeoSatelliteInfoSource::startUpdates_testZeroInterval() +{ + CHECK_SOURCE_VALID; + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy timeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->setUpdateInterval(0); + m_source->startUpdates(); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + for (int i = 0; i < 3; i++) { + QTRY_VERIFY_WITH_TIMEOUT( (spyView.count() > 0 ) && (spyUse.count() > 0) && (timeout.count() == 0), 7000); + spyView.clear(); + spyUse.clear(); + } + m_source->stopUpdates(); +} + +void TestQGeoSatelliteInfoSource::startUpdates_moreThanOnce() +{ + CHECK_SOURCE_VALID; + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->setUpdateInterval(0); + m_source->startUpdates(); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + m_source->startUpdates(); // check there is no crash + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() > 0) && (spyUse.count() > 0), MAX_WAITING_TIME); + + m_source->startUpdates(); // check there is no crash + + m_source->stopUpdates(); +} + +void TestQGeoSatelliteInfoSource::stopUpdates() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->setUpdateInterval(10000); + m_source->startUpdates(); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + for (int i = 0; i < 2; i++) { + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1), 12000); + spyView.clear(); + spyUse.clear(); + } + + m_source->stopUpdates(); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 0) && (spyUse.count() == 0), 12000); +} + +void TestQGeoSatelliteInfoSource::stopUpdates_withoutStart() +{ + CHECK_SOURCE_VALID; + + m_source->stopUpdates(); // check there is no crash +} + +void TestQGeoSatelliteInfoSource::requestUpdate() +{ + CHECK_SOURCE_VALID; + + QFETCH(int, timeout); + QSignalSpy spy(m_source, SIGNAL(requestTimeout())); + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->requestUpdate(timeout); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + // Geoclue may deliver update instantly if there is a satellite fix + QTRY_VERIFY_WITH_TIMEOUT(!spy.isEmpty() || !spyView.isEmpty(), 10); +} + +void TestQGeoSatelliteInfoSource::requestUpdate_data() +{ + QTest::addColumn("timeout"); + QTest::newRow("less than zero") << -1; + QTest::newRow("very small timeout") << 1; +} + +void TestQGeoSatelliteInfoSource::requestUpdate_validTimeout() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy spyTimeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->requestUpdate(7000); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + QTRY_VERIFY_WITH_TIMEOUT( + (spyView.count() == 1) && (spyUse.count() == 1 && (spyTimeout.count()) == 0), 7000); +} + +void TestQGeoSatelliteInfoSource::requestUpdate_defaultTimeout() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy spyTimeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->requestUpdate(0); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + QTRY_VERIFY_WITH_TIMEOUT( + (spyView.count() == 1) && (spyUse.count() == 1 && (spyTimeout.count()) == 0), + MAX_WAITING_TIME); +} + +void TestQGeoSatelliteInfoSource::requestUpdate_timeoutLessThanMinimumInterval() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyTimeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->requestUpdate(1); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + QTRY_COMPARE_WITH_TIMEOUT(spyTimeout.count(), 1, 1000); +} + +void TestQGeoSatelliteInfoSource::requestUpdate_repeatedCalls() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->requestUpdate(7000); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1), 7000); + spyView.clear(); + spyUse.clear(); + + m_source->requestUpdate(7000); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1), 7000); +} + +void TestQGeoSatelliteInfoSource::requestUpdate_overlappingCalls() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->requestUpdate(7000); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + m_source->requestUpdate(7000); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1), 7000); +} + +void TestQGeoSatelliteInfoSource::requestUpdate_overlappingCallsWithTimeout() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy spyTimeout(m_source, + SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->requestUpdate(0); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + m_source->requestUpdate(1); + + QTRY_COMPARE_WITH_TIMEOUT(spyTimeout.count(), 0, 7000); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1), 7000); +} + +void TestQGeoSatelliteInfoSource::requestUpdateAfterStartUpdates_ZeroInterval() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy spyTimeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->setUpdateInterval(0); + m_source->startUpdates(); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1), MAX_WAITING_TIME); + spyView.clear(); + spyUse.clear(); + + m_source->requestUpdate(7000); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1) + && (spyTimeout.count() == 0), 7000); + + spyView.clear(); + spyUse.clear(); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1), 12000); + + m_source->stopUpdates(); +} + +void TestQGeoSatelliteInfoSource::requestUpdateAfterStartUpdates_SmallInterval() +{ + CHECK_SOURCE_VALID; + + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy spyTimeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->setUpdateInterval(10000); + m_source->requestUpdate(7000); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + m_source->startUpdates(); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() > 0) && (spyUse.count() > 0) + && (spyTimeout.count() == 0), 7000); + + spyView.clear(); + spyUse.clear(); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() == 1) && (spyUse.count() == 1), 12000); + + m_source->stopUpdates(); +} + +void TestQGeoSatelliteInfoSource::requestUpdateBeforeStartUpdates_ZeroInterval() +{ + CHECK_SOURCE_VALID; + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy timeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->requestUpdate(7000); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + m_source->setUpdateInterval(0); + m_source->startUpdates(); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() >= 2) && (spyUse.count() >= 2) && (timeout.count() == 0), 14000); + spyView.clear(); + spyUse.clear(); + + QTest::qWait(7000); + + QCOMPARE(timeout.count(), 0); + + m_source->stopUpdates(); +} + +void TestQGeoSatelliteInfoSource::requestUpdateBeforeStartUpdates_SmallInterval() +{ + CHECK_SOURCE_VALID; + QSignalSpy spyView(m_source, + SIGNAL(satellitesInViewUpdated(QList))); + QSignalSpy spyUse(m_source, + SIGNAL(satellitesInUseUpdated(QList))); + QSignalSpy timeout(m_source, SIGNAL(requestTimeout())); + QSignalSpy errorSpy(m_source, SIGNAL(error(QGeoSatelliteInfoSource::Error))); + + m_source->requestUpdate(7000); + + if (!errorSpy.isEmpty()) + QSKIP("Error starting satellite updates."); + + m_source->setUpdateInterval(10000); + m_source->startUpdates(); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() > 0) && (spyUse.count() > 0) && (timeout.count() == 0), 7000); + spyView.clear(); + spyUse.clear(); + + QTRY_VERIFY_WITH_TIMEOUT((spyView.count() > 0) && (spyUse.count() > 0) && (timeout.count() == 0), 20000); + + m_source->stopUpdates(); +} + + + +void TestQGeoSatelliteInfoSource::removeSlotForRequestTimeout() +{ + CHECK_SOURCE_VALID; + + bool i = connect(m_source, SIGNAL(requestTimeout()), this, SLOT(test_slot1())); + QVERIFY(i==true); + i = connect(m_source, SIGNAL(requestTimeout()), this, SLOT(test_slot2())); + QVERIFY(i==true); + i = disconnect(m_source, SIGNAL(requestTimeout()), this, SLOT(test_slot1())); + QVERIFY(i==true); + + m_source->requestUpdate(-1); + QTRY_VERIFY_WITH_TIMEOUT((m_testSlot2Called == true), 1000); +} + +void TestQGeoSatelliteInfoSource::removeSlotForSatellitesInUseUpdated() +{ + CHECK_SOURCE_VALID; + + bool i = connect(m_source, SIGNAL(satellitesInUseUpdated(QList)), this, SLOT(test_slot1())); + QVERIFY(i == true); + i = connect(m_source, SIGNAL(satellitesInUseUpdated(QList)), this, SLOT(test_slot2())); + QVERIFY(i == true); + i = disconnect(m_source, SIGNAL(satellitesInUseUpdated(QList)), this, SLOT(test_slot1())); + QVERIFY(i == true); + + m_source->requestUpdate(7000); + + if (m_source->error() != QGeoSatelliteInfoSource::NoError) + QSKIP("Error starting satellite updates."); + + QTRY_VERIFY_WITH_TIMEOUT((m_testSlot2Called == true), 7000); +} + +void TestQGeoSatelliteInfoSource::removeSlotForSatellitesInViewUpdated() +{ + CHECK_SOURCE_VALID; + + bool i = connect(m_source, SIGNAL(satellitesInViewUpdated(QList)), this, SLOT(test_slot1())); + QVERIFY(i == true); + i = connect(m_source, SIGNAL(satellitesInViewUpdated(QList)), this, SLOT(test_slot2())); + QVERIFY(i == true); + i = disconnect(m_source, SIGNAL(satellitesInViewUpdated(QList)), this, SLOT(test_slot1())); + QVERIFY(i == true); + + m_source->requestUpdate(7000); + + if (m_source->error() != QGeoSatelliteInfoSource::NoError) + QSKIP("Error starting satellite updates."); + + QTRY_VERIFY_WITH_TIMEOUT((m_testSlot2Called == true), 7000); +} + +#include "testqgeosatelliteinfosource.moc" diff --git a/tests/auto/qgeosatelliteinfosource/testqgeosatelliteinfosource_p.h b/tests/auto/qgeosatelliteinfosource/testqgeosatelliteinfosource_p.h new file mode 100644 index 0000000..cf15f7c --- /dev/null +++ b/tests/auto/qgeosatelliteinfosource/testqgeosatelliteinfosource_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTQGEOSATELLITEINFOSOURCE_H +#define TESTQGEOSATELLITEINFOSOURCE_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QGeoSatelliteInfoSource; +QT_END_NAMESPACE + + +class TestQGeoSatelliteInfoSource : public QObject +{ + Q_OBJECT + +public: + TestQGeoSatelliteInfoSource(QObject *parent = 0); + + static TestQGeoSatelliteInfoSource *createDefaultSourceTest(); + +protected: + virtual QGeoSatelliteInfoSource *createTestSource() = 0; + + // MUST be called by subclasses if they override respective test slots + void base_initTestCase(); + void base_init(); + void base_cleanup(); + void base_cleanupTestCase(); + +public slots: + void test_slot1(); + void test_slot2(); + +private slots: + void initTestCase(); + void init(); + void cleanup(); + void cleanupTestCase(); + + void constructor_withParent(); + void constructor_noParent(); + + void updateInterval(); + + void setUpdateInterval(); + void setUpdateInterval_data(); + + void minimumUpdateInterval(); + + void createDefaultSource(); + void createDefaultSource_noParent(); + + void startUpdates_testIntervals(); + void startUpdates_testIntervalChangesWhileRunning(); + void startUpdates_testDefaultInterval(); + void startUpdates_testZeroInterval(); + void startUpdates_moreThanOnce(); + void stopUpdates(); + void stopUpdates_withoutStart(); + + void requestUpdate(); + void requestUpdate_data(); + + void requestUpdate_validTimeout(); + void requestUpdate_defaultTimeout(); + void requestUpdate_timeoutLessThanMinimumInterval(); + void requestUpdate_repeatedCalls(); + void requestUpdate_overlappingCalls(); + void requestUpdate_overlappingCallsWithTimeout(); + + void requestUpdateAfterStartUpdates_ZeroInterval(); + void requestUpdateAfterStartUpdates_SmallInterval(); + void requestUpdateBeforeStartUpdates_ZeroInterval(); + void requestUpdateBeforeStartUpdates_SmallInterval(); + + void removeSlotForRequestTimeout(); + void removeSlotForSatellitesInUseUpdated(); + void removeSlotForSatellitesInViewUpdated(); + +private: + QGeoSatelliteInfoSource *m_source; + bool m_testingDefaultSource; + bool m_testSlot2Called; +}; + +#endif // #ifndef TESTQGEOSATELLITEINFOSOURCE_H diff --git a/tests/auto/qgeosatelliteinfosource/tst_qgeosatelliteinfosource.cpp b/tests/auto/qgeosatelliteinfosource/tst_qgeosatelliteinfosource.cpp new file mode 100644 index 0000000..db8099a --- /dev/null +++ b/tests/auto/qgeosatelliteinfosource/tst_qgeosatelliteinfosource.cpp @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testqgeosatelliteinfosource_p.h" +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + TestQGeoSatelliteInfoSource *test = TestQGeoSatelliteInfoSource::createDefaultSourceTest(); + return QTest::qExec(test, argc, argv); +} diff --git a/tests/auto/qgeoserviceprovider/qgeoserviceprovider.pro b/tests/auto/qgeoserviceprovider/qgeoserviceprovider.pro new file mode 100644 index 0000000..5dfe2dd --- /dev/null +++ b/tests/auto/qgeoserviceprovider/qgeoserviceprovider.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG+=testcase +TARGET=tst_qgeoserviceprovider + +SOURCES += tst_qgeoserviceprovider.cpp + +CONFIG -= app_bundle + +QT += testlib location diff --git a/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp b/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp new file mode 100644 index 0000000..e33dab3 --- /dev/null +++ b/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QGeoServiceProvider : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void tst_availableServiceProvider(); + void tst_features_data(); + void tst_features(); + void tst_misc(); + void tst_nokiaRename(); +}; + +void tst_QGeoServiceProvider::initTestCase() +{ + /* + * Set custom path since CI doesn't install test plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif +} + +void tst_QGeoServiceProvider::tst_availableServiceProvider() +{ + const QStringList provider = QGeoServiceProvider::availableServiceProviders(); + + // Currently provided plugins + if (provider.count() != 7) + qWarning() << provider; + QCOMPARE(provider.count(), 7); + // these providers are deployed + QVERIFY(provider.contains(QStringLiteral("mapbox"))); + QVERIFY(provider.contains(QStringLiteral("here"))); + QVERIFY(provider.contains(QStringLiteral("osm"))); + // these providers exist for unit tests only + QVERIFY(provider.contains(QStringLiteral("geocode.test.plugin"))); + QVERIFY(provider.contains(QStringLiteral("georoute.test.plugin"))); + QVERIFY(provider.contains(QStringLiteral("qmlgeo.test.plugin"))); + QVERIFY(provider.contains(QStringLiteral("test.places.unsupported"))); + +} + +Q_DECLARE_METATYPE(QGeoServiceProvider::MappingFeatures) +Q_DECLARE_METATYPE(QGeoServiceProvider::GeocodingFeatures) +Q_DECLARE_METATYPE(QGeoServiceProvider::RoutingFeatures) +Q_DECLARE_METATYPE(QGeoServiceProvider::PlacesFeatures) + +void tst_QGeoServiceProvider::tst_features_data() +{ + QTest::addColumn("providerName"); + QTest::addColumn("mappingFeatures"); + QTest::addColumn("codingFeatures"); + QTest::addColumn("routingFeatures"); + QTest::addColumn("placeFeatures"); + + QTest::newRow("invalid") << QString("non-existing-provider-name") + << QGeoServiceProvider::MappingFeatures(QGeoServiceProvider::NoMappingFeatures) + << QGeoServiceProvider::GeocodingFeatures(QGeoServiceProvider::NoGeocodingFeatures) + << QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::NoRoutingFeatures) + << QGeoServiceProvider::PlacesFeatures(QGeoServiceProvider::NoPlacesFeatures); + + QTest::newRow("mapbox") << QString("mapbox") + << QGeoServiceProvider::MappingFeatures(QGeoServiceProvider::OnlineMappingFeature) + << QGeoServiceProvider::GeocodingFeatures(QGeoServiceProvider::NoGeocodingFeatures) + << QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::NoRoutingFeatures) + << QGeoServiceProvider::PlacesFeatures(QGeoServiceProvider::NoPlacesFeatures); + + QTest::newRow("here") << QString("here") + << QGeoServiceProvider::MappingFeatures(QGeoServiceProvider::OnlineMappingFeature) + << QGeoServiceProvider::GeocodingFeatures(QGeoServiceProvider::OnlineGeocodingFeature + | QGeoServiceProvider::ReverseGeocodingFeature) + << QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::OnlineRoutingFeature + | QGeoServiceProvider::RouteUpdatesFeature + | QGeoServiceProvider::AlternativeRoutesFeature + | QGeoServiceProvider::ExcludeAreasRoutingFeature) + << QGeoServiceProvider::PlacesFeatures(QGeoServiceProvider::OnlinePlacesFeature + | QGeoServiceProvider::PlaceRecommendationsFeature + | QGeoServiceProvider::SearchSuggestionsFeature + | QGeoServiceProvider::LocalizedPlacesFeature); + + QTest::newRow("osm") << QString("osm") + << QGeoServiceProvider::MappingFeatures(QGeoServiceProvider::OnlineMappingFeature) + << QGeoServiceProvider::GeocodingFeatures(QGeoServiceProvider::OnlineGeocodingFeature + | QGeoServiceProvider::ReverseGeocodingFeature) + << QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::OnlineRoutingFeature) + << QGeoServiceProvider::PlacesFeatures(QGeoServiceProvider::OnlinePlacesFeature); +} + +void tst_QGeoServiceProvider::tst_features() +{ + QFETCH(QString, providerName); + QFETCH(QGeoServiceProvider::MappingFeatures, mappingFeatures); + QFETCH(QGeoServiceProvider::GeocodingFeatures, codingFeatures); + QFETCH(QGeoServiceProvider::RoutingFeatures, routingFeatures); + QFETCH(QGeoServiceProvider::PlacesFeatures, placeFeatures); + + QGeoServiceProvider provider(providerName); + QCOMPARE(provider.mappingFeatures(), mappingFeatures); + QCOMPARE(provider.geocodingFeatures(), codingFeatures); + QCOMPARE(provider.routingFeatures(), routingFeatures); + QCOMPARE(provider.placesFeatures(), placeFeatures); + + if (provider.mappingFeatures() == QGeoServiceProvider::NoMappingFeatures) { + QVERIFY(provider.mappingManager() == Q_NULLPTR); + } else { + // some plugins require token/access parameter + // they return 0 but set QGeoServiceProvider::MissingRequiredParameterError + if (provider.mappingManager() != Q_NULLPTR) + QCOMPARE(provider.error(), QGeoServiceProvider::NoError); + else + QCOMPARE(provider.error(), QGeoServiceProvider::MissingRequiredParameterError); + } + + if (provider.geocodingFeatures() == QGeoServiceProvider::NoGeocodingFeatures) { + QVERIFY(provider.geocodingManager() == Q_NULLPTR); + } else { + if (provider.geocodingManager() != Q_NULLPTR) + QVERIFY(provider.geocodingManager() != Q_NULLPTR); //pointless but we want a VERIFY here + else + QCOMPARE(provider.error(), QGeoServiceProvider::MissingRequiredParameterError); + } + + if (provider.routingFeatures() == QGeoServiceProvider::NoRoutingFeatures) { + QVERIFY(provider.routingManager() == Q_NULLPTR); + } else { + if (provider.routingManager() != Q_NULLPTR) + QCOMPARE(provider.error(), QGeoServiceProvider::NoError); + else + QCOMPARE(provider.error(), QGeoServiceProvider::MissingRequiredParameterError); + } + + if (provider.placesFeatures() == QGeoServiceProvider::NoPlacesFeatures) { + QVERIFY(provider.placeManager() == Q_NULLPTR); + } else { + if (provider.placeManager() != Q_NULLPTR) + QCOMPARE(provider.error(), QGeoServiceProvider::NoError); + else + QCOMPARE(provider.error(), QGeoServiceProvider::MissingRequiredParameterError); + } +} + +void tst_QGeoServiceProvider::tst_misc() +{ + const QStringList provider = QGeoServiceProvider::availableServiceProviders(); + QVERIFY(provider.contains(QStringLiteral("osm"))); + QVERIFY(provider.contains(QStringLiteral("geocode.test.plugin"))); + + QGeoServiceProvider test_experimental( + QStringLiteral("geocode.test.plugin"), QVariantMap(), true); + QGeoServiceProvider test_noexperimental( + QStringLiteral("geocode.test.plugin"), QVariantMap(), false); + QCOMPARE(test_experimental.error(), QGeoServiceProvider::NoError); + QCOMPARE(test_noexperimental.error(), QGeoServiceProvider::NotSupportedError); + + QGeoServiceProvider osm_experimental( + QStringLiteral("osm"), QVariantMap(), true); + QGeoServiceProvider osm_noexperimental( + QStringLiteral("osm"), QVariantMap(), false); + QCOMPARE(osm_experimental.error(), QGeoServiceProvider::NoError); + QCOMPARE(osm_noexperimental.error(), QGeoServiceProvider::NoError); +} + +void tst_QGeoServiceProvider::tst_nokiaRename() +{ + // The "nokia" plugin was renamed to "here". + // It remains available under the name "nokia" for now + // but is not advertised via QGeoServiceProvider::availableServiceProviders() + + QVERIFY(!QGeoServiceProvider::availableServiceProviders().contains("nokia")); + QGeoServiceProvider provider(QStringLiteral("nokia")); + QCOMPARE(provider.error(), QGeoServiceProvider::NoError); + +} + +QTEST_GUILESS_MAIN(tst_QGeoServiceProvider) + +#include "tst_qgeoserviceprovider.moc" diff --git a/tests/auto/qgeoshape/qgeoshape.pro b/tests/auto/qgeoshape/qgeoshape.pro new file mode 100644 index 0000000..dd55138 --- /dev/null +++ b/tests/auto/qgeoshape/qgeoshape.pro @@ -0,0 +1,5 @@ +load(testcase) +TARGET = tst_qgeoshape +QT += testlib positioning +SOURCES = \ + tst_qgeoshape.cpp diff --git a/tests/auto/qgeoshape/tst_qgeoshape.cpp b/tests/auto/qgeoshape/tst_qgeoshape.cpp new file mode 100644 index 0000000..72611ff --- /dev/null +++ b/tests/auto/qgeoshape/tst_qgeoshape.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +QString tst_qgeoshape_debug; + +void tst_qgeoshape_messageHandler(QtMsgType type, const QMessageLogContext&, + const QString &msg) +{ + switch (type) { + case QtDebugMsg : + tst_qgeoshape_debug = msg; + break; + default: + break; + } +} + +class tst_qgeoshape : public QObject +{ + Q_OBJECT + +private slots: + void testArea(); + void debug_data(); + void debug(); + void conversions(); +}; + +void tst_qgeoshape::testArea() +{ + QGeoShape area; + QVERIFY(!area.isValid()); + QVERIFY(area.isEmpty()); + QCOMPARE(area.type(), QGeoShape::UnknownType); + QVERIFY(!area.contains(QGeoCoordinate())); + + // QGeoShape never constructs a QGeoShapePrivate. Hence d_ptr is always 0. + + QGeoShape area2; + + QCOMPARE(area, area2); + + area = area2; + + QCOMPARE(area, area2); + + QGeoShape area3(area2); + + QCOMPARE(area2, area3); +} + +void tst_qgeoshape::debug_data() +{ + QTest::addColumn("shape"); + QTest::addColumn("nextValue"); + QTest::addColumn("debugString"); + + QTest::newRow("uninitialized") << QGeoShape() << 45 + << QString("QGeoShape(Unknown) 45"); + QTest::newRow("uninitialized") << QGeoShape(QGeoRectangle()) << 45 + << QString("QGeoShape(Rectangle) 45"); + QTest::newRow("uninitialized") << QGeoShape(QGeoCircle()) << 45 + << QString("QGeoShape(Circle) 45"); +} + + +void tst_qgeoshape::debug() +{ + QFETCH(QGeoShape, shape); + QFETCH(int, nextValue); + QFETCH(QString, debugString); + + qInstallMessageHandler(tst_qgeoshape_messageHandler); + qDebug() << shape << nextValue; + qInstallMessageHandler(0); + QCOMPARE(tst_qgeoshape_debug, debugString); +} + +void tst_qgeoshape::conversions() +{ + QVariant varShape = QVariant::fromValue(QGeoShape()); + QVariant varRect = QVariant::fromValue(QGeoRectangle( + QGeoCoordinate(1, 1), + QGeoCoordinate(2, 2))); + QVariant varCircle = QVariant::fromValue(QGeoCircle(QGeoCoordinate(3, 3), 1000)); + + QVERIFY(varShape.canConvert()); + QVERIFY(varShape.canConvert()); + QVERIFY(varShape.canConvert()); + QVERIFY(!varRect.canConvert()); + QVERIFY(varRect.canConvert()); + QVERIFY(varRect.canConvert()); + QVERIFY(varCircle.canConvert()); + QVERIFY(!varCircle.canConvert()); + QVERIFY(varCircle.canConvert()); +} + +QTEST_MAIN(tst_qgeoshape) +#include "tst_qgeoshape.moc" diff --git a/tests/auto/qgeotiledmap/qgeotiledmap.pro b/tests/auto/qgeotiledmap/qgeotiledmap.pro new file mode 100644 index 0000000..b485022 --- /dev/null +++ b/tests/auto/qgeotiledmap/qgeotiledmap.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeotiledmap +INCLUDEPATH += ../geotestplugin + +SOURCES += tst_qgeotiledmap.cpp + +QT += location-private positioning-private testlib +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp b/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp new file mode 100644 index 0000000..e7026cf --- /dev/null +++ b/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotiledmap_test.h" +#include "qgeotilefetcher_test.h" +#include "qgeotiledmappingmanagerengine_test.h" +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QGeoTiledMap::PrefetchStyle) + +class FetchTileCounter: public QObject +{ + Q_OBJECT +public Q_SLOTS: + void tileFetched(const QGeoTileSpec& spec) { + m_tiles << spec; + } +public: + QSet m_tiles; +}; + +class tst_QGeoTiledMap : public QObject +{ + Q_OBJECT + +public: + tst_QGeoTiledMap(); + ~tst_QGeoTiledMap(); + +private: + void waitForFetch(int count); + +private Q_SLOTS: + void initTestCase(); + void fetchTiles(); + void fetchTiles_data(); + +private: + QScopedPointer m_map; + QScopedPointer m_tilesCounter; + QGeoTileFetcherTest *m_fetcher; + +}; + +tst_QGeoTiledMap::tst_QGeoTiledMap(): + m_fetcher(0) +{ +} + +tst_QGeoTiledMap::~tst_QGeoTiledMap() +{ +} + +void tst_QGeoTiledMap::initTestCase() +{ + // Set custom path since CI doesn't install test plugins +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif + QVariantMap parameters; + parameters["tileSize"] = 16; + parameters["maxZoomLevel"] = 8; + parameters["finishRequestImmediately"] = true; + QGeoServiceProvider *provider = new QGeoServiceProvider("qmlgeo.test.plugin",parameters); + provider->setAllowExperimental(true); + QGeoMappingManager *mappingManager = provider->mappingManager(); + QVERIFY2(provider->error() == QGeoServiceProvider::NoError, "Could not load plugin: " + provider->errorString().toLatin1()); + m_map.reset(static_cast(mappingManager->createMap(this))); + QVERIFY(m_map); + m_map->setSize(QSize(16, 16)); + m_fetcher = static_cast(m_map->m_engine->tileFetcher()); + m_tilesCounter.reset(new FetchTileCounter()); + connect(m_fetcher, SIGNAL(tileFetched(const QGeoTileSpec&)), m_tilesCounter.data(), SLOT(tileFetched(const QGeoTileSpec&))); +} + +void tst_QGeoTiledMap::fetchTiles() +{ + QFETCH(double, zoomLevel); + QFETCH(int, visibleCount); + QFETCH(int, prefetchCount); + QFETCH(QGeoTiledMap::PrefetchStyle, style); + QFETCH(int, nearestNeighbourLayer); + + m_map->setPrefetchStyle(style); + + QGeoCameraData camera; + camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D( 0.5 , 0.5 ))); + + //prev_visible + camera.setZoomLevel(zoomLevel-1); + m_map->clearData(); + m_tilesCounter->m_tiles.clear(); + m_map->setCameraData(camera); + waitForFetch(visibleCount); + QSet prev_visible = m_tilesCounter->m_tiles; + + //visible + prefetch + camera.setZoomLevel(zoomLevel); + m_map->clearData(); + m_tilesCounter->m_tiles.clear(); + m_map->setCameraData(camera); + waitForFetch(visibleCount); + QSet visible = m_tilesCounter->m_tiles; + m_map->clearData(); + m_tilesCounter->m_tiles.clear(); + m_map->prefetchData(); + waitForFetch(prefetchCount); + QSet prefetched = m_tilesCounter->m_tiles; + + //next visible + camera.setZoomLevel(zoomLevel + 1); + m_map->clearData(); + m_tilesCounter->m_tiles.clear(); + m_map->setCameraData(camera); + waitForFetch(visibleCount); + QSet next_visible = m_tilesCounter->m_tiles; + + QVERIFY2(visibleCount == visible.size(), "visible count incorrect"); + QVERIFY2(prefetchCount == prefetched.size(), "prefetch count incorrect"); + QSetIterator i(visible); + while (i.hasNext()) + QVERIFY2(prefetched.contains(i.next()),"visible tile missing from prefetched tiles"); + + //for zoomLevels wihtout fractions more tiles are fetched for current zoomlevel due to ViewExpansion + if (qCeil(zoomLevel) != zoomLevel && style == QGeoTiledMap::PrefetchNeighbourLayer && nearestNeighbourLayer < zoomLevel) + QVERIFY2(prefetched == prev_visible + visible, "wrongly prefetched tiles"); + + if (qCeil(zoomLevel) != zoomLevel && style == QGeoTiledMap::PrefetchNeighbourLayer && nearestNeighbourLayer > zoomLevel) + QVERIFY2(prefetched == next_visible + visible, "wrongly prefetched tiles"); + + if (qCeil(zoomLevel) != zoomLevel && style == QGeoTiledMap::PrefetchTwoNeighbourLayers) + QVERIFY2(prefetched == prev_visible + visible + next_visible, "wrongly prefetched tiles"); +} + +void tst_QGeoTiledMap::fetchTiles_data() +{ + QTest::addColumn("zoomLevel"); + QTest::addColumn("visibleCount"); + QTest::addColumn("prefetchCount"); + QTest::addColumn("style"); + QTest::addColumn("nearestNeighbourLayer"); + QTest::newRow("zoomLevel: 4 , visible count: 4 : prefetch count: 16") << 4.0 << 4 << 4 + 16 << QGeoTiledMap::PrefetchNeighbourLayer << 3; + QTest::newRow("zoomLevel: 4.06 , visible count: 4 : prefetch count: 4") << 4.06 << 4 << 4 + 4 << QGeoTiledMap::PrefetchNeighbourLayer << 3; + QTest::newRow("zoomLevel: 4.1 , visible count: 4 : prefetch count: 4") << 4.1 << 4 << 4 + 4 << QGeoTiledMap::PrefetchNeighbourLayer << 3; + QTest::newRow("zoomLevel: 4.5 , visible count: 4 : prefetch count: 4") << 4.5 << 4 << 4 + 4 << QGeoTiledMap::PrefetchNeighbourLayer << 3; + QTest::newRow("zoomLevel: 4.6 , visible count: 4 : prefetch count: 4") << 4.6 << 4 << 4 + 4 << QGeoTiledMap::PrefetchNeighbourLayer << 5; + QTest::newRow("zoomLevel: 4.9 , visible count: 4 : prefetch count: 4") << 4.9 << 4 <<4 + 4 << QGeoTiledMap::PrefetchNeighbourLayer << 5; + QTest::newRow("zoomLevel: 4 , visible count: 4 : prefetch count: 4") << 4.0 << 4 << 16 + 4 + 4 << QGeoTiledMap::PrefetchTwoNeighbourLayers << 3; + QTest::newRow("zoomLevel: 4.1 , visible count: 4 : prefetch count: 4") << 4.1 << 4 << 4 + 4 + 4 << QGeoTiledMap::PrefetchTwoNeighbourLayers << 3; + QTest::newRow("zoomLevel: 4.6 ,visible count: 4 : prefetch count: 4") << 4.6 << 4 << 4 + 4 + 4 << QGeoTiledMap::PrefetchTwoNeighbourLayers << 5; +} + +void tst_QGeoTiledMap::waitForFetch(int count) +{ + int timeout = 0; + while (m_tilesCounter->m_tiles.count() < count && timeout < count) { + //250ms for each tile fetch + QTest::qWait(250); + timeout++; + } +} + +QTEST_MAIN(tst_QGeoTiledMap) + +#include "tst_qgeotiledmap.moc" diff --git a/tests/auto/qgeotiledmapscene/qgeotiledmapscene.pro b/tests/auto/qgeotiledmapscene/qgeotiledmapscene.pro new file mode 100644 index 0000000..c3ec6e9 --- /dev/null +++ b/tests/auto/qgeotiledmapscene/qgeotiledmapscene.pro @@ -0,0 +1,8 @@ +CONFIG += testcase +TARGET = tst_qgeotiledmapscene + +INCLUDEPATH += ../../../src/location/maps + +SOURCES += tst_qgeotiledmapscene.cpp + +QT += location positioning-private testlib diff --git a/tests/auto/qgeotiledmapscene/tst_qgeotiledmapscene.cpp b/tests/auto/qgeotiledmapscene/tst_qgeotiledmapscene.cpp new file mode 100644 index 0000000..3d43ebd --- /dev/null +++ b/tests/auto/qgeotiledmapscene/tst_qgeotiledmapscene.cpp @@ -0,0 +1,384 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location/maps + +#include "qgeotilespec_p.h" +#include "qgeotiledmapscene_p.h" +#include "qgeocameratiles_p.h" +#include "qgeocameradata_p.h" +#include "qabstractgeotilecache_p.h" + +#include +#include + +#include + +#include +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QGeoTiledMapScene : public QObject +{ + Q_OBJECT + + private: + void row(QString name, double screenX, double screenY, double cameraCenterX, double cameraCenterY, + double zoom, int tileSize, int screenWidth, int screenHeight, double mercatorX, double mercatorY){ + + // expected behaviour of wrapping + if (mercatorX <= 0.0) + mercatorX += 1.0; + else if (mercatorX > 1.0) + mercatorX -= 1.0; + + QTest::newRow(qPrintable(name)) + << screenX << screenY + << cameraCenterX << cameraCenterY + << zoom << tileSize + << screenWidth << screenHeight + << mercatorX + << mercatorY; + } + + void screenPositions(QString name, double cameraCenterX, double cameraCenterY, double zoom, + int tileSize, int screenWidth, int screenHeight) + { + double screenX; + double screenY; + double mercatorX; + double mercatorY; + + double halfLength = 1 / (std::pow(2.0, zoom) * 2); + double scaleX = screenWidth / tileSize; + double scaleY = screenHeight / tileSize; + double scaledHalfLengthX = halfLength * scaleX; + double scaledHalfLengthY = halfLength * scaleY; + + // top left + screenX = 0.0; + screenY = 1.0 * screenHeight; + mercatorX = cameraCenterX - scaledHalfLengthX; + mercatorY = cameraCenterY + scaledHalfLengthY; + row (name + QString("_topLeftScreen"), screenX, screenY, cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY); + + // top + screenX = 0.5 * screenWidth; + screenY = 1.0 * screenHeight; + mercatorX = cameraCenterX; + mercatorY = cameraCenterY + scaledHalfLengthY; + row (name + QString("_topScreen"), screenX, screenY, cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY); + + // top right + screenX = 1.0 * screenWidth; + screenY = 1.0 * screenHeight; + mercatorX = cameraCenterX + scaledHalfLengthX; + mercatorY = cameraCenterY + scaledHalfLengthY; + row (name + QString("_topRightScreen"), screenX, screenY, cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY); + + // left + screenX = 0.0 * screenWidth; + screenY = 0.5 * screenHeight; + mercatorX = cameraCenterX - scaledHalfLengthX; + mercatorY = cameraCenterY; + row (name + QString("_leftScreen"), screenX, screenY, cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY); + + // center + screenX = 0.5 * screenWidth; + screenY = 0.5 * screenHeight; + mercatorX = cameraCenterX; + mercatorY = cameraCenterY; + row (name + QString("_centerScreen"), screenX, screenY, cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY); + + // right + screenX = 1.0 * screenWidth; + screenY = 0.5 * screenHeight; + mercatorX = cameraCenterX + scaledHalfLengthX; + mercatorY = cameraCenterY; + row (name + QString("_rightScreen"), screenX, screenY, cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY); + + // bottom left + screenX = 0.0; + screenY = 0.0; + mercatorX = cameraCenterX - scaledHalfLengthX; + mercatorY = cameraCenterY - scaledHalfLengthY; + row (name + QString("_bottomLeftrScreen"), screenX, screenY, cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY); + + // bottom + screenX = 0.5 * screenWidth; + screenY = 0.0; + mercatorX = cameraCenterX; + mercatorY = cameraCenterY - scaledHalfLengthY; + row (name + QString("_bottomScreen"), screenX, screenY, cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY); + + // bottom right + screenX = 1.0 * screenWidth; + screenY = 0.0; + mercatorX = cameraCenterX + scaledHalfLengthX; + mercatorY = cameraCenterY - scaledHalfLengthY; + row (name + QString("_bottomRightScreen"), screenX, screenY, cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY); + + } + + void screenCameraPositions(QString name, double zoom, int tileSize, + int screenWidth, int screenHeight) + { + double cameraCenterX; + double cameraCenterY; + + // top left + cameraCenterX = 0; + cameraCenterY = 1.0; + screenPositions(name + QString("_topLeftCamera"), cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight); + + // top + cameraCenterX = 0.5; + cameraCenterY = 1.0; + screenPositions(name + QString("_topCamera"), cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight); + // top right + cameraCenterX = 1.0; + cameraCenterY = 1.0; + screenPositions(name + QString("_topRightCamera"), cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight); + // left + cameraCenterX = 0.0; + cameraCenterY = 0.5; + screenPositions(name + QString("_leftCamera"), cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight); + // middle + cameraCenterX = 0.5; + cameraCenterY = 0.5; + screenPositions(name + QString("_middleCamera"), cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight); + // right + cameraCenterX = 1.0; + cameraCenterY = 0.5; + screenPositions(name + QString("_rightCamera"), cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight); + // bottom left + cameraCenterX = 0.0; + cameraCenterY = 0.0; + screenPositions(name + QString("_bottomLeftCamera"), cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight); + // bottom + cameraCenterX = 0.5; + cameraCenterY = 0.0; + screenPositions(name + QString("_bottomCamera"), cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight); + // bottom right + cameraCenterX = 1.0; + cameraCenterY = 0.0; + screenPositions(name + QString("_bottomRightCamera"), cameraCenterX, cameraCenterY, + zoom, tileSize, screenWidth, screenHeight); + } + + void populateScreenMercatorData(){ + QTest::addColumn("screenX"); + QTest::addColumn("screenY"); + QTest::addColumn("cameraCenterX"); + QTest::addColumn("cameraCenterY"); + QTest::addColumn("zoom"); + QTest::addColumn("tileSize"); + QTest::addColumn("screenWidth"); + QTest::addColumn("screenHeight"); + QTest::addColumn("mercatorX"); + QTest::addColumn("mercatorY"); + + int tileSize; + double zoom; + int screenWidth; + int screenHeight; + QString name; + tileSize = 16; + zoom = 4.0; + + /* + ScreenWidth = t + ScreenHeight = t + */ + screenWidth = tileSize; + screenHeight = tileSize; + name = QString("_(t x t)"); + screenCameraPositions(name, zoom, tileSize, screenWidth, screenHeight); + + /* + ScreenWidth = t * 2 + ScreenHeight = t + */ + screenWidth = tileSize * 2; + screenHeight = tileSize; + name = QString("_(2t x t)"); + screenCameraPositions(name, zoom, tileSize, screenWidth, screenHeight); + + /* + ScreenWidth = t + ScreenHeight = t * 2 + */ + screenWidth = tileSize; + screenHeight = tileSize * 2; + name = QString("_(2t x t)"); + screenCameraPositions(name, zoom, tileSize, screenWidth, screenHeight); + + /* + Screen Width = t * 2 + Screen Height = t * 2 + */ + screenWidth = tileSize * 2; + screenHeight = tileSize * 2; + name = QString("_(2t x 2t)"); + screenCameraPositions(name, zoom, tileSize, screenWidth, screenHeight); + } + + private slots: + + void useVerticalLock(){ + QGeoCameraData camera; + camera.setZoomLevel(4.0); + camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D(0.0, 0.0))); + + QGeoCameraTiles ct; + ct.setTileSize(16); + ct.setCameraData(camera); + ct.setScreenSize(QSize(16,16)); + + QGeoTiledMapScene mapScene; + mapScene.setTileSize(16); + mapScene.setScreenSize(QSize(16,16*32)); + mapScene.setCameraData(camera); + QVERIFY(!mapScene.verticalLock()); + mapScene.setUseVerticalLock(true); + mapScene.setVisibleTiles(ct.createTiles()); + QVERIFY(mapScene.verticalLock()); + + // Test the case when setting vertical lock has no effect + QGeoTiledMapScene mapScene2; + mapScene2.setTileSize(16); + mapScene2.setScreenSize(QSize(16,16)); + mapScene2.setCameraData(camera); + QVERIFY(!mapScene2.verticalLock()); + mapScene2.setUseVerticalLock(true); + mapScene2.setVisibleTiles(ct.createTiles()); + QVERIFY(!mapScene2.verticalLock()); + } + + void screenToMercatorPositions(){ + QFETCH(double, screenX); + QFETCH(double, screenY); + QFETCH(double, cameraCenterX); + QFETCH(double, cameraCenterY); + QFETCH(double, zoom); + QFETCH(int, tileSize); + QFETCH(int, screenWidth); + QFETCH(int, screenHeight); + QFETCH(double, mercatorX); + QFETCH(double, mercatorY); + + QGeoCameraData camera; + camera.setZoomLevel(zoom); + camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D(cameraCenterX, cameraCenterY))); + + QGeoCameraTiles ct; + ct.setTileSize(tileSize); + ct.setCameraData(camera); + ct.setScreenSize(QSize(screenWidth,screenHeight)); + + QGeoTiledMapScene mapGeometry; + mapGeometry.setTileSize(tileSize); + mapGeometry.setScreenSize(QSize(screenWidth,screenHeight)); + mapGeometry.setCameraData(camera); + mapGeometry.setVisibleTiles(ct.createTiles()); + + QDoubleVector2D point(screenX,screenY); + QDoubleVector2D mecartorPos = mapGeometry.itemPositionToMercator(point); + + QCOMPARE(mecartorPos.x(),mercatorX); + QCOMPARE(mecartorPos.y(),mercatorY); + } + + void screenToMercatorPositions_data() + { + populateScreenMercatorData(); + } + + void mercatorToScreenPositions(){ + QFETCH(double, screenX); + QFETCH(double, screenY); + QFETCH(double, cameraCenterX); + QFETCH(double, cameraCenterY); + QFETCH(double, zoom); + QFETCH(int, tileSize); + QFETCH(int, screenWidth); + QFETCH(int, screenHeight); + QFETCH(double, mercatorX); + QFETCH(double, mercatorY); + + QGeoCameraData camera; + camera.setZoomLevel(zoom); + camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D(cameraCenterX, cameraCenterY))); + + QGeoCameraTiles ct; + ct.setTileSize(tileSize); + ct.setCameraData(camera); + ct.setScreenSize(QSize(screenWidth,screenHeight)); + + QGeoTiledMapScene mapGeometry; + mapGeometry.setTileSize(tileSize); + mapGeometry.setScreenSize(QSize(screenWidth,screenHeight)); + mapGeometry.setCameraData(camera); + mapGeometry.setVisibleTiles(ct.createTiles()); + + QDoubleVector2D mercatorPos(mercatorX, mercatorY); + QPointF point = mapGeometry.mercatorToItemPosition(mercatorPos).toPointF(); + + QCOMPARE(point.x(), screenX); + QCOMPARE(point.y(), screenY); + } + + void mercatorToScreenPositions_data(){ + populateScreenMercatorData(); + } + +}; + +QTEST_GUILESS_MAIN(tst_QGeoTiledMapScene) +#include "tst_qgeotiledmapscene.moc" diff --git a/tests/auto/qgeotilespec/qgeotilespec.pro b/tests/auto/qgeotilespec/qgeotilespec.pro new file mode 100644 index 0000000..eb48aea --- /dev/null +++ b/tests/auto/qgeotilespec/qgeotilespec.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeotilespec + +INCLUDEPATH += ../../../src/location/maps + +SOURCES += tst_qgeotilespec.cpp + +QT += location testlib diff --git a/tests/auto/qgeotilespec/tst_qgeotilespec.cpp b/tests/auto/qgeotilespec/tst_qgeotilespec.cpp new file mode 100644 index 0000000..84df268 --- /dev/null +++ b/tests/auto/qgeotilespec/tst_qgeotilespec.cpp @@ -0,0 +1,319 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "qgeotilespec_p.h" + +QT_USE_NAMESPACE + +class tst_QGeoTileSpec : public QObject +{ + Q_OBJECT + +public: + tst_QGeoTileSpec(); + +private: + void populateGeoTileSpecData(); + +private Q_SLOTS: + void constructorTest_data(); + void constructorTest(); + void pluginTest(); + void zoomTest(); + void xTest(); + void yTest(); + void mapIdTest(); + void assignsOperatorTest_data(); + void assignsOperatorTest(); + void equalsOperatorTest_data(); + void equalsOperatorTest(); + void lessThanOperatorTest_data(); + void lessThanOperatorTest(); + void qHashTest_data(); + void qHashTest(); +}; + +tst_QGeoTileSpec::tst_QGeoTileSpec() +{ +} + +void tst_QGeoTileSpec::populateGeoTileSpecData(){ + QTest::addColumn("plugin"); + QTest::addColumn("mapId"); + QTest::addColumn("zoom"); + QTest::addColumn("x"); + QTest::addColumn("y"); + QTest::newRow("zeros") << QString() << 0 << 0 << 0 << 0; + QTest::newRow("valid") << QString("geo plugin") << 455 << 1 << 20 << 50; + QTest::newRow("negative values") << QString("geo plugin negative") << -350 << 2 << -20 << -50; +} + +void tst_QGeoTileSpec::constructorTest_data() +{ + populateGeoTileSpecData(); +} + +void tst_QGeoTileSpec::constructorTest() +{ + QFETCH(QString,plugin); + QFETCH(int,zoom); + QFETCH(int,mapId); + QFETCH(int,x); + QFETCH(int,y); + + // test constructor copy with default values + QGeoTileSpec testObj; + QGeoTileSpec testObj2(testObj); + QCOMPARE(testObj.plugin(), testObj2.plugin()); + QCOMPARE(testObj.mapId(), testObj2.mapId()); + QCOMPARE(testObj.zoom(), testObj2.zoom()); + QCOMPARE(testObj.x(), testObj2.x()); + QCOMPARE(testObj.y(), testObj2.y()); + + // test second construct + QGeoTileSpec testObj3(plugin, mapId, zoom, x, y); + QCOMPARE(testObj3.plugin(), plugin); + QCOMPARE(testObj3.mapId(), mapId); + QCOMPARE(testObj3.zoom(), zoom); + QCOMPARE(testObj3.x(), x); + QCOMPARE(testObj3.y(), y); +} + +void tst_QGeoTileSpec::pluginTest() +{ + QGeoTileSpec tileSpec; + QCOMPARE(tileSpec.plugin(), QString()); + + QGeoTileSpec tileSpec2(QString("plugin test"),1,10,10,5); + QCOMPARE(tileSpec2.plugin(), QString("plugin test")); +} + +void tst_QGeoTileSpec::zoomTest() +{ + QGeoTileSpec tileSpec; + QVERIFY(tileSpec.zoom() == -1); + tileSpec.setZoom(1); + QVERIFY(tileSpec.zoom() == 1); + + QGeoTileSpec tileSpec2 = tileSpec; + QVERIFY(tileSpec2.zoom() == 1); + tileSpec.setZoom(2); + QVERIFY(tileSpec2.zoom() == 1); +} + +void tst_QGeoTileSpec::xTest() +{ + QGeoTileSpec tileSpec; + QVERIFY(tileSpec.x() == -1); + tileSpec.setX(10); + QVERIFY(tileSpec.x() == 10); + + QGeoTileSpec tileSpec2 = tileSpec; + QVERIFY(tileSpec2.x() == 10); + tileSpec.setX(30); + QVERIFY(tileSpec2.x() == 10); +} + +void tst_QGeoTileSpec::yTest() +{ + QGeoTileSpec tileSpec; + QVERIFY(tileSpec.y() == -1); + tileSpec.setY(20); + QVERIFY(tileSpec.y() == 20); + + QGeoTileSpec tileSpec2 = tileSpec; + QVERIFY(tileSpec2.y() == 20); + tileSpec.setY(40); + QVERIFY(tileSpec2.y() == 20); +} + +void tst_QGeoTileSpec::mapIdTest() +{ + QGeoTileSpec tileSpec; + QVERIFY(tileSpec.mapId() == 0); + tileSpec.setMapId(1); + QVERIFY(tileSpec.mapId() == 1); + + QGeoTileSpec tileSpec2 = tileSpec; + QVERIFY(tileSpec2.mapId() == 1); + tileSpec.setMapId(5); + QVERIFY(tileSpec2.mapId() == 1); +} + +void tst_QGeoTileSpec::assignsOperatorTest_data() +{ + populateGeoTileSpecData(); +} + + +void tst_QGeoTileSpec::assignsOperatorTest() +{ + QFETCH(QString,plugin); + QFETCH(int,mapId); + QFETCH(int,zoom); + QFETCH(int,x); + QFETCH(int,y); + + QGeoTileSpec testObj(plugin, mapId, zoom, x, y); + QGeoTileSpec testObj2; + testObj2 = testObj; + // test the correctness of the asignment operator + QVERIFY2(testObj2.plugin() == plugin, "Plugin not copied correctly"); + QVERIFY2(testObj2.zoom() == zoom, "Zoom not copied correctly"); + QVERIFY2(testObj2.mapId() == mapId, "Map Id not copied correctly"); + QVERIFY2(testObj2.x() == x, "X not copied correctly"); + QVERIFY2(testObj2.y() == y, "Y not copied correctly"); + // verify that values have not changed after an assignment + QVERIFY2(testObj.plugin() == testObj2.plugin(), "Plugin not copied correctly"); + QVERIFY2(testObj.zoom() == testObj2.zoom(), "Zoom not copied correctly"); + QVERIFY2(testObj.mapId() == testObj2.mapId(), "Map Id not copied correctly"); + QVERIFY2(testObj.x() == testObj2.x(), "X not copied correctly"); + QVERIFY2(testObj.y() == testObj2.y(), "Y not copied correctly"); +} + + +void tst_QGeoTileSpec::equalsOperatorTest_data() +{ + populateGeoTileSpecData(); +} + +void tst_QGeoTileSpec::equalsOperatorTest() +{ + QFETCH(QString,plugin); + QFETCH(int,mapId); + QFETCH(int,zoom); + QFETCH(int,x); + QFETCH(int,y); + + QGeoTileSpec testObj(plugin, mapId, zoom, x, y); + QGeoTileSpec testObj2(plugin, mapId, zoom, x, y); + QVERIFY2(testObj == testObj2, "Equals operator is not correct"); + + // test QGeoTileSpec pairs where they differ in one field + testObj2.setZoom(zoom+1); + QVERIFY2(!(testObj == testObj2), "Equals operator is not correct"); + testObj2 = testObj; + testObj2.setMapId(mapId+1); + QVERIFY2(!(testObj == testObj2), "Equals operator is not correct"); + testObj2 = testObj; + testObj2.setX(x+1); + QVERIFY2(!(testObj == testObj2), "Equals operator is not correct"); + testObj2 = testObj; + testObj2.setY(y+1); + QVERIFY2(!(testObj == testObj2), "Equals operator is not correct"); +} + +void tst_QGeoTileSpec::lessThanOperatorTest_data() +{ + populateGeoTileSpecData(); +} + +void tst_QGeoTileSpec::lessThanOperatorTest() +{ + QFETCH(QString,plugin); + QFETCH(int,mapId); + QFETCH(int,zoom); + QFETCH(int,x); + QFETCH(int,y); + + QGeoTileSpec testObj(plugin, mapId, zoom, x, y); + QGeoTileSpec testObj2(testObj); + QVERIFY(!(testObj < testObj2)); + + testObj2.setMapId(mapId-1); + QVERIFY2(testObj2 < testObj, "Less than operator is not correct for mapId"); + testObj2 = testObj; + testObj2.setZoom(zoom-1); + QVERIFY2(testObj2 < testObj, "Less than operator is not correct for zoom"); + testObj2 = testObj; + testObj2.setX(x-1); + QVERIFY2(testObj2 < testObj, "Less than operator is not correct for x"); + testObj2 = testObj; + testObj2.setY(y-1); + QVERIFY2(testObj2 < testObj, "Less than operator is not correct for y"); + + // less than comparisons are done in the order: plugin -> mapId -> zoom -> x -> y + // the test below checks if the order is correct + QGeoTileSpec testObj3(plugin + QString('a'), mapId-1, zoom-1, x-1, y-1); + QVERIFY2(testObj < testObj3, "Order of less than operator is not correct"); + QGeoTileSpec testObj4(plugin, mapId+1, zoom-1, x-1, y-1); + QVERIFY2(testObj < testObj4, "Order of less than operator is not correct"); + QGeoTileSpec testObj5(plugin, mapId, zoom+1, x-1, y-1); + QVERIFY2(testObj < testObj5, "Order of less than operator is not correct"); + QGeoTileSpec testObj6(plugin, mapId, zoom, x+1, y-1); + QVERIFY2(testObj < testObj6, "Order of less than operator is not correct"); + QGeoTileSpec testObj7(plugin, mapId, zoom, x, y+1); + QVERIFY2(testObj < testObj7, "Order of less than operator is not correct"); + + QGeoTileSpec testObj8(plugin, mapId-1, zoom+1, x+1, y+1); + QVERIFY2(testObj8 < testObj, "Order of less than operator is not correct"); + QGeoTileSpec testObj9(plugin, mapId, zoom-1, x+1, y+1); + QVERIFY2(testObj9 < testObj, "Order of less than operator is not correct"); + QGeoTileSpec testObj10(plugin, mapId, zoom, x-1, y+1); + QVERIFY2(testObj10 < testObj, "Order of less than operator is not correct"); +} + +void tst_QGeoTileSpec::qHashTest_data(){ + populateGeoTileSpecData(); +} + +void tst_QGeoTileSpec::qHashTest() +{ + QGeoTileSpec testObj; + unsigned int hash1 = qHash(testObj); + QGeoTileSpec testObj2; + testObj2 = testObj; + unsigned int hash2 = qHash(testObj2); + QCOMPARE(hash1, hash2); + + QFETCH(QString,plugin); + QFETCH(int,mapId); + QFETCH(int,zoom); + QFETCH(int,x); + QFETCH(int,y); + + QGeoTileSpec testObj3(plugin, mapId, zoom, x, y); + unsigned int hash3 = qHash(testObj3); + QVERIFY(hash1 != hash3); + + testObj2.setMapId(testObj3.mapId()+1); + testObj2.setZoom(testObj3.zoom()+1); + testObj2.setX(testObj3.x()*5); + testObj2.setY(testObj3.y()*10); + hash2 = qHash(testObj2); + QVERIFY(hash2 != hash3); +} + +QTEST_APPLESS_MAIN(tst_QGeoTileSpec) + +#include "tst_qgeotilespec.moc" + + diff --git a/tests/auto/qmlinterface/data/TestAddress.qml b/tests/auto/qmlinterface/data/TestAddress.qml new file mode 100644 index 0000000..8d646a6 --- /dev/null +++ b/tests/auto/qmlinterface/data/TestAddress.qml @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtPositioning 5.5 + +Address { + city: "Brisbane" + country: "Australia" + countryCode: "AU" + postalCode: "4000" + state: "Queensland" + street: "123 Fake Street" +} diff --git a/tests/auto/qmlinterface/data/TestCategory.qml b/tests/auto/qmlinterface/data/TestCategory.qml new file mode 100644 index 0000000..d6ac2e4 --- /dev/null +++ b/tests/auto/qmlinterface/data/TestCategory.qml @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtLocation 5.3 + +Category { + name: "Test category" + categoryId: "test-category-id" +} diff --git a/tests/auto/qmlinterface/data/TestContactDetail.qml b/tests/auto/qmlinterface/data/TestContactDetail.qml new file mode 100644 index 0000000..7d76ff2 --- /dev/null +++ b/tests/auto/qmlinterface/data/TestContactDetail.qml @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtLocation 5.3 + +ContactDetail { + label: "Test Contact Detail" + value: "Test contact detail value" +} diff --git a/tests/auto/qmlinterface/data/TestIcon.qml b/tests/auto/qmlinterface/data/TestIcon.qml new file mode 100644 index 0000000..6df8077 --- /dev/null +++ b/tests/auto/qmlinterface/data/TestIcon.qml @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtLocation 5.3 + +Icon { + Component.onCompleted: { + parameters.singleUrl = "http://www.example.com/test-icon.png" + } +} diff --git a/tests/auto/qmlinterface/data/TestLocation.qml b/tests/auto/qmlinterface/data/TestLocation.qml new file mode 100644 index 0000000..6c3bb27 --- /dev/null +++ b/tests/auto/qmlinterface/data/TestLocation.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtPositioning 5.5 + +Location { + address: TestAddress { } +// TODO:unsupported syntax for now +// boundingBox { +// center { +// longitude: 10.0 +// latitude: 20.0 +// altitude: 30.0 +// } +// height: 30.0 +// width: 40.0 +// } + boundingBox : QtPositioning.rectangle(QtPositioning.coordinate(20,10, 30),40.0,30) + coordinate { + longitude: 10.0 + latitude: 20.0 + altitude: 30.0 + } +} diff --git a/tests/auto/qmlinterface/data/TestPlace.qml b/tests/auto/qmlinterface/data/TestPlace.qml new file mode 100644 index 0000000..7b42bf3 --- /dev/null +++ b/tests/auto/qmlinterface/data/TestPlace.qml @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtLocation 5.6 + +Place { + name: "Test Place" + placeId: "test-place-id" + attribution: "Place data by Foo" + categories: [ + Category { + name: "Test category 1" + categoryId: "test-category-id-1" + }, + Category { + name: "Test category 2" + categoryId: "test-category-id-2" + } + ] + location: TestLocation { } + ratings: TestRatings { } + icon: TestIcon { } + supplier: TestSupplier { } + visibility: Place.PrivateVisibility +} diff --git a/tests/auto/qmlinterface/data/TestPlaceAttribute.qml b/tests/auto/qmlinterface/data/TestPlaceAttribute.qml new file mode 100644 index 0000000..07cec51 --- /dev/null +++ b/tests/auto/qmlinterface/data/TestPlaceAttribute.qml @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtLocation 5.3 + +PlaceAttribute { + label: "Test Attribute" + text: "Test attribute text" +} diff --git a/tests/auto/qmlinterface/data/TestRatings.qml b/tests/auto/qmlinterface/data/TestRatings.qml new file mode 100644 index 0000000..6e115fe --- /dev/null +++ b/tests/auto/qmlinterface/data/TestRatings.qml @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtLocation 5.3 + +Ratings { + average: 3.5 + maximum: 5.0 + count: 10 +} diff --git a/tests/auto/qmlinterface/data/TestSupplier.qml b/tests/auto/qmlinterface/data/TestSupplier.qml new file mode 100644 index 0000000..32b4b0f --- /dev/null +++ b/tests/auto/qmlinterface/data/TestSupplier.qml @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtLocation 5.3 + +Supplier { + name: "Test supplier" + supplierId: "test-supplier-id" + url: "http://www.example.com/test-supplier" + icon: TestIcon { } +} diff --git a/tests/auto/qmlinterface/data/TestUser.qml b/tests/auto/qmlinterface/data/TestUser.qml new file mode 100644 index 0000000..062d4b2 --- /dev/null +++ b/tests/auto/qmlinterface/data/TestUser.qml @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtLocation 5.3 + +User { + name: "Test User" + userId: "test-user-id" +} diff --git a/tests/auto/qmlinterface/qmlinterface.pro b/tests/auto/qmlinterface/qmlinterface.pro new file mode 100644 index 0000000..9f1acad --- /dev/null +++ b/tests/auto/qmlinterface/qmlinterface.pro @@ -0,0 +1,26 @@ +QT += location qml testlib + +#QT -= gui + +TARGET = tst_qmlinterface +CONFIG += testcase +CONFIG -= app_bundle + +TEMPLATE = app + + +SOURCES += tst_qmlinterface.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" + +OTHER_FILES += \ + data/TestCategory.qml \ + data/TestAddress.qml \ + data/TestLocation.qml \ + data/TestPlace.qml \ + data/TestIcon.qml \ + data/TestRatings.qml \ + data/TestSupplier.qml \ + data/TestUser.qml \ + data/TestPlaceAttribute.qml \ + data/TestContactDetail.qml + diff --git a/tests/auto/qmlinterface/tst_qmlinterface.cpp b/tests/auto/qmlinterface/tst_qmlinterface.cpp new file mode 100644 index 0000000..11fc3c1 --- /dev/null +++ b/tests/auto/qmlinterface/tst_qmlinterface.cpp @@ -0,0 +1,353 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class tst_qmlinterface : public QObject +{ + Q_OBJECT + +public: + tst_qmlinterface(); + +private Q_SLOTS: + void testAddress(); + void testLocation(); + void testCategory(); + void testIcon(); + void testRatings(); + void testSupplier(); + void testUser(); + void testPlaceAttribute(); + void testContactDetail(); + void testPlace(); + +private: + QGeoCoordinate m_coordinate; + QGeoAddress m_address; + QGeoRectangle m_rectangle; + QGeoLocation m_location; + QPlaceCategory m_category; + QPlaceIcon m_icon; + QPlaceRatings m_ratings; + QPlaceSupplier m_supplier; + QPlaceUser m_user; + QPlaceAttribute m_placeAttribute; + QPlaceContactDetail m_contactDetail; + QList m_categories; + QPlace m_place; +}; + +tst_qmlinterface::tst_qmlinterface() +{ + m_coordinate.setLongitude(10.0); + m_coordinate.setLatitude(20.0); + m_coordinate.setAltitude(30.0); + + m_address.setCity(QStringLiteral("Brisbane")); + m_address.setCountry(QStringLiteral("Australia")); + m_address.setCountryCode(QStringLiteral("AU")); + m_address.setPostalCode(QStringLiteral("4000")); + m_address.setState(QStringLiteral("Queensland")); + m_address.setStreet(QStringLiteral("123 Fake Street")); + + m_rectangle.setCenter(m_coordinate); + m_rectangle.setHeight(30.0); + m_rectangle.setWidth(40.0); + + m_location.setAddress(m_address); + m_location.setBoundingBox(m_rectangle); + m_location.setCoordinate(m_coordinate); + + m_category.setName(QStringLiteral("Test category")); + m_category.setCategoryId(QStringLiteral("test-category-id")); + + QVariantMap iconParams; + iconParams.insert(QPlaceIcon::SingleUrl, QUrl(QStringLiteral("http://www.example.com/test-icon.png"))); + m_icon.setParameters(iconParams); + + m_ratings.setAverage(3.5); + m_ratings.setMaximum(5.0); + m_ratings.setCount(10); + + m_supplier.setName(QStringLiteral("Test supplier")); + m_supplier.setUrl(QUrl(QStringLiteral("http://www.example.com/test-supplier"))); + m_supplier.setSupplierId(QStringLiteral("test-supplier-id")); + m_supplier.setIcon(m_icon); + + m_user.setName(QStringLiteral("Test User")); + m_user.setUserId(QStringLiteral("test-user-id")); + + m_placeAttribute.setLabel(QStringLiteral("Test Attribute")); + m_placeAttribute.setText(QStringLiteral("Test attribute text")); + + m_contactDetail.setLabel(QStringLiteral("Test Contact Detail")); + m_contactDetail.setValue(QStringLiteral("Test contact detail value")); + + QPlaceCategory category; + category.setName(QStringLiteral("Test category 1")); + category.setCategoryId(QStringLiteral("test-category-id-1")); + m_categories.append(category); + category.setName(QStringLiteral("Test category 2")); + category.setCategoryId(QStringLiteral("test-category-id-2")); + m_categories.append(category); + + m_place.setName(QStringLiteral("Test Place")); + m_place.setPlaceId(QStringLiteral("test-place-id")); + m_place.setAttribution(QStringLiteral("Place data by Foo")); + m_place.setCategories(m_categories); + m_place.setLocation(m_location); + m_place.setRatings(m_ratings); + m_place.setIcon(m_icon); + m_place.setSupplier(m_supplier); + m_place.setVisibility(QLocation::PrivateVisibility); +} + +void tst_qmlinterface::testAddress() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestAddress.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QGeoAddress address = qmlObject->property("address").value(); + + QCOMPARE(address, m_address); + + qmlObject->setProperty("address", QVariant::fromValue(QGeoAddress())); + + QVERIFY(qmlObject->property("city").toString().isEmpty()); + QVERIFY(qmlObject->property("country").toString().isEmpty()); + QVERIFY(qmlObject->property("countryCode").toString().isEmpty()); + QVERIFY(qmlObject->property("postalCode").toString().isEmpty()); + QVERIFY(qmlObject->property("state").toString().isEmpty()); + QVERIFY(qmlObject->property("street").toString().isEmpty()); + + delete qmlObject; +} + +void tst_qmlinterface::testLocation() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestLocation.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QGeoLocation location = qmlObject->property("location").value(); + + QCOMPARE(location, m_location); + + qmlObject->setProperty("location", QVariant::fromValue(QGeoLocation())); + + QCOMPARE(qmlObject->property("address").value(), QGeoAddress()); + QCOMPARE(qmlObject->property("boundingBox").value(), QGeoRectangle()); + QCOMPARE(qmlObject->property("coordinate").value(), QGeoCoordinate()); + + delete qmlObject; +} + +void tst_qmlinterface::testCategory() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestCategory.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QPlaceCategory category = qmlObject->property("category").value(); + + QCOMPARE(category, m_category); + + qmlObject->setProperty("category", QVariant::fromValue(QPlaceCategory())); + + QVERIFY(qmlObject->property("name").toString().isEmpty()); + QVERIFY(qmlObject->property("categoryId").toString().isEmpty()); + + delete qmlObject; +} + +void tst_qmlinterface::testIcon() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestIcon.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QPlaceIcon icon = qmlObject->property("icon").value(); + + QCOMPARE(icon, m_icon); + + qmlObject->setProperty("icon", QVariant::fromValue(QPlaceIcon())); + + QVERIFY(!qmlObject->property("fullUrl").toUrl().isValid()); + + delete qmlObject; +} + +void tst_qmlinterface::testRatings() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestRatings.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QPlaceRatings ratings = qmlObject->property("ratings").value(); + + QCOMPARE(ratings, m_ratings); + + qmlObject->setProperty("ratings", QVariant::fromValue(QPlaceRatings())); + + QCOMPARE(qmlObject->property("average").value(), 0.0); + QCOMPARE(qmlObject->property("maximum").value(), 0.0); + QCOMPARE(qmlObject->property("average").toInt(), 0); + + delete qmlObject; +} + +void tst_qmlinterface::testSupplier() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestSupplier.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QPlaceSupplier supplier = qmlObject->property("supplier").value(); + + QCOMPARE(supplier, m_supplier); + + qmlObject->setProperty("supplier", QVariant::fromValue(QPlaceSupplier())); + + QVERIFY(qmlObject->property("name").toString().isEmpty()); + QVERIFY(!qmlObject->property("url").toUrl().isValid()); + QVERIFY(qmlObject->property("supplierId").toString().isEmpty()); + QCOMPARE(qmlObject->property("icon").value(), QPlaceIcon()); + + delete qmlObject; +} + +void tst_qmlinterface::testUser() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestUser.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QPlaceUser user = qmlObject->property("user").value(); + + QCOMPARE(user, m_user); + + qmlObject->setProperty("user", QVariant::fromValue(QPlaceUser())); + + QVERIFY(qmlObject->property("name").toString().isEmpty()); + QVERIFY(qmlObject->property("userId").toString().isEmpty()); + + delete qmlObject; +} + +void tst_qmlinterface::testPlaceAttribute() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestPlaceAttribute.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QPlaceAttribute placeAttribute = qmlObject->property("attribute").value(); + + QCOMPARE(placeAttribute, m_placeAttribute); + + qmlObject->setProperty("attribute", QVariant::fromValue(QPlaceAttribute())); + + QVERIFY(qmlObject->property("label").toString().isEmpty()); + QVERIFY(qmlObject->property("text").toString().isEmpty()); + + delete qmlObject; +} + +void tst_qmlinterface::testContactDetail() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestContactDetail.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QPlaceContactDetail contactDetail = qmlObject->property("contactDetail").value(); + + QCOMPARE(contactDetail, m_contactDetail); + + qmlObject->setProperty("contactDetail", QVariant::fromValue(QPlaceContactDetail())); + + QVERIFY(qmlObject->property("label").toString().isEmpty()); + QVERIFY(qmlObject->property("value").toString().isEmpty()); + + delete qmlObject; +} + +void tst_qmlinterface::testPlace() +{ + QQmlEngine engine; + QQmlComponent component(&engine, SRCDIR "data/TestPlace.qml"); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QObject *qmlObject = component.create(); + + QPlace place = qmlObject->property("place").value(); + + QCOMPARE(place, m_place); + + qmlObject->setProperty("place", QVariant::fromValue(QPlace())); + + QVERIFY(qmlObject->property("name").toString().isEmpty()); + QVERIFY(qmlObject->property("placeId").toString().isEmpty()); + QVERIFY(qmlObject->property("attribution").toString().isEmpty()); + QQmlListReference categories(qmlObject, "categories", &engine); + QCOMPARE(categories.count(), 0); + QCOMPARE(qmlObject->property("location").value(), QGeoLocation()); + QCOMPARE(qmlObject->property("ratings").value(), QPlaceRatings()); + QCOMPARE(qmlObject->property("icon").value(), QPlaceIcon()); + QCOMPARE(qmlObject->property("supplier").value(), QPlaceSupplier()); + + delete qmlObject; +} + +QTEST_MAIN(tst_qmlinterface) + +#include "tst_qmlinterface.moc" diff --git a/tests/auto/qnmeapositioninfosource/dummynmeapositioninfosource/dummynmeapositioninfosource.pro b/tests/auto/qnmeapositioninfosource/dummynmeapositioninfosource/dummynmeapositioninfosource.pro new file mode 100644 index 0000000..261992a --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/dummynmeapositioninfosource/dummynmeapositioninfosource.pro @@ -0,0 +1,23 @@ +TEMPLATE = app +CONFIG+=testcase +QT += network positioning testlib +TARGET = tst_dummynmeapositioninfosource + +INCLUDEPATH += .. + +HEADERS += ../../utils/qlocationtestutils_p.h \ + ../../qgeopositioninfosource/testqgeopositioninfosource_p.h \ + ../qnmeapositioninfosourceproxyfactory.h + +SOURCES += ../../utils/qlocationtestutils.cpp \ + ../../qgeopositioninfosource/testqgeopositioninfosource.cpp \ + ../qnmeapositioninfosourceproxyfactory.cpp \ + tst_dummynmeapositioninfosource.cpp + +# This test relies on a working local QTcpSocket(Server). When the CI is under +# heavy load the socket code cannot establish a connection which leads to flaky +# test results. We make this test insiginficant as there is currently no known +# solution to this problem. On the positive side QNmeaPositionInfoSource +# does not have a platform specific implementation. Other platforms should provide +# a close enough test approximation. +win32:CONFIG+=insignificant_test diff --git a/tests/auto/qnmeapositioninfosource/dummynmeapositioninfosource/tst_dummynmeapositioninfosource.cpp b/tests/auto/qnmeapositioninfosource/dummynmeapositioninfosource/tst_dummynmeapositioninfosource.cpp new file mode 100644 index 0000000..4468f91 --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/dummynmeapositioninfosource/tst_dummynmeapositioninfosource.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include "qnmeapositioninfosourceproxyfactory.h" +#include "../qgeopositioninfosource/testqgeopositioninfosource_p.h" +#include "../utils/qlocationtestutils_p.h" + +#include +#include +#include + +Q_DECLARE_METATYPE(QNmeaPositionInfoSource::UpdateMode) +Q_DECLARE_METATYPE(QGeoPositionInfo) + +class DummyNmeaPositionInfoSource : public QNmeaPositionInfoSource +{ + Q_OBJECT + +public: + DummyNmeaPositionInfoSource(QNmeaPositionInfoSource::UpdateMode mode, QObject *parent = 0); + +protected: + virtual bool parsePosInfoFromNmeaData(const char *data, + int size, + QGeoPositionInfo *posInfo, + bool *hasFix); + +private: + int callCount; +}; + +DummyNmeaPositionInfoSource::DummyNmeaPositionInfoSource(QNmeaPositionInfoSource::UpdateMode mode, QObject *parent) : + QNmeaPositionInfoSource(mode, parent), + callCount(0) +{ +} + +bool DummyNmeaPositionInfoSource::parsePosInfoFromNmeaData(const char* data, + int size, + QGeoPositionInfo *posInfo, + bool *hasFix) +{ + Q_UNUSED(data); + Q_UNUSED(size); + + posInfo->setCoordinate(QGeoCoordinate(callCount * 1.0, callCount * 1.0, callCount * 1.0)); + posInfo->setTimestamp(QDateTime::currentDateTime().toUTC()); + *hasFix = true; + ++callCount; + + return true; +} + +class tst_DummyNmeaPositionInfoSource : public QObject +{ + Q_OBJECT + +public: + tst_DummyNmeaPositionInfoSource(); + +private slots: + void initTestCase(); + void testOverloadedParseFunction(); +}; + + +tst_DummyNmeaPositionInfoSource::tst_DummyNmeaPositionInfoSource() {} + +void tst_DummyNmeaPositionInfoSource::initTestCase() +{ + qRegisterMetaType(); +} + +void tst_DummyNmeaPositionInfoSource::testOverloadedParseFunction() +{ + DummyNmeaPositionInfoSource source(QNmeaPositionInfoSource::RealTimeMode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spy(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + + QGeoPositionInfo pos; + + proxy->source()->startUpdates(); + + proxy->feedBytes(QString("The parser converts\n").toLatin1()); + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 1), 10000); + pos = spy.at(0).at(0).value(); + + QVERIFY((pos.coordinate().latitude() == 0.0) + && (pos.coordinate().longitude() == 0.0) + && (pos.coordinate().altitude() == 0.0)); + + spy.clear(); + + proxy->feedBytes(QString("any data it receives\n").toLatin1()); + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 1), 10000); + pos = spy.at(0).at(0).value(); + + QVERIFY((pos.coordinate().latitude() == 1.0) + && (pos.coordinate().longitude() == 1.0) + && (pos.coordinate().altitude() == 1.0)); + + spy.clear(); + + proxy->feedBytes(QString("into positions\n").toLatin1()); + + QTRY_VERIFY_WITH_TIMEOUT((spy.count() == 1), 10000); + pos = spy.at(0).at(0).value(); + + QVERIFY((pos.coordinate().latitude() == 2.0) + && (pos.coordinate().longitude() == 2.0) + && (pos.coordinate().altitude() == 2.0)); + + spy.clear(); +} + +#include "tst_dummynmeapositioninfosource.moc" + +QTEST_GUILESS_MAIN(tst_DummyNmeaPositionInfoSource); diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource.pro b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource.pro new file mode 100644 index 0000000..8c168d5 --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs +SUBDIRS += \ + dummynmeapositioninfosource \ + qnmeapositioninfosource_realtime \ + qnmeapositioninfosource_simulation \ + qnmeapositioninfosource_realtime_generic \ + qnmeapositioninfosource_simulation_generic + diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime/qnmeapositioninfosource_realtime.pro b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime/qnmeapositioninfosource_realtime.pro new file mode 100644 index 0000000..2b93cc2 --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime/qnmeapositioninfosource_realtime.pro @@ -0,0 +1,25 @@ +TEMPLATE = app +CONFIG+=testcase +QT += network positioning testlib +TARGET = tst_qnmeapositioninfosource_realtime + +INCLUDEPATH += .. + +HEADERS += ../../utils/qlocationtestutils_p.h \ + ../../qgeopositioninfosource/testqgeopositioninfosource_p.h \ + ../qnmeapositioninfosourceproxyfactory.h \ + ../tst_qnmeapositioninfosource.h + +SOURCES += ../../utils/qlocationtestutils.cpp \ + ../../qgeopositioninfosource/testqgeopositioninfosource.cpp \ + ../qnmeapositioninfosourceproxyfactory.cpp \ + ../tst_qnmeapositioninfosource.cpp \ + tst_qnmeapositioninfosource_realtime.cpp + +# This test relies on a working local QTcpSocket(Server). When the CI is under +# heavy load the socket code cannot establish a connection which leads to flaky +# test results. We make this test insiginficant as there is currently no known +# solution to this problem. On the positive side QNmeaPositionInfoSource +# does not have a platform specific implementation. Other platforms should provide +# a close enough test approximation. +win32:CONFIG+=insignificant_test diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime/tst_qnmeapositioninfosource_realtime.cpp b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime/tst_qnmeapositioninfosource_realtime.cpp new file mode 100644 index 0000000..423f657 --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime/tst_qnmeapositioninfosource_realtime.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include "tst_qnmeapositioninfosource.h" + +class tst_QNmeaPositionInfoSource_RealTime : public tst_QNmeaPositionInfoSource +{ + Q_OBJECT + +public: + tst_QNmeaPositionInfoSource_RealTime() + : tst_QNmeaPositionInfoSource(QNmeaPositionInfoSource::RealTimeMode) {} +}; + +#include "tst_qnmeapositioninfosource_realtime.moc" + +QTEST_GUILESS_MAIN(tst_QNmeaPositionInfoSource_RealTime); diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime_generic/qnmeapositioninfosource_realtime_generic.pro b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime_generic/qnmeapositioninfosource_realtime_generic.pro new file mode 100644 index 0000000..068289b --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime_generic/qnmeapositioninfosource_realtime_generic.pro @@ -0,0 +1,28 @@ +TEMPLATE = app +CONFIG+=testcase +testcase.timeout = 400 # this test is slow +QT += network positioning testlib +TARGET = tst_qnmeapositioninfosource_realtime_generic + +INCLUDEPATH += .. + +HEADERS += ../../utils/qlocationtestutils_p.h \ + ../../qgeopositioninfosource/testqgeopositioninfosource_p.h \ + ../qnmeapositioninfosourceproxyfactory.h \ + ../tst_qnmeapositioninfosource.h + +SOURCES += ../../utils/qlocationtestutils.cpp \ + ../../qgeopositioninfosource/testqgeopositioninfosource.cpp \ + ../qnmeapositioninfosourceproxyfactory.cpp \ + ../tst_qnmeapositioninfosource.cpp \ + tst_qnmeapositioninfosource_realtime_generic.cpp + +CONFIG -= app_bundle + +# This test relies on a working local QTcpSocket(Server). When the CI is under +# heavy load the socket code cannot establish a connection which leads to flaky +# test results. We make this test insiginficant as there is currently no known +# solution to this problem. On the positive side QNmeaPositionInfoSource +# does not have a platform specific implementation. Other platforms should provide +# a close enough test approximation. +win32:CONFIG+=insignificant_test diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime_generic/tst_qnmeapositioninfosource_realtime_generic.cpp b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime_generic/tst_qnmeapositioninfosource_realtime_generic.cpp new file mode 100644 index 0000000..cedcd56 --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_realtime_generic/tst_qnmeapositioninfosource_realtime_generic.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include "tst_qnmeapositioninfosource.h" + +class tst_QNmeaPositionInfoSource_RealTime_Generic : public TestQGeoPositionInfoSource +{ + Q_OBJECT + +public: + tst_QNmeaPositionInfoSource_RealTime_Generic() + { + m_factory = new QNmeaPositionInfoSourceProxyFactory; + /* + * Set custom path since CI doesn't install test plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#endif + } + + ~tst_QNmeaPositionInfoSource_RealTime_Generic() + { + delete m_factory; + } + +protected: + QGeoPositionInfoSource *createTestSource() + { + QNmeaPositionInfoSource *source = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::RealTimeMode); + QNmeaPositionInfoSourceProxy *proxy = static_cast(m_factory->createProxy(source)); + Feeder *feeder = new Feeder(source); + feeder->start(proxy); + return source; + } + +private: + QNmeaPositionInfoSourceProxyFactory *m_factory; +}; + +#include "tst_qnmeapositioninfosource_realtime_generic.moc" + +QTEST_GUILESS_MAIN(tst_QNmeaPositionInfoSource_RealTime_Generic); diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation/qnmeapositioninfosource_simulation.pro b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation/qnmeapositioninfosource_simulation.pro new file mode 100644 index 0000000..1214d7e --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation/qnmeapositioninfosource_simulation.pro @@ -0,0 +1,25 @@ +TEMPLATE = app +CONFIG+=testcase +QT += network positioning testlib +TARGET = tst_qnmeapositioninfosource_simulation + +INCLUDEPATH += .. + +HEADERS += ../../utils/qlocationtestutils_p.h \ + ../../qgeopositioninfosource/testqgeopositioninfosource_p.h \ + ../qnmeapositioninfosourceproxyfactory.h \ + ../tst_qnmeapositioninfosource.h + +SOURCES += ../../utils/qlocationtestutils.cpp \ + ../../qgeopositioninfosource/testqgeopositioninfosource.cpp \ + ../qnmeapositioninfosourceproxyfactory.cpp \ + ../tst_qnmeapositioninfosource.cpp \ + tst_qnmeapositioninfosource_simulation.cpp + +# This test relies on a working local QTcpSocket(Server). When the CI is under +# heavy load the socket code cannot establish a connection which leads to flaky +# test results. We make this test insiginficant as there is currently no known +# solution to this problem. On the positive side QNmeaPositionInfoSource +# does not have a platform specific implementation. Other platforms should provide +# a close enough test approximation. +win32:CONFIG+=insignificant_test diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation/tst_qnmeapositioninfosource_simulation.cpp b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation/tst_qnmeapositioninfosource_simulation.cpp new file mode 100644 index 0000000..ffe5e1d --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation/tst_qnmeapositioninfosource_simulation.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include "tst_qnmeapositioninfosource.h" + +class tst_QNmeaPositionInfoSource_Simulation : public tst_QNmeaPositionInfoSource +{ + Q_OBJECT +public: + tst_QNmeaPositionInfoSource_Simulation() + : tst_QNmeaPositionInfoSource(QNmeaPositionInfoSource::SimulationMode) {} +}; + +#include "tst_qnmeapositioninfosource_simulation.moc" + +QTEST_GUILESS_MAIN(tst_QNmeaPositionInfoSource_Simulation); diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation_generic/qnmeapositioninfosource_simulation_generic.pro b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation_generic/qnmeapositioninfosource_simulation_generic.pro new file mode 100644 index 0000000..726a746 --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation_generic/qnmeapositioninfosource_simulation_generic.pro @@ -0,0 +1,28 @@ +TEMPLATE = app +CONFIG+=testcase +testcase.timeout = 400 # this test is slow +QT += network positioning testlib +TARGET = tst_qnmeapositioninfosource_simulation_generic + +INCLUDEPATH += .. + +HEADERS += ../../utils/qlocationtestutils_p.h \ + ../../qgeopositioninfosource/testqgeopositioninfosource_p.h \ + ../qnmeapositioninfosourceproxyfactory.h \ + ../tst_qnmeapositioninfosource.h + +SOURCES += ../../utils/qlocationtestutils.cpp \ + ../../qgeopositioninfosource/testqgeopositioninfosource.cpp \ + ../qnmeapositioninfosourceproxyfactory.cpp \ + ../tst_qnmeapositioninfosource.cpp \ + tst_qnmeapositioninfosource_simulation_generic.cpp + +CONFIG -= app_bundle + +# This test relies on a working local QTcpSocket(Server). When the CI is under +# heavy load the socket code cannot establish a connection which leads to flaky +# test results. We make this test insiginficant as there is currently no known +# solution to this problem. On the positive side QNmeaPositionInfoSource +# does not have a platform specific implementation. Other platforms should provide +# a close enough test approximation. +win32:CONFIG+=insignificant_test diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation_generic/tst_qnmeapositioninfosource_simulation_generic.cpp b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation_generic/tst_qnmeapositioninfosource_simulation_generic.cpp new file mode 100644 index 0000000..0d8f03c --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosource_simulation_generic/tst_qnmeapositioninfosource_simulation_generic.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include "tst_qnmeapositioninfosource.h" + +class tst_QNmeaPositionInfoSource_Simulation_Generic : public TestQGeoPositionInfoSource +{ + Q_OBJECT +public: + tst_QNmeaPositionInfoSource_Simulation_Generic() + { + /* + * Set custom path since CI doesn't install test plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#endif + } + +protected: + QGeoPositionInfoSource *createTestSource() + { + QNmeaPositionInfoSource *source = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::SimulationMode); + source->setDevice(new UnlimitedNmeaStream(source)); + return source; + } +}; + +#include "tst_qnmeapositioninfosource_simulation_generic.moc" + +QTEST_GUILESS_MAIN(tst_QNmeaPositionInfoSource_Simulation_Generic); diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.cpp b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.cpp new file mode 100644 index 0000000..756d027 --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnmeapositioninfosourceproxyfactory.h" +#include "../utils/qlocationtestutils_p.h" + +#include +#include +#include + + +QNmeaPositionInfoSourceProxy::QNmeaPositionInfoSourceProxy(QNmeaPositionInfoSource *source, QIODevice *outDevice) + : m_source(source), + m_outDevice(outDevice) +{ +} + +QNmeaPositionInfoSourceProxy::~QNmeaPositionInfoSourceProxy() +{ + m_outDevice->close(); + delete m_outDevice; +} + +QGeoPositionInfoSource *QNmeaPositionInfoSourceProxy::source() const +{ + return m_source; +} + +void QNmeaPositionInfoSourceProxy::feedUpdate(const QDateTime &dt) +{ + m_outDevice->write(QLocationTestUtils::createRmcSentence(dt).toLatin1()); +} + +void QNmeaPositionInfoSourceProxy::feedBytes(const QByteArray &bytes) +{ + m_outDevice->write(bytes); +} + + +QNmeaPositionInfoSourceProxyFactory::QNmeaPositionInfoSourceProxyFactory() + : m_server(new QTcpServer(this)) +{ + bool b = m_server->listen(QHostAddress::LocalHost); + Q_ASSERT(b); +} + +QNmeaPositionInfoSourceProxy *QNmeaPositionInfoSourceProxyFactory::createProxy(QNmeaPositionInfoSource *source) +{ + QTcpSocket *client = new QTcpSocket; + client->connectToHost(m_server->serverAddress(), m_server->serverPort()); + qDebug() << "listening on" << m_server->serverAddress() << m_server->serverPort(); + bool b = m_server->waitForNewConnection(15000); + if (!b) + qWarning() << "Server didin't receive new connection"; + b = client->waitForConnected(); + if (!b) + qWarning() << "Client could not connect to server"; + + //QNmeaPositionInfoSource *source = new QNmeaPositionInfoSource(m_mode); + QIODevice *device = m_server->nextPendingConnection(); + if (!device) + qWarning() << "Missing pending connection. Test is going to fail."; + else + qWarning() << "Received pending connection:" << device << b; + source->setDevice(device); + Q_ASSERT(source->device() != 0); + QNmeaPositionInfoSourceProxy *proxy = new QNmeaPositionInfoSourceProxy(source, client); + proxy->setParent(source); + return proxy; +} diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.h b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.h new file mode 100644 index 0000000..d740f9b --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNMEAPOSITIONINFOSOURCEPROXYFACTORY_H +#define QNMEAPOSITIONINFOSOURCEPROXYFACTORY_H + +#include + +#include + +QT_BEGIN_NAMESPACE +class QTcpServer; +class QIODevice; +class QNmeaPositionInfoSource; +QT_END_NAMESPACE + +class QNmeaPositionInfoSourceProxy : public QObject +{ + Q_OBJECT +public: + QNmeaPositionInfoSourceProxy(QNmeaPositionInfoSource *source, QIODevice *outDevice); + ~QNmeaPositionInfoSourceProxy(); + + QGeoPositionInfoSource *source() const; + + void feedUpdate(const QDateTime &dt); + + void feedBytes(const QByteArray &bytes); + + int updateIntervalErrorMargin() const { return 50; } + +private: + QNmeaPositionInfoSource *m_source; + QIODevice *m_outDevice; +}; + +class QNmeaPositionInfoSourceProxyFactory : public QObject +{ + Q_OBJECT +public: + QNmeaPositionInfoSourceProxyFactory(); + + // proxy is created as child of source + QNmeaPositionInfoSourceProxy *createProxy(QNmeaPositionInfoSource *source); + +private: + QTcpServer *m_server; +}; + +#endif diff --git a/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp new file mode 100644 index 0000000..8305dc1 --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp @@ -0,0 +1,573 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jolla Ltd. +** Contact: Aaron McCarthy +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/location + +#include "tst_qnmeapositioninfosource.h" + +#include + +#ifdef Q_OS_WIN + +// Windows seems to require longer timeouts and step length +// We override the standard QTestCase related macros + +#ifdef QTRY_COMPARE_WITH_TIMEOUT +#undef QTRY_COMPARE_WITH_TIMEOUT +#endif +#define QTRY_COMPARE_WITH_TIMEOUT(__expr, __expected, __timeout) \ +do { \ + const int __step = 100; \ + const int __timeoutValue = __timeout; \ + if ((__expr) != (__expected)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeoutValue && ((__expr) != (__expected)); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QCOMPARE(__expr, __expected); \ +} while (0) + +#ifdef QTRY_COMPARE +#undef QTRY_COMPARE +#endif +#define QTRY_COMPARE(__expr, __expected) QTRY_COMPARE_WITH_TIMEOUT(__expr, __expected, 10000) + +#endif + +tst_QNmeaPositionInfoSource::tst_QNmeaPositionInfoSource(QNmeaPositionInfoSource::UpdateMode mode, QObject *parent) + : QObject(parent), + m_mode(mode) +{ +} + +void tst_QNmeaPositionInfoSource::initTestCase() +{ + qRegisterMetaType(); + qRegisterMetaType(); +} + +void tst_QNmeaPositionInfoSource::constructor() +{ + QObject o; + QNmeaPositionInfoSource source(m_mode, &o); + QCOMPARE(source.updateMode(), m_mode); + QCOMPARE(source.parent(), &o); +} + +void tst_QNmeaPositionInfoSource::supportedPositioningMethods() +{ + QNmeaPositionInfoSource source(m_mode); + QCOMPARE(source.supportedPositioningMethods(), QNmeaPositionInfoSource::SatellitePositioningMethods); +} + +void tst_QNmeaPositionInfoSource::minimumUpdateInterval() +{ + QNmeaPositionInfoSource source(m_mode); + QCOMPARE(source.minimumUpdateInterval(), 100); +} + +void tst_QNmeaPositionInfoSource::userEquivalentRangeError() +{ + QNmeaPositionInfoSource source(m_mode); + QVERIFY(qIsNaN(source.userEquivalentRangeError())); + source.setUserEquivalentRangeError(5.1); + QVERIFY(qFuzzyCompare(source.userEquivalentRangeError(), 5.1)); +} + +void tst_QNmeaPositionInfoSource::setUpdateInterval_delayedUpdate() +{ + // If an update interval is set, and an update is not available at a + // particular interval, the source should emit the next update as soon + // as it becomes available + + QNmeaPositionInfoSource source(m_mode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spyUpdate(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + proxy->source()->setUpdateInterval(500); + proxy->source()->startUpdates(); + + QTest::qWait(600); + QDateTime now = QDateTime::currentDateTime(); + proxy->feedUpdate(now); + QTRY_COMPARE(spyUpdate.count(), 1); + + // should have gotten the update immediately, and not have needed to + // wait until the next interval + QVERIFY(now.time().msecsTo(QDateTime::currentDateTime().time()) < 200); +} + +void tst_QNmeaPositionInfoSource::lastKnownPosition() +{ + QNmeaPositionInfoSource source(m_mode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QCOMPARE(proxy->source()->lastKnownPosition(), QGeoPositionInfo()); + + // source may need requestUpdate() or startUpdates() to be called to + // trigger reading of data channel + QSignalSpy spyTimeout(proxy->source(), SIGNAL(updateTimeout())); + proxy->source()->requestUpdate(proxy->source()->minimumUpdateInterval()); + QTRY_COMPARE(spyTimeout.count(), 1); + + // If an update is received and startUpdates() or requestUpdate() hasn't + // been called, it should still be available through lastKnownPosition() + QDateTime dt = QDateTime::currentDateTime().toUTC(); + proxy->feedUpdate(dt); + QTRY_COMPARE(proxy->source()->lastKnownPosition().timestamp(), dt); + + QList dateTimes = createDateTimes(5); + for (int i=0; isource()->requestUpdate(); + proxy->feedUpdate(dateTimes[i]); + QTRY_COMPARE(proxy->source()->lastKnownPosition().timestamp(), dateTimes[i]); + } + + proxy->source()->startUpdates(); + dateTimes = createDateTimes(5); + for (int i=0; ifeedUpdate(dateTimes[i]); + QTRY_COMPARE(proxy->source()->lastKnownPosition().timestamp(), dateTimes[i]); + } +} + +void tst_QNmeaPositionInfoSource::beginWithBufferedData() +{ + // In SimulationMode, data stored in the QIODevice is read when + // startUpdates() or requestUpdate() is called. + // In RealTimeMode, all existing data in the QIODevice is ignored - + // only new data will be read. + + QFETCH(QList, dateTimes); + QFETCH(UpdateTriggerMethod, trigger); + + QByteArray bytes; + for (int i=0; i().timestamp(), dateTimes[i]); + } else if (trigger == RequestUpdatesMethod) { + QTRY_COMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).value().timestamp(), dateTimes.first()); + } + } +} + +void tst_QNmeaPositionInfoSource::beginWithBufferedData_data() +{ + QTest::addColumn >("dateTimes"); + QTest::addColumn("trigger"); + + QList dateTimes; + dateTimes << QDateTime::currentDateTime().toUTC(); + + QTest::newRow("startUpdates(), 1 update in buffer") << dateTimes << StartUpdatesMethod; + QTest::newRow("requestUpdate(), 1 update in buffer") << dateTimes << RequestUpdatesMethod; + + for (int i=1; i<3; i++) + dateTimes << dateTimes[0].addDays(i); + QTest::newRow("startUpdates(), multiple updates in buffer") << dateTimes << StartUpdatesMethod; + QTest::newRow("requestUpdate(), multiple updates in buffer") << dateTimes << RequestUpdatesMethod; +} + +void tst_QNmeaPositionInfoSource::startUpdates() +{ + QFETCH(QList, dateTimes); + + QNmeaPositionInfoSource source(m_mode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spyUpdate(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + proxy->source()->startUpdates(); + + for (int i=0; ifeedUpdate(dateTimes[i]); + QTRY_COMPARE(spyUpdate.count(), dateTimes.count()); +} + +void tst_QNmeaPositionInfoSource::startUpdates_data() +{ + QTest::addColumn >("dateTimes"); + + QTest::newRow("1 update") << createDateTimes(1); + QTest::newRow("2 updates") << createDateTimes(2); + QTest::newRow("10 updates") << createDateTimes(10); +} + +void tst_QNmeaPositionInfoSource::startUpdates_withTimeout() +{ + QNmeaPositionInfoSource source(m_mode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spyUpdate(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(proxy->source(), SIGNAL(updateTimeout())); + + proxy->source()->setUpdateInterval(1000); + proxy->source()->startUpdates(); + + QDateTime dt = QDateTime::currentDateTime().toUTC(); + + if (m_mode == QNmeaPositionInfoSource::SimulationMode) { + // the first sentence primes the simulation + proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt).toLatin1()); + proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addMSecs(10)).toLatin1()); + proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addMSecs(1100)).toLatin1()); + proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addMSecs(2200)).toLatin1()); + proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addSecs(9)).toLatin1()); + + QTime t; + t.start(); + + for (int j = 1; j < 4; ++j) { + QTRY_COMPARE(spyUpdate.count(), j); + QCOMPARE(spyTimeout.count(), 0); + int time = t.elapsed(); + QVERIFY((time > j*1000 - 300) && (time < j*1000 + 300)); + } + + spyUpdate.clear(); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() == 0) && (spyTimeout.count() == 1), 7500); + spyTimeout.clear(); + + QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.count() == 1) && (spyTimeout.count() == 0), 7500); + + } else { + // dt + 900 + QTRY_VERIFY(spyUpdate.count() == 0 && spyTimeout.count() == 0); + + proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addSecs(1)).toLatin1()); + // dt + 1200 + QTRY_VERIFY(spyUpdate.count() == 1 && spyTimeout.count() == 0); + spyUpdate.clear(); + + // dt + 1900 + QTRY_VERIFY(spyUpdate.count() == 0 && spyTimeout.count() == 0); + proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addSecs(2)).toLatin1()); + + // dt + 2200 + QTRY_VERIFY(spyUpdate.count() == 1 && spyTimeout.count() == 0); + spyUpdate.clear(); + + // dt + 2900 + QTRY_VERIFY(spyUpdate.count() == 0 && spyTimeout.count() == 0); + proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addSecs(3)).toLatin1()); + + // dt + 3200 + QTRY_VERIFY(spyUpdate.count() == 1 && spyTimeout.count() == 0); + spyUpdate.clear(); + + // dt + 6900 + QTRY_VERIFY(spyUpdate.count() == 0 && spyTimeout.count() == 1); + spyTimeout.clear(); + proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addSecs(7)).toLatin1()); + + // dt + 7200 + QTRY_VERIFY(spyUpdate.count() == 1 && spyTimeout.count() == 0); + spyUpdate.clear(); + } +} + +void tst_QNmeaPositionInfoSource::startUpdates_expectLatestUpdateOnly() +{ + // If startUpdates() is called and an interval has been set, if multiple' + // updates are in the buffer, only the latest update should be emitted + + QNmeaPositionInfoSource source(m_mode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spyUpdate(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + proxy->source()->setUpdateInterval(500); + proxy->source()->startUpdates(); + + QList dateTimes = createDateTimes(3); + for (int i=0; ifeedUpdate(dateTimes[i]); + + QTRY_COMPARE(spyUpdate.count(), 1); + QCOMPARE(spyUpdate[0][0].value().timestamp(), dateTimes.last()); +} + +void tst_QNmeaPositionInfoSource::startUpdates_waitForValidDateTime() +{ + // Tests that the class does not emit an update until it receives a + // sentences with a valid date *and* time. All sentences before this + // should be ignored, and any sentences received after this that do + // not have a date should use the known date. + + QFETCH(QByteArray, bytes); + QFETCH(QList, dateTimes); + QFETCH(QList, expectHorizontalAccuracy); + QFETCH(QList, expectVerticalAccuracy); + + QNmeaPositionInfoSource source(m_mode); + source.setUserEquivalentRangeError(5.1); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spy(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + proxy->source()->startUpdates(); + + proxy->feedBytes(bytes); + QTRY_COMPARE(spy.count(), dateTimes.count()); + + for (int i=0; i(); + + QCOMPARE(pInfo.timestamp(), dateTimes[i]); + + // Generated GGA/GSA sentences have hard coded HDOP of 3.5, which corrisponds to a + // horizontal accuracy of 35.7, for the user equivalent range error of 5.1 set above. + QCOMPARE(pInfo.hasAttribute(QGeoPositionInfo::HorizontalAccuracy), + expectHorizontalAccuracy[i]); + if (pInfo.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + QVERIFY(qFuzzyCompare(pInfo.attribute(QGeoPositionInfo::HorizontalAccuracy), 35.7)); + + // Generate GSA sentences have hard coded VDOP of 4.0, which corrisponds to a vertical + // accuracy of 40.8, for the user equivalent range error of 5.1 set above. + QCOMPARE(pInfo.hasAttribute(QGeoPositionInfo::VerticalAccuracy), + expectVerticalAccuracy[i]); + if (pInfo.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) + QVERIFY(qFuzzyCompare(pInfo.attribute(QGeoPositionInfo::VerticalAccuracy), 40.8)); + } +} + +void tst_QNmeaPositionInfoSource::startUpdates_waitForValidDateTime_data() +{ + QTest::addColumn("bytes"); + QTest::addColumn >("dateTimes"); + QTest::addColumn >("expectHorizontalAccuracy"); + QTest::addColumn >("expectVerticalAccuracy"); + + QDateTime dt = QDateTime::currentDateTime().toUTC(); + QByteArray bytes; + + // should only receive RMC sentence and the GGA sentence *after* it + bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(1).time()).toLatin1(); + bytes += QLocationTestUtils::createRmcSentence(dt.addSecs(2)).toLatin1(); + bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(3).time()).toLatin1(); + QTest::newRow("Feed GGA,RMC,GGA; expect RMC, second GGA only") + << bytes << (QList() << dt.addSecs(2) << dt.addSecs(3)) + << (QList() << true << true) + << (QList() << false << false); + + // should not receive ZDA (has no coordinates) but should get the GGA + // sentence after it since it got the date/time from ZDA + bytes.clear(); + bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(1).time()).toLatin1(); + bytes += QLocationTestUtils::createZdaSentence(dt.addSecs(2)).toLatin1(); + bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(3).time()).toLatin1(); + QTest::newRow("Feed GGA,ZDA,GGA; expect second GGA only") + << bytes << (QList() << dt.addSecs(3)) + << (QList() << true) + << (QList() << false); + + // Feed ZDA,GGA,GSA,GGA; expect vertical accuracy from second GGA. + bytes.clear(); + bytes += QLocationTestUtils::createZdaSentence(dt.addSecs(1)).toLatin1(); + bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(2).time()).toLatin1(); + bytes += QLocationTestUtils::createGsaSentence().toLatin1(); + bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(3).time()).toLatin1(); + QTest::newRow("Feed ZDA,GGA,GSA,GGA; expect vertical accuracy from second GGA") + << bytes << (QList() << dt.addSecs(2) << dt.addSecs(3)) + << (QList() << true << true) + << (QList() << false << true); + + if (m_mode == QNmeaPositionInfoSource::SimulationMode) { + // In sim m_mode, should ignore sentence with a date/time before the known date/time + // (in real time m_mode, everything is passed on regardless) + bytes.clear(); + bytes += QLocationTestUtils::createRmcSentence(dt.addSecs(1)).toLatin1(); + bytes += QLocationTestUtils::createRmcSentence(dt.addSecs(-2)).toLatin1(); + bytes += QLocationTestUtils::createRmcSentence(dt.addSecs(2)).toLatin1(); + QTest::newRow("Feed good RMC, RMC with bad date/time, good RMC; expect first and third RMC only") + << bytes << (QList() << dt.addSecs(1) << dt.addSecs(2)) + << (QList() << false << false) + << (QList() << false << false); + } +} + +void tst_QNmeaPositionInfoSource::requestUpdate_waitForValidDateTime() +{ + QFETCH(QByteArray, bytes); + QFETCH(QList, dateTimes); + + QNmeaPositionInfoSource source(m_mode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spy(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + proxy->source()->requestUpdate(); + + proxy->feedBytes(bytes); + QTRY_COMPARE(spy.count(), 1); + QCOMPARE(spy[0][0].value().timestamp(), dateTimes[0]); +} + +void tst_QNmeaPositionInfoSource::requestUpdate_waitForValidDateTime_data() +{ + startUpdates_waitForValidDateTime_data(); +} + +void tst_QNmeaPositionInfoSource::requestUpdate() +{ + QNmeaPositionInfoSource source(m_mode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spyUpdate(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(proxy->source(), SIGNAL(updateTimeout())); + QDateTime dt; + + proxy->source()->requestUpdate(100); + QTRY_COMPARE(spyTimeout.count(), 1); + spyTimeout.clear(); + + dt = QDateTime::currentDateTime().toUTC(); + proxy->feedUpdate(dt); + proxy->source()->requestUpdate(); + QTRY_COMPARE(spyUpdate.count(), 1); + QCOMPARE(spyUpdate[0][0].value().timestamp(), dt); + QCOMPARE(spyTimeout.count(), 0); + spyUpdate.clear(); + + // delay the update and expect it to be emitted after 300ms + dt = QDateTime::currentDateTime().toUTC(); + proxy->source()->requestUpdate(1000); + QTest::qWait(300); + proxy->feedUpdate(dt); + QTRY_COMPARE(spyUpdate.count(), 1); + QCOMPARE(spyUpdate[0][0].value().timestamp(), dt); + QCOMPARE(spyTimeout.count(), 0); + spyUpdate.clear(); + + // delay the update and expect updateTimeout() to be emitted + dt = QDateTime::currentDateTime().toUTC(); + proxy->source()->requestUpdate(500); + QTest::qWait(1000); + proxy->feedUpdate(dt); + QCOMPARE(spyTimeout.count(), 1); + QCOMPARE(spyUpdate.count(), 0); + spyUpdate.clear(); +} + +void tst_QNmeaPositionInfoSource::requestUpdate_after_start() +{ + QNmeaPositionInfoSource source(m_mode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spyUpdate(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + QSignalSpy spyTimeout(proxy->source(), SIGNAL(updateTimeout())); + + // Start updates with 500ms interval and requestUpdate() with 100ms + // timeout. Feed an update, and it should be emitted immediately due to + // the requestUpdate(). The update should not be emitted again after that + // (i.e. the startUpdates() interval should not cause it to be re-emitted). + + QDateTime dt = QDateTime::currentDateTime().toUTC(); + proxy->source()->setUpdateInterval(500); + proxy->source()->startUpdates(); + proxy->source()->requestUpdate(100); + proxy->feedUpdate(dt); + QTRY_COMPARE(spyUpdate.count(), 1); + QCOMPARE(spyUpdate[0][0].value().timestamp(), dt); + QCOMPARE(spyTimeout.count(), 0); + spyUpdate.clear(); + + // Update has been emitted for requestUpdate(), shouldn't be emitted for startUpdates() + QTRY_COMPARE_WITH_TIMEOUT(spyUpdate.count(), 0, 1000); +} + +void tst_QNmeaPositionInfoSource::testWithBadNmea() +{ + QFETCH(QByteArray, bytes); + QFETCH(QList, dateTimes); + QFETCH(UpdateTriggerMethod, trigger); + + QNmeaPositionInfoSource source(m_mode); + QNmeaPositionInfoSourceProxyFactory factory; + QNmeaPositionInfoSourceProxy *proxy = static_cast(factory.createProxy(&source)); + + QSignalSpy spy(proxy->source(), SIGNAL(positionUpdated(QGeoPositionInfo))); + if (trigger == StartUpdatesMethod) + proxy->source()->startUpdates(); + else + proxy->source()->requestUpdate(); + + proxy->feedBytes(bytes); + QTRY_COMPARE(spy.count(), dateTimes.count()); + for (int i=0; i().timestamp(), dateTimes[i]); +} + +void tst_QNmeaPositionInfoSource::testWithBadNmea_data() +{ + QTest::addColumn("bytes"); + QTest::addColumn >("dateTimes"); + QTest::addColumn("trigger"); + + QDateTime firstDateTime = QDateTime::currentDateTime().toUTC(); + QByteArray bad = QLocationTestUtils::createRmcSentence(firstDateTime.addSecs(1)).toLatin1(); + bad = bad.mid(bad.length()/2); + QDateTime lastDateTime = firstDateTime.addSecs(2); + + QByteArray bytes; + bytes += QLocationTestUtils::createRmcSentence(firstDateTime).toLatin1(); + bytes += bad; + bytes += QLocationTestUtils::createRmcSentence(lastDateTime).toLatin1(); + QTest::newRow("requestUpdate(), bad second sentence") << bytes + << (QList() << firstDateTime) << RequestUpdatesMethod; + QTest::newRow("startUpdates(), bad second sentence") << bytes + << (QList() << firstDateTime << lastDateTime) << StartUpdatesMethod; +} diff --git a/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.h b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.h new file mode 100644 index 0000000..844dfba --- /dev/null +++ b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.h @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnmeapositioninfosourceproxyfactory.h" +#include "../qgeopositioninfosource/testqgeopositioninfosource_p.h" +#include "../utils/qlocationtestutils_p.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE +Q_DECLARE_METATYPE(QNmeaPositionInfoSource::UpdateMode) +Q_DECLARE_METATYPE(QGeoPositionInfo) +Q_DECLARE_METATYPE(QList) + +class tst_QNmeaPositionInfoSource : public QObject +{ + Q_OBJECT + +public: + enum UpdateTriggerMethod + { + StartUpdatesMethod, + RequestUpdatesMethod + }; + + tst_QNmeaPositionInfoSource(QNmeaPositionInfoSource::UpdateMode mode, QObject *parent = 0); + +private: + QList createDateTimes(int count) const + { + QList dateTimes; + QDateTime dt = QDateTime::currentDateTime().toUTC(); + int interval = 100; + for (int i=0; isetInterval(proxy->source()->minimumUpdateInterval()*2); + timer->start(); + } + +public slots: + void timeout() + { + m_proxy->feedBytes(QLocationTestUtils::createRmcSentence(QDateTime::currentDateTime()).toLatin1()); + } + +private: + QNmeaPositionInfoSourceProxy *m_proxy; +}; + +//--------------------------------------------------- + + +class UnlimitedNmeaStream : public QIODevice +{ + Q_OBJECT + +public: + UnlimitedNmeaStream(QObject *parent) : QIODevice(parent) {} + +protected: + qint64 readData(char *data, qint64 maxSize) + { + QByteArray bytes = QLocationTestUtils::createRmcSentence(QDateTime::currentDateTime()).toLatin1(); + qint64 sz = qMin(qint64(bytes.size()), maxSize); + memcpy(data, bytes.constData(), sz); + return sz; + } + + qint64 writeData(const char *, qint64) + { + return -1; + } + + qint64 bytesAvailable() const + { + return 1024 + QIODevice::bytesAvailable(); + } +}; diff --git a/tests/auto/qplace/qplace.pro b/tests/auto/qplace/qplace.pro new file mode 100644 index 0000000..290c831 --- /dev/null +++ b/tests/auto/qplace/qplace.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplace + +SOURCES += tst_qplace.cpp + +QT += location testlib diff --git a/tests/auto/qplace/tst_qplace.cpp b/tests/auto/qplace/tst_qplace.cpp new file mode 100644 index 0000000..bc86599 --- /dev/null +++ b/tests/auto/qplace/tst_qplace.cpp @@ -0,0 +1,681 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_Place : public QObject +{ + Q_OBJECT + +public: + tst_Place(); + +private Q_SLOTS: + void constructorTest(); + void categoriesTest(); + void detailsFetchedTest(); + void locationTest(); + void ratingTest(); + void supplierTest(); + void imageContentTest(); + void reviewContentTest(); + void editorialContentTest(); + void totalContentCountTest(); + void totalContentCountTest_data(); + void nameTest(); + void placeIdTest(); + void attributionTest(); + void contactDetailsTest(); + void primaryPhoneTest(); + void primaryFaxTest(); + void primaryEmailTest(); + void primaryWebsiteTest(); + void operatorsTest(); + void extendedAttributeTest(); + void visibilityTest(); + void isEmptyTest(); +}; + +tst_Place::tst_Place() +{ +} + +void tst_Place::constructorTest() +{ + QPlace testObj; + testObj.setPlaceId("testId"); + QPlaceAttribute paymentMethods; + paymentMethods.setLabel("Payment methods"); + paymentMethods.setText("Visa"); + testObj.setExtendedAttribute(QStringLiteral("paymentMethods"), paymentMethods); + QGeoLocation loc; + loc.setCoordinate(QGeoCoordinate(10,20)); + testObj.setLocation(loc); + QPlace *testObjPtr = new QPlace(testObj); + + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + + delete testObjPtr; +} + +void tst_Place::nameTest() +{ + QPlace testObj; + QVERIFY2(testObj.name() == QString(), "Wrong default value"); + testObj.setName("testText"); + QVERIFY2(testObj.name() == "testText", "Wrong value returned"); +} + +void tst_Place::placeIdTest() +{ + QPlace testObj; + QVERIFY2(testObj.placeId() == QString(), "Wrong default value"); + testObj.setPlaceId("testText"); + QVERIFY2(testObj.placeId() == "testText", "Wrong value returned"); +} + +void tst_Place::totalContentCountTest() +{ + QFETCH(QPlaceContent::Type, contentType); + QPlace testObj; + QVERIFY2(testObj.totalContentCount(contentType) == 0, "Wrong default value"); + testObj.setTotalContentCount(contentType, 50); + QVERIFY2(testObj.totalContentCount(contentType) == 50, "Wrong value returned"); + + testObj.setTotalContentCount(contentType,0); + QVERIFY2(testObj.totalContentCount(contentType) == 0, "Wrong value returned"); +} + +void tst_Place::totalContentCountTest_data() +{ + QTest::addColumn("contentType"); + QTest::newRow("Image content") << QPlaceContent::ImageType; + QTest::newRow("Editoral content") << QPlaceContent::EditorialType; + QTest::newRow("Review content") << QPlaceContent::ReviewType; +} + +void tst_Place::ratingTest() +{ + QPlace testObj; + QVERIFY2(testObj.ratings() == QPlaceRatings(), "Wrong default value"); + QPlaceRatings obj; + obj.setCount(10); + testObj.setRatings(obj); + QVERIFY2(testObj.ratings() == obj, "Wrong value returned"); +} + +void tst_Place::locationTest() +{ + QPlace testObj; + QVERIFY2(testObj.location() == QGeoLocation(), "Wrong default value"); + QGeoLocation obj; + obj.setCoordinate(QGeoCoordinate(10,20)); + testObj.setLocation(obj); + QVERIFY2(testObj.location() == obj, "Wrong value returned"); +} + +void tst_Place::detailsFetchedTest() +{ + QPlace testPlace; + QVERIFY2(testPlace.detailsFetched() == false, "Wrong default value"); + testPlace.setDetailsFetched(true); + QVERIFY2(testPlace.detailsFetched() == true, "Wrong value returned"); + testPlace.setDetailsFetched(false); + QVERIFY2(testPlace.detailsFetched() == false, "Wrong value returned"); +} + +void tst_Place::imageContentTest() +{ + QPlace place; + QVERIFY2(place.content(QPlaceContent::ImageType).count() ==0,"Wrong default value"); + + QPlaceImage dummyImage; + dummyImage.setUrl(QUrl("www.dummy.one")); + + QPlaceImage dummyImage2; + dummyImage2.setUrl(QUrl("www.dummy.two")); + + QPlaceImage dummyImage3; + dummyImage3.setUrl(QUrl("www.dummy.three")); + + QPlaceContent::Collection imageCollection; + imageCollection.insert(0,dummyImage); + imageCollection.insert(1, dummyImage2); + imageCollection.insert(2, dummyImage3); + + place.setContent(QPlaceContent::ImageType, imageCollection); + QPlaceContent::Collection retrievedCollection = place.content(QPlaceContent::ImageType); + + QCOMPARE(retrievedCollection.count(), 3); + QCOMPARE(QPlaceImage(retrievedCollection.value(0)), dummyImage); + QCOMPARE(QPlaceImage(retrievedCollection.value(1)), dummyImage2); + QCOMPARE(QPlaceImage(retrievedCollection.value(2)), dummyImage3); + + //replace the second and insert a sixth image + //indexes 4 and 5 are "missing" + QPlaceImage dummyImage2New; + dummyImage2.setUrl(QUrl("www.dummy.two.new")); + + QPlaceImage dummyImage6; + dummyImage6.setUrl(QUrl("www.dummy.six")); + + imageCollection.clear(); + imageCollection.insert(1, dummyImage2New); + imageCollection.insert(5, dummyImage6); + place.insertContent(QPlaceContent::ImageType, imageCollection); + + retrievedCollection = place.content(QPlaceContent::ImageType); + QCOMPARE(retrievedCollection.count(), 4); + QCOMPARE(QPlaceImage(retrievedCollection.value(0)), dummyImage); + QCOMPARE(QPlaceImage(retrievedCollection.value(1)), dummyImage2New); + QCOMPARE(QPlaceImage(retrievedCollection.value(2)), dummyImage3); + QCOMPARE(QPlaceImage(retrievedCollection.value(3)), QPlaceImage()); + QCOMPARE(QPlaceImage(retrievedCollection.value(4)), QPlaceImage()); + QCOMPARE(QPlaceImage(retrievedCollection.value(5)), dummyImage6); +} + +void tst_Place::reviewContentTest() +{ + QPlace place; + QVERIFY2(place.content(QPlaceContent::ReviewType).count() ==0,"Wrong default value"); + + QPlaceReview dummyReview; + dummyReview.setTitle(QStringLiteral("Review 1")); + + QPlaceReview dummyReview2; + dummyReview2.setTitle(QStringLiteral("Review 2")); + + QPlaceReview dummyReview3; + dummyReview3.setTitle(QStringLiteral("Review 3")); + + QPlaceContent::Collection reviewCollection; + reviewCollection.insert(0,dummyReview); + reviewCollection.insert(1, dummyReview2); + reviewCollection.insert(2, dummyReview3); + + place.setContent(QPlaceContent::ReviewType, reviewCollection); + QPlaceContent::Collection retrievedCollection = place.content(QPlaceContent::ReviewType); + + QCOMPARE(retrievedCollection.count(), 3); + QCOMPARE(QPlaceReview(retrievedCollection.value(0)), dummyReview); + QCOMPARE(QPlaceReview(retrievedCollection.value(1)), dummyReview2); + QCOMPARE(QPlaceReview(retrievedCollection.value(2)), dummyReview3); + + //replace the second and insert a sixth review + //indexes 4 and 5 are "missing" + QPlaceReview dummyReview2New; + dummyReview2.setTitle(QStringLiteral("Review 2 new")); + + QPlaceReview dummyReview6; + dummyReview6.setTitle(QStringLiteral("Review 6")); + + reviewCollection.clear(); + reviewCollection.insert(1, dummyReview2New); + reviewCollection.insert(5, dummyReview6); + place.insertContent(QPlaceContent::ReviewType, reviewCollection); + + retrievedCollection = place.content(QPlaceContent::ReviewType); + QCOMPARE(retrievedCollection.count(), 4); + QCOMPARE(QPlaceReview(retrievedCollection.value(0)), dummyReview); + QCOMPARE(QPlaceReview(retrievedCollection.value(1)), dummyReview2New); + QCOMPARE(QPlaceReview(retrievedCollection.value(2)), dummyReview3); + QCOMPARE(QPlaceReview(retrievedCollection.value(3)), QPlaceReview()); + QCOMPARE(QPlaceReview(retrievedCollection.value(4)), QPlaceReview()); + QCOMPARE(QPlaceReview(retrievedCollection.value(5)), dummyReview6); +} + +void tst_Place::editorialContentTest() +{ + QPlace place; + QVERIFY2(place.content(QPlaceContent::EditorialType).count() == 0, "Wrong default value"); + + QPlaceEditorial dummyEditorial; + dummyEditorial.setTitle(QStringLiteral("Editorial 1")); + + QPlaceEditorial dummyEditorial2; + dummyEditorial2.setTitle(QStringLiteral("Editorial 2")); + + QPlaceEditorial dummyEditorial3; + dummyEditorial3.setTitle(QStringLiteral("Editorial 3")); + + QPlaceContent::Collection editorialCollection; + editorialCollection.insert(0,dummyEditorial); + editorialCollection.insert(1, dummyEditorial2); + editorialCollection.insert(2, dummyEditorial3); + + place.setContent(QPlaceContent::EditorialType, editorialCollection); + QPlaceContent::Collection retrievedCollection = place.content(QPlaceContent::EditorialType); + + QCOMPARE(retrievedCollection.count(), 3); + QCOMPARE(QPlaceEditorial(retrievedCollection.value(0)), dummyEditorial); + QCOMPARE(QPlaceEditorial(retrievedCollection.value(1)), dummyEditorial2); + QCOMPARE(QPlaceEditorial(retrievedCollection.value(2)), dummyEditorial3); + + //replace the second and insert a sixth editorial + //indexes 4 and 5 are "missing" + QPlaceEditorial dummyEditorial2New; + dummyEditorial2.setTitle(QStringLiteral("Editorial 2 new")); + + QPlaceEditorial dummyEditorial6; + dummyEditorial6.setTitle(QStringLiteral("Editorial 6")); + + editorialCollection.clear(); + editorialCollection.insert(1, dummyEditorial2New); + editorialCollection.insert(5, dummyEditorial6); + place.insertContent(QPlaceContent::EditorialType, editorialCollection); + + retrievedCollection = place.content(QPlaceContent::EditorialType); + QCOMPARE(retrievedCollection.count(), 4); + QCOMPARE(QPlaceEditorial(retrievedCollection.value(0)), dummyEditorial); + QCOMPARE(QPlaceEditorial(retrievedCollection.value(1)), dummyEditorial2New); + QCOMPARE(QPlaceEditorial(retrievedCollection.value(2)), dummyEditorial3); + QCOMPARE(QPlaceEditorial(retrievedCollection.value(3)), QPlaceEditorial()); + QCOMPARE(QPlaceEditorial(retrievedCollection.value(4)), QPlaceEditorial()); + QCOMPARE(QPlaceEditorial(retrievedCollection.value(5)), dummyEditorial6); +} + +void tst_Place::categoriesTest() +{ + QPlace place; + QVERIFY(place.categories().isEmpty()); + + //set a single category + QPlaceCategory cat1; + cat1.setName("cat1"); + + place.setCategory(cat1); + QCOMPARE(place.categories().count(), 1); + QCOMPARE(place.categories().at(0), cat1); + + //set multiple categories + QPlaceCategory cat2; + cat2.setName("cat2"); + + QPlaceCategory cat3; + cat3.setName("cat3"); + + QList categories; + categories << cat2 << cat3; + + place.setCategories(categories); + QCOMPARE(place.categories().count(), 2); + QVERIFY(place.categories().contains(cat2)); + QVERIFY(place.categories().contains(cat3)); + + //set a single category again while there are multiple categories already assigned. + place.setCategory(cat1); + QCOMPARE(place.categories().count(), 1); + QCOMPARE(place.categories().at(0), cat1); + + //set an empty list of categories + place.setCategories(QList()); + QVERIFY(place.categories().isEmpty()); +} + +void tst_Place::supplierTest() +{ + QPlace testObj; + QCOMPARE(testObj.supplier(), QPlaceSupplier()); + + QPlaceSupplier sup; + sup.setName("testName1"); + sup.setSupplierId("testId"); + + testObj.setSupplier(sup); + + QCOMPARE(testObj.supplier(), sup); +} + +void tst_Place::attributionTest() +{ + QPlace testPlace; + QVERIFY(testPlace.attribution().isEmpty()); + testPlace.setAttribution(QStringLiteral("attribution")); + QCOMPARE(testPlace.attribution(), QStringLiteral("attribution")); + testPlace.setAttribution(QString()); + QVERIFY(testPlace.attribution().isEmpty()); +} + +void tst_Place::contactDetailsTest() +{ + QPlaceContactDetail phone1; + phone1.setLabel("Phone1"); + phone1.setValue("555-5555"); + + QPlaceContactDetail phone2; + phone2.setLabel("Phone2"); + phone2.setValue("555-5556"); + + QList phones; + phones << phone1 << phone2; + + + QPlaceContactDetail email; + email.setLabel("Email"); + email.setValue("email@email.com"); + + QPlace place; + place.setContactDetails(QPlaceContactDetail::Phone,phones); + QCOMPARE(place.contactTypes().count(), 1); + QVERIFY(place.contactTypes().contains(QPlaceContactDetail::Phone)); + QCOMPARE(place.contactDetails(QPlaceContactDetail::Phone), phones); + + place.appendContactDetail(QPlaceContactDetail::Email, email); + QCOMPARE(place.contactTypes().count(), 2); + QVERIFY(place.contactTypes().contains(QPlaceContactDetail::Phone)); + QVERIFY(place.contactTypes().contains(QPlaceContactDetail::Email)); + QCOMPARE(place.contactDetails(QPlaceContactDetail::Phone), phones); + QCOMPARE(place.contactDetails(QPlaceContactDetail::Email).count(), 1); + QCOMPARE(place.contactDetails(QPlaceContactDetail::Email).at(0), email); + + place.removeContactDetails(QPlaceContactDetail::Phone); + QCOMPARE(place.contactTypes().count(), 1); + QVERIFY(!place.contactTypes().contains(QPlaceContactDetail::Phone)); + QVERIFY(place.contactDetails(QPlaceContactDetail::Phone).isEmpty()); + QVERIFY(place.contactTypes().contains(QPlaceContactDetail::Email)); + QCOMPARE(place.contactDetails(QPlaceContactDetail::Email).count(), 1); + QCOMPARE(place.contactDetails(QPlaceContactDetail::Email).at(0), email); + + place.removeContactDetails(QPlaceContactDetail::Email); + QVERIFY(place.contactTypes().isEmpty()); + QVERIFY(place.contactDetails(QPlaceContactDetail::Email).isEmpty()); +} + +void tst_Place::primaryPhoneTest() +{ + QPlace place; + QVERIFY2(place.primaryPhone().isEmpty(), "Wrong default value"); + + QPlaceContactDetail contactDetail; + contactDetail.setLabel(QStringLiteral("Phone")); + contactDetail.setValue(QStringLiteral("555-5555")); + place.appendContactDetail(QPlaceContactDetail::Phone, contactDetail); + + QCOMPARE(place.primaryPhone(), QString("555-5555")); + + //try clearing the primary phone number + place.setContactDetails(QPlaceContactDetail::Phone, QList()); + QCOMPARE(place.primaryPhone(), QString()); +} + +void tst_Place::primaryEmailTest() +{ + QPlace place; + QVERIFY2(place.primaryEmail().isEmpty(), "Wrong default value"); + + QPlaceContactDetail contactDetail; + contactDetail.setLabel(QStringLiteral("Email")); + contactDetail.setValue(QStringLiteral("test@test.com")); + place.appendContactDetail(QPlaceContactDetail::Email, contactDetail); + + QCOMPARE(place.primaryEmail(), QStringLiteral("test@test.com")); + + //try clearing the primary email address + place.setContactDetails(QPlaceContactDetail::Email, QList()); + QCOMPARE(place.primaryEmail(), QString()); +} + +void tst_Place::primaryFaxTest() +{ + QPlace place; + QVERIFY2(place.primaryFax().isEmpty(), "Wrong default value"); + + QPlaceContactDetail contactDetail; + contactDetail.setLabel(QStringLiteral("Fax")); + contactDetail.setValue(QStringLiteral("555-5555")); + place.appendContactDetail(QPlaceContactDetail::Fax, contactDetail); + + QCOMPARE(place.primaryFax(), QStringLiteral("555-5555")); + + //try clearing the primary fax number + place.setContactDetails(QPlaceContactDetail::Fax, QList()); + QCOMPARE(place.primaryFax(), QString()); +} + +void tst_Place::primaryWebsiteTest() +{ + QPlace place; + QVERIFY2(place.primaryWebsite().isEmpty(), "Wrong default value"); + + QPlaceContactDetail contactDetail; + contactDetail.setLabel(QStringLiteral("Website")); + contactDetail.setValue(QStringLiteral("www.example.com")); + place.appendContactDetail(QPlaceContactDetail::Website, contactDetail); + + QCOMPARE(place.primaryWebsite(), QUrl("www.example.com")); + + //try clearing the primary website number + place.setContactDetails(QPlaceContactDetail::Website, QList()); + QCOMPARE(place.primaryWebsite(), QUrl()); +} + +void tst_Place::operatorsTest() +{ + QPlace testObj; + testObj.setPlaceId("testId"); + QPlaceAttribute paymentMethods; + paymentMethods.setLabel("Payment methods"); + paymentMethods.setText("Visa"); + testObj.setExtendedAttribute(QStringLiteral("paymentMethods"), paymentMethods); + QGeoLocation loc; + loc.setCoordinate(QGeoCoordinate(10,20)); + testObj.setLocation(loc); + + QPlace testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setPlaceId("342-456"); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +void tst_Place::extendedAttributeTest() +{ + QPlace place; + QVERIFY(place.extendedAttributeTypes().isEmpty()); + QPlaceAttribute smoking; + smoking.setLabel(QStringLiteral("Public Smoking")); + smoking.setText(QStringLiteral("No")); + + //test setting of an attribue + place.setExtendedAttribute(QStringLiteral("smoking"), smoking); + + QVERIFY(place.extendedAttributeTypes().contains(QStringLiteral("smoking"))); + QCOMPARE(place.extendedAttributeTypes().count(), 1); + + QCOMPARE(place.extendedAttribute(QStringLiteral("smoking")).label(), QStringLiteral("Public Smoking")); + QCOMPARE(place.extendedAttribute(QStringLiteral("smoking")).text(), QStringLiteral("No")); + + QPlaceAttribute shelter; + shelter.setLabel(QStringLiteral("Outdoor shelter")); + shelter.setText(QStringLiteral("Yes")); + + //test setting another new attribute + place.setExtendedAttribute("shelter", shelter); + QVERIFY(place.extendedAttributeTypes().contains(QStringLiteral("shelter"))); + QVERIFY(place.extendedAttributeTypes().contains(QStringLiteral("smoking"))); + QCOMPARE(place.extendedAttributeTypes().count(), 2); + QCOMPARE(place.extendedAttribute(QStringLiteral("shelter")).label(), QStringLiteral("Outdoor shelter")); + QCOMPARE(place.extendedAttribute(QStringLiteral("shelter")).text(), QStringLiteral("Yes")); + + //test overwriting an attribute + shelter.setText(QStringLiteral("No")); + place.setExtendedAttribute(QStringLiteral("shelter"), shelter); + + QVERIFY(place.extendedAttributeTypes().contains(QStringLiteral("shelter"))); + QVERIFY(place.extendedAttributeTypes().contains(QStringLiteral("smoking"))); + QCOMPARE(place.extendedAttributeTypes().count(), 2); + QCOMPARE(place.extendedAttribute(QStringLiteral("shelter")).text(), QStringLiteral("No")); + + //test clearing of attributes by setting them to the default attribute + foreach (const QString &attributeType, place.extendedAttributeTypes()) + place.setExtendedAttribute(attributeType, QPlaceAttribute()); + + QCOMPARE(place.extendedAttributeTypes().count(), 0); + + //test removing of attributes + place.setExtendedAttribute(QStringLiteral("smoking"), smoking); + QVERIFY(!place.extendedAttributeTypes().isEmpty()); + place.removeExtendedAttribute(QStringLiteral("smoking")); + QVERIFY(place.extendedAttributeTypes().isEmpty()); +} +void tst_Place::visibilityTest() +{ + QPlace place; + + QCOMPARE(place.visibility(), QLocation::UnspecifiedVisibility); + + place.setVisibility(QLocation::DeviceVisibility); + + QCOMPARE(place.visibility(), QLocation::DeviceVisibility); +} + +void tst_Place::isEmptyTest() +{ + QGeoLocation location; + location.setCoordinate(QGeoCoordinate(6.788697, 51.224679)); + QVERIFY(!location.isEmpty()); + + QPlaceCategory category; + + QPlaceRatings ratings; + ratings.setCount(1); + QVERIFY(!ratings.isEmpty()); + + QPlaceSupplier supplier; + supplier.setName(QStringLiteral("Foo & Bar Imports")); + QVERIFY(!supplier.isEmpty()); + + QPlaceIcon icon; + QVariantMap iconParametersMap; + iconParametersMap.insert(QStringLiteral("Para"), QStringLiteral("meter")); + icon.setParameters(iconParametersMap); + QVERIFY(!icon.isEmpty()); + + QPlaceContent content; + QPlaceContent::Collection contentCollection; + contentCollection.insert(42, content); + + QPlaceAttribute attribute; + attribute.setLabel(QStringLiteral("noodle")); + + QPlaceContactDetail contactDetail; + + + QPlace place; + + // default constructed + QVERIFY(place.isEmpty()); + + // categories + place.setCategory(category); + QVERIFY(!place.isEmpty()); + place.categories().clear(); + place = QPlace(); + + // location + place.setLocation(location); + QVERIFY(!place.isEmpty()); + place.setLocation(QGeoLocation()); + QVERIFY(place.isEmpty()); + + // ratings + place.setRatings(ratings); + QVERIFY(!place.isEmpty()); + place.setRatings(QPlaceRatings()); + QVERIFY(place.isEmpty()); + + // supplier + place.setSupplier(supplier); + QVERIFY(!place.isEmpty()); + place.setSupplier(QPlaceSupplier()); + QVERIFY(place.isEmpty()); + + // attribution + place.setAttribution(QStringLiteral("attr")); + QVERIFY(!place.isEmpty()); + place.setAttribution(QString()); + QVERIFY(place.isEmpty()); + + // icon + place.setIcon(icon); + QVERIFY(!place.isEmpty()); + place.setIcon(QPlaceIcon()); + QVERIFY(place.isEmpty()); + + // content + place.insertContent(QPlaceContent::EditorialType, contentCollection); + QVERIFY(!place.isEmpty()); + place = QPlace(); + + // name + place.setName(QStringLiteral("Naniwa")); + QVERIFY(!place.isEmpty()); + place.setName(QString()); + QVERIFY(place.isEmpty()); + + // placeId + place.setPlaceId(QStringLiteral("naniwa")); + QVERIFY(!place.isEmpty()); + place.setPlaceId(QString()); + QVERIFY(place.isEmpty()); + + // extendedAttributes + place.setExtendedAttribute(QStringLiteral("part"), attribute); + QVERIFY(!place.isEmpty()); + place.removeExtendedAttribute(QStringLiteral("part")); + QVERIFY(place.isEmpty()); + + // extendedAttributes + place.setDetailsFetched(true); + QVERIFY(place.isEmpty()); + + // contact detail + place.appendContactDetail(QStringLiteral("phone"), contactDetail); + QVERIFY(!place.isEmpty()); + place.removeContactDetails(QStringLiteral("phone")); + QVERIFY(place.isEmpty()); + + // visibility + place.setVisibility(QLocation::DeviceVisibility); + QVERIFY(!place.isEmpty()); + place.setVisibility(QLocation::UnspecifiedVisibility); + QVERIFY(place.isEmpty()); +} + +QTEST_APPLESS_MAIN(tst_Place) + +#include "tst_qplace.moc" diff --git a/tests/auto/qplaceattribute/qplaceattribute.pro b/tests/auto/qplaceattribute/qplaceattribute.pro new file mode 100644 index 0000000..4fc27e5 --- /dev/null +++ b/tests/auto/qplaceattribute/qplaceattribute.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplaceattribute + +SOURCES += tst_qplaceattribute.cpp + +QT += location testlib diff --git a/tests/auto/qplaceattribute/tst_qplaceattribute.cpp b/tests/auto/qplaceattribute/tst_qplaceattribute.cpp new file mode 100644 index 0000000..1f229ab --- /dev/null +++ b/tests/auto/qplaceattribute/tst_qplaceattribute.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QPlaceAttribute : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceAttribute(); + +private Q_SLOTS: + void constructorTest(); + void operatorsTest(); + void isEmptyTest(); +}; + +tst_QPlaceAttribute::tst_QPlaceAttribute() +{ +} + +void tst_QPlaceAttribute::constructorTest() +{ + QPlaceAttribute testObj; + + QPlaceAttribute *testObjPtr = new QPlaceAttribute(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(testObjPtr->label() == QString(), "Copy constructor - wrong label"); + QVERIFY2(testObjPtr->text() == QString(), "Copy constructor - wrong text"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + delete testObjPtr; +} + +void tst_QPlaceAttribute::operatorsTest() +{ + QPlaceAttribute testObj; + testObj.setLabel(QStringLiteral("label")); + QPlaceAttribute testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setText(QStringLiteral("text")); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +void tst_QPlaceAttribute::isEmptyTest() +{ + QPlaceAttribute attribute; + + QVERIFY(attribute.isEmpty()); + + attribute.setLabel(QStringLiteral("label")); + QVERIFY(!attribute.isEmpty()); + attribute.setLabel(QString()); + QVERIFY(attribute.isEmpty()); + + attribute.setText(QStringLiteral("text")); + QVERIFY(!attribute.isEmpty()); + attribute.setText(QString()); + QVERIFY(attribute.isEmpty()); +} + +QTEST_APPLESS_MAIN(tst_QPlaceAttribute); + +#include "tst_qplaceattribute.moc" diff --git a/tests/auto/qplacecategory/qplacecategory.pro b/tests/auto/qplacecategory/qplacecategory.pro new file mode 100644 index 0000000..43686ec --- /dev/null +++ b/tests/auto/qplacecategory/qplacecategory.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacecategory + +SOURCES += tst_qplacecategory.cpp + +QT += location testlib diff --git a/tests/auto/qplacecategory/tst_qplacecategory.cpp b/tests/auto/qplacecategory/tst_qplacecategory.cpp new file mode 100644 index 0000000..8a84d64 --- /dev/null +++ b/tests/auto/qplacecategory/tst_qplacecategory.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include + +QT_USE_NAMESPACE + +class tst_QPlaceCategory : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceCategory(); + +private Q_SLOTS: + void constructorTest(); + void categoryIdTest(); + void nameTest(); + void visibilityTest(); + void operatorsTest(); + void isEmptyTest(); +}; + +tst_QPlaceCategory::tst_QPlaceCategory() +{ +} + +void tst_QPlaceCategory::constructorTest() +{ + QPlaceCategory testObj; + Q_UNUSED(testObj); + + testObj.setCategoryId("testId"); + QPlaceCategory *testObjPtr = new QPlaceCategory(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + delete testObjPtr; +} + +void tst_QPlaceCategory::categoryIdTest() +{ + QPlaceCategory testObj; + QVERIFY2(testObj.categoryId() == QString(), "Wrong default value"); + testObj.setCategoryId("testText"); + QVERIFY2(testObj.categoryId() == "testText", "Wrong value returned"); +} + +void tst_QPlaceCategory::nameTest() +{ + QPlaceCategory testObj; + QVERIFY2(testObj.name() == QString(), "Wrong default value"); + testObj.setName("testText"); + QVERIFY2(testObj.name() == "testText", "Wrong value returned"); +} + +void tst_QPlaceCategory::visibilityTest() +{ + QPlaceCategory category; + + QCOMPARE(category.visibility(), QLocation::UnspecifiedVisibility); + + category.setVisibility(QLocation::DeviceVisibility); + + QCOMPARE(category.visibility(), QLocation::DeviceVisibility); +} + +void tst_QPlaceCategory::operatorsTest() +{ + QPlaceCategory testObj; + testObj.setName("testValue"); + QPlaceCategory testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setCategoryId("a3rfg"); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +void tst_QPlaceCategory::isEmptyTest() +{ + QPlaceIcon icon; + QVariantMap parameters; + parameters.insert(QStringLiteral("para"), QStringLiteral("meter")); + icon.setParameters(parameters); + QVERIFY(!icon.isEmpty()); + + QPlaceCategory category; + + QVERIFY(category.isEmpty()); + + category.setName(QStringLiteral("name")); + QVERIFY(!category.isEmpty()); + category.setName(QString()); + QVERIFY(category.isEmpty()); + + category.setCategoryId(QStringLiteral("id")); + QVERIFY(!category.isEmpty()); + category.setCategoryId(QString()); + QVERIFY(category.isEmpty()); + + category.setVisibility(QLocation::PublicVisibility); + QVERIFY(!category.isEmpty()); + category.setVisibility(QLocation::UnspecifiedVisibility); + QVERIFY(category.isEmpty()); + + category.setIcon(icon); + QVERIFY(!category.isEmpty()); + category.setIcon(QPlaceIcon()); + QVERIFY(category.isEmpty()); +} + +QTEST_APPLESS_MAIN(tst_QPlaceCategory); + +#include "tst_qplacecategory.moc" diff --git a/tests/auto/qplacecontactdetail/qplacecontactdetail.pro b/tests/auto/qplacecontactdetail/qplacecontactdetail.pro new file mode 100644 index 0000000..ab49471 --- /dev/null +++ b/tests/auto/qplacecontactdetail/qplacecontactdetail.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacecontactdetail + +SOURCES += tst_qplacecontactdetail.cpp + +QT += location testlib diff --git a/tests/auto/qplacecontactdetail/tst_qplacecontactdetail.cpp b/tests/auto/qplacecontactdetail/tst_qplacecontactdetail.cpp new file mode 100644 index 0000000..370bb5e --- /dev/null +++ b/tests/auto/qplacecontactdetail/tst_qplacecontactdetail.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QPlaceContactDetail : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceContactDetail(); + +private Q_SLOTS: + void constructorTest(); + void labelTest(); + void valueTest(); + void clearTest(); + void operatorsTest(); + void operatorsTest_data(); +}; + +tst_QPlaceContactDetail::tst_QPlaceContactDetail() +{ +} + +void tst_QPlaceContactDetail::constructorTest() +{ + QPlaceContactDetail detail; + QVERIFY(detail.label().isEmpty()); + QVERIFY(detail.value().isEmpty()); + + detail.setLabel(QStringLiteral("Emergency Services")); + detail.setValue(QStringLiteral("0118 999")); + + QPlaceContactDetail detail2(detail); + QCOMPARE(detail2.label(), QStringLiteral("Emergency Services")); + QCOMPARE(detail2.value(), QStringLiteral("0118 999")); +} + +void tst_QPlaceContactDetail::labelTest() +{ + QPlaceContactDetail detail; + detail.setLabel(QStringLiteral("home")); + QCOMPARE(detail.label(), QStringLiteral("home")); + detail.setLabel(QString()); + QVERIFY(detail.label().isEmpty()); +} + +void tst_QPlaceContactDetail::valueTest() +{ + QPlaceContactDetail detail; + detail.setValue(QStringLiteral("555-5555")); + QCOMPARE(detail.value(), QStringLiteral("555-5555")); + detail.setValue(QString()); + QVERIFY(detail.value().isEmpty()); +} + +void tst_QPlaceContactDetail::clearTest() +{ + QPlaceContactDetail detail; + detail.setLabel(QStringLiteral("Ghostbusters")); + detail.setValue(QStringLiteral("555-2368")); + detail.clear(); + QVERIFY(detail.label().isEmpty()); + QVERIFY(detail.value().isEmpty()); +} + +void tst_QPlaceContactDetail::operatorsTest() +{ + QPlaceContactDetail detail1; + detail1.setLabel(QStringLiteral("Kramer")); + detail1.setValue(QStringLiteral("555-filk")); + + QPlaceContactDetail detail2; + detail2.setLabel(QStringLiteral("Kramer")); + detail2.setValue(QStringLiteral("555-filk")); + + QVERIFY(detail1 == detail2); + QVERIFY(!(detail1 != detail2)); + QVERIFY(detail2 == detail1); + QVERIFY(!(detail2 != detail1)); + + QPlaceContactDetail detail3; + QVERIFY(!(detail1 == detail3)); + QVERIFY(detail1 != detail3); + QVERIFY(!(detail1 == detail3)); + QVERIFY(detail1 != detail3); + + detail3 = detail1; + QVERIFY(detail1 == detail3); + QVERIFY(!(detail1 != detail3)); + QVERIFY(detail3 == detail1); + QVERIFY(!(detail3 != detail1)); + + QFETCH(QString, field); + if (field == QStringLiteral("label")) + detail3.setLabel(QStringLiteral("Cosmo")); + else if (field == QStringLiteral("value")) + detail3.setValue(QStringLiteral("555-5555")); + + QVERIFY(!(detail1 == detail3)); + QVERIFY(detail1 != detail3); + QVERIFY(!(detail3 == detail1)); + QVERIFY(detail3 != detail1); +} + +void tst_QPlaceContactDetail::operatorsTest_data() +{ + QTest::addColumn("field"); + QTest::newRow("label") << "label"; + QTest::newRow("value") << "value"; +} + +QTEST_APPLESS_MAIN(tst_QPlaceContactDetail) + +#include "tst_qplacecontactdetail.moc" diff --git a/tests/auto/qplacecontentrequest/qplacecontentrequest.pro b/tests/auto/qplacecontentrequest/qplacecontentrequest.pro new file mode 100644 index 0000000..6e27c4e --- /dev/null +++ b/tests/auto/qplacecontentrequest/qplacecontentrequest.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacecontentrequest +SOURCES += tst_qplacecontentrequest.cpp + +QT += location testlib diff --git a/tests/auto/qplacecontentrequest/tst_qplacecontentrequest.cpp b/tests/auto/qplacecontentrequest/tst_qplacecontentrequest.cpp new file mode 100644 index 0000000..46bfb9e --- /dev/null +++ b/tests/auto/qplacecontentrequest/tst_qplacecontentrequest.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QPlaceContentRequest : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceContentRequest(); + +private Q_SLOTS: + void contentTest(); + void clearTest(); +}; + +tst_QPlaceContentRequest::tst_QPlaceContentRequest() +{ +} + +void tst_QPlaceContentRequest::contentTest() +{ + QPlaceContentRequest req; + QCOMPARE(req.limit(), -1); + QCOMPARE(req.contentType(), QPlaceContent::NoType); + + //check that we can set the request fields + req.setLimit(100); + req.setContentType(QPlaceContent::ImageType); + QCOMPARE(req.limit(), 100); + QCOMPARE(req.contentType(), QPlaceContent::ImageType); + + //check that we assignment works correctly + QPlaceContentRequest otherReq; + otherReq.setLimit(10); + otherReq.setContentType(QPlaceContent::ReviewType); + req = otherReq; + QCOMPARE(req.limit(), 10); + QCOMPARE(req.contentType(), QPlaceContent::ReviewType); + QCOMPARE(req, otherReq); + + //check that comparison will fail if one the fields are different + req.setLimit(9000); + QVERIFY(req != otherReq); +} + +void tst_QPlaceContentRequest::clearTest() +{ + QPlaceContentRequest req; + req.setContentType(QPlaceContent::ReviewType); + req.setLimit(9000); + req.clear(); + QVERIFY(req.contentType() == QPlaceContent::NoType); + QVERIFY(req.limit() == -1); +} + +QTEST_APPLESS_MAIN(tst_QPlaceContentRequest) + +#include "tst_qplacecontentrequest.moc" diff --git a/tests/auto/qplacedetailsreply/qplacedetailsreply.pro b/tests/auto/qplacedetailsreply/qplacedetailsreply.pro new file mode 100644 index 0000000..05daa2f --- /dev/null +++ b/tests/auto/qplacedetailsreply/qplacedetailsreply.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacedetailsreply + +SOURCES += tst_qplacedetailsreply.cpp + +QT += location testlib diff --git a/tests/auto/qplacedetailsreply/tst_qplacedetailsreply.cpp b/tests/auto/qplacedetailsreply/tst_qplacedetailsreply.cpp new file mode 100644 index 0000000..5ea509b --- /dev/null +++ b/tests/auto/qplacedetailsreply/tst_qplacedetailsreply.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class TestDetailsReply : public QPlaceDetailsReply +{ + Q_OBJECT +public: + TestDetailsReply(QObject *parent) : QPlaceDetailsReply(parent){} + ~TestDetailsReply() {} + void setPlace(const QPlace &place) { QPlaceDetailsReply::setPlace(place); } +}; + +class tst_QPlaceDetailsReply : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceDetailsReply(); + +private Q_SLOTS: + void constructorTest(); + void typeTest(); + void placeTest(); +}; + +tst_QPlaceDetailsReply::tst_QPlaceDetailsReply() +{ +} + +void tst_QPlaceDetailsReply::constructorTest() +{ + TestDetailsReply *reply = new TestDetailsReply(this); + QVERIFY(reply->parent() == this); + delete reply; +} + +void tst_QPlaceDetailsReply::typeTest() +{ + TestDetailsReply *reply = new TestDetailsReply(this); + QCOMPARE(reply->type(), QPlaceReply::DetailsReply); + delete reply; +} + +void tst_QPlaceDetailsReply::placeTest() +{ + TestDetailsReply *reply = new TestDetailsReply(this); + QPlace place; + place.setName(QStringLiteral("Gotham City")); + reply->setPlace(place); + + QCOMPARE(reply->place(), place); + delete reply; +} + +QTEST_APPLESS_MAIN(tst_QPlaceDetailsReply) + +#include "tst_qplacedetailsreply.moc" diff --git a/tests/auto/qplaceeditorial/qplaceeditorial.pro b/tests/auto/qplaceeditorial/qplaceeditorial.pro new file mode 100644 index 0000000..703fa8b --- /dev/null +++ b/tests/auto/qplaceeditorial/qplaceeditorial.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplaceeditorial + +SOURCES += tst_qplaceeditorial.cpp + +QT += location testlib diff --git a/tests/auto/qplaceeditorial/tst_qplaceeditorial.cpp b/tests/auto/qplaceeditorial/tst_qplaceeditorial.cpp new file mode 100644 index 0000000..1c20bd2 --- /dev/null +++ b/tests/auto/qplaceeditorial/tst_qplaceeditorial.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "../utils/qlocationtestutils_p.h" + +QT_USE_NAMESPACE + +class tst_QPlaceEditorial : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceEditorial(); + + //needed for QLocationTestUtils::testConversion + QPlaceEditorial initialSubObject(); + bool checkType(const QPlaceContent &); + void detach(QPlaceContent *); + void setSubClassProperty(QPlaceEditorial *); + +private Q_SLOTS: + void constructorTest(); + void supplierTest(); + void textTest(); + void titleTest(); + void languageTest(); + void operatorsTest(); + void conversionTest(); +}; + +tst_QPlaceEditorial::tst_QPlaceEditorial() +{ +} + +QPlaceEditorial tst_QPlaceEditorial::initialSubObject() +{ + QPlaceUser user; + user.setName("user 1"); + user.setUserId("0001"); + + QPlaceSupplier supplier; + supplier.setName("supplier"); + supplier.setSupplierId("1"); + + QPlaceEditorial editorial; + editorial.setTitle("title"); + editorial.setText("text"); + editorial.setLanguage("en"); + editorial.setUser(user); + editorial.setSupplier(supplier); + editorial.setAttribution("attribution"); + + return editorial; +} + +bool tst_QPlaceEditorial::checkType(const QPlaceContent &content) +{ + return content.type() == QPlaceContent::EditorialType; +} + +void tst_QPlaceEditorial::detach(QPlaceContent *content) +{ + content->setAttribution("attribution"); +} + +void tst_QPlaceEditorial::setSubClassProperty(QPlaceEditorial * editorial) +{ + editorial->setTitle("new title"); +} +void tst_QPlaceEditorial::constructorTest() +{ + QPlaceEditorial testObj; + testObj.setText("testId"); + QPlaceEditorial *testObjPtr = new QPlaceEditorial(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + delete testObjPtr; +} + +void tst_QPlaceEditorial::supplierTest() +{ + QPlaceEditorial testObj; + QVERIFY2(testObj.supplier().supplierId() == QString(), "Wrong default value"); + QPlaceSupplier sup; + sup.setName("testName1"); + sup.setSupplierId("testId"); + testObj.setSupplier(sup); + QVERIFY2(testObj.supplier() == sup, "Wrong value returned"); +} + +void tst_QPlaceEditorial::textTest() +{ + QPlaceEditorial testObj; + QVERIFY2(testObj.text() == QString(), "Wrong default value"); + testObj.setText("testText"); + QVERIFY2(testObj.text() == "testText", "Wrong value returned"); +} + +void tst_QPlaceEditorial::titleTest() +{ + QPlaceEditorial testObj; + QVERIFY2(testObj.title() == QString(), "Wrong default value"); + testObj.setTitle("testText"); + QVERIFY2(testObj.title() == "testText", "Wrong value returned"); +} + +void tst_QPlaceEditorial::languageTest() +{ + QPlaceEditorial testObj; + QVERIFY2(testObj.language() == QString(), "Wrong default value"); + testObj.setLanguage("testText"); + QVERIFY2(testObj.language() == "testText", "Wrong value returned"); +} + +void tst_QPlaceEditorial::operatorsTest() +{ + QPlaceEditorial testObj; + testObj.setLanguage("testValue"); + QPlaceEditorial testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setText("testValue2"); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +void tst_QPlaceEditorial::conversionTest() +{ + QLocationTestUtils::testConversion(this); +} +QTEST_APPLESS_MAIN(tst_QPlaceEditorial); + +#include "tst_qplaceeditorial.moc" diff --git a/tests/auto/qplaceimage/qplaceimage.pro b/tests/auto/qplaceimage/qplaceimage.pro new file mode 100644 index 0000000..b6a2805 --- /dev/null +++ b/tests/auto/qplaceimage/qplaceimage.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplaceimage + +SOURCES += tst_qplaceimage.cpp + +QT += location testlib diff --git a/tests/auto/qplaceimage/tst_qplaceimage.cpp b/tests/auto/qplaceimage/tst_qplaceimage.cpp new file mode 100644 index 0000000..aa3f9df --- /dev/null +++ b/tests/auto/qplaceimage/tst_qplaceimage.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#include "../utils/qlocationtestutils_p.h" + +QT_USE_NAMESPACE + +class tst_QPlaceImage : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceImage(); + + //needed for QLocationTestUtils::testConversion + QPlaceImage initialSubObject(); + bool checkType(const QPlaceContent &); + void detach(QPlaceContent *); + void setSubClassProperty(QPlaceImage *); + +private Q_SLOTS: + void constructorTest(); + void supplierTest(); + void idTest(); + void mimeTypeTest(); + void attributionTest(); + void operatorsTest(); + void conversionTest(); +}; + +tst_QPlaceImage::tst_QPlaceImage() +{ +} + +QPlaceImage tst_QPlaceImage::initialSubObject() +{ + QPlaceUser user; + user.setName("user 1"); + user.setUserId("0001"); + + QPlaceSupplier supplier; + supplier.setName("supplier"); + supplier.setSupplierId("1"); + + QPlaceImage image; + image.setUrl(QUrl(QStringLiteral("file:///opt/icon/img.png"))); + image.setImageId("0001"); + image.setMimeType("image/png"); + image.setUser(user); + image.setSupplier(supplier); + image.setAttribution("attribution"); + + return image; +} + +bool tst_QPlaceImage::checkType(const QPlaceContent &content) +{ + return content.type() == QPlaceContent::ImageType; +} + +void tst_QPlaceImage::detach(QPlaceContent *content) +{ + content->setAttribution("attribution"); +} + +void tst_QPlaceImage::setSubClassProperty(QPlaceImage *image) +{ + image->setImageId("0002"); +} + +void tst_QPlaceImage::constructorTest() +{ + QPlaceImage testObj; + testObj.setImageId("testId"); + QPlaceImage *testObjPtr = new QPlaceImage(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + delete testObjPtr; +} + +void tst_QPlaceImage::supplierTest() +{ + QPlaceImage testObj; + QVERIFY2(testObj.supplier().supplierId() == QString(), "Wrong default value"); + QPlaceSupplier sup; + sup.setName("testName1"); + sup.setSupplierId("testId"); + testObj.setSupplier(sup); + QVERIFY2(testObj.supplier() == sup, "Wrong value returned"); +} + +void tst_QPlaceImage::idTest() +{ + QPlaceImage testObj; + QVERIFY2(testObj.imageId() == QString(), "Wrong default value"); + testObj.setImageId("testText"); + QVERIFY2(testObj.imageId() == "testText", "Wrong value returned"); +} + +void tst_QPlaceImage::mimeTypeTest() +{ + QPlaceImage testObj; + QVERIFY2(testObj.mimeType() == QString(), "Wrong default value"); + testObj.setMimeType("testText"); + QVERIFY2(testObj.mimeType() == "testText", "Wrong value returned"); +} + +void tst_QPlaceImage::attributionTest() +{ + QPlaceImage image; + QVERIFY(image.attribution().isEmpty()); + image.setAttribution(QStringLiteral("Brought to you by acme")); + QCOMPARE(image.attribution(), QStringLiteral("Brought to you by acme")); + image.setAttribution(QString()); + QVERIFY(image.attribution().isEmpty()); +} + +void tst_QPlaceImage::operatorsTest() +{ + QPlaceImage testObj; + testObj.setMimeType("testValue"); + QPlaceImage testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setImageId("testValue2"); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +void tst_QPlaceImage::conversionTest() +{ + QLocationTestUtils::testConversion(this); +} + +QTEST_APPLESS_MAIN(tst_QPlaceImage); + +#include "tst_qplaceimage.moc" diff --git a/tests/auto/qplacemanager/qplacemanager.pro b/tests/auto/qplacemanager/qplacemanager.pro new file mode 100644 index 0000000..7e7b25e --- /dev/null +++ b/tests/auto/qplacemanager/qplacemanager.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacemanager + +SOURCES += tst_qplacemanager.cpp + +CONFIG -= app_bundle + +QT += location testlib diff --git a/tests/auto/qplacemanager/tst_qplacemanager.cpp b/tests/auto/qplacemanager/tst_qplacemanager.cpp new file mode 100644 index 0000000..fe97b37 --- /dev/null +++ b/tests/auto/qplacemanager/tst_qplacemanager.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include +#include + + +#ifndef WAIT_UNTIL +#define WAIT_UNTIL(__expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + } while (0) +#endif + +QT_USE_NAMESPACE + +class tst_QPlaceManager : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void compatiblePlace(); + void testMetadata(); + void testLocales(); + void testMatchUnsupported(); + +private: + bool checkSignals(QPlaceReply *reply, QPlaceReply::Error expectedError); + + QGeoServiceProvider *provider; + QPlaceManager *placeManager; +}; + +void tst_QPlaceManager::initTestCase() +{ + /* + * Set custom path since CI doesn't install test plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif + provider = 0; + + QStringList providers = QGeoServiceProvider::availableServiceProviders(); + QVERIFY(providers.contains("qmlgeo.test.plugin")); + + provider = new QGeoServiceProvider("qmlgeo.test.plugin"); + provider->setAllowExperimental(true); + QCOMPARE(provider->placesFeatures() & QGeoServiceProvider::OfflinePlacesFeature, + QGeoServiceProvider::OfflinePlacesFeature); + placeManager = provider->placeManager(); + QVERIFY(placeManager); +} + +void tst_QPlaceManager::testMetadata() +{ + QCOMPARE(placeManager->managerName(), QStringLiteral("qmlgeo.test.plugin")); + QCOMPARE(placeManager->managerVersion(), 100); +} + +void tst_QPlaceManager::testLocales() +{ + QCOMPARE(placeManager->locales().count(), 1); + QCOMPARE(placeManager->locales().at(0), QLocale()); + + QLocale locale(QLocale::Norwegian, QLocale::Norway); + placeManager->setLocale(locale); + + QCOMPARE(placeManager->locales().at(0), locale); + + QList locales; + QLocale en_AU = QLocale(QLocale::English, QLocale::Australia); + QLocale en_UK = QLocale(QLocale::English, QLocale::UnitedKingdom); + locales << en_AU << en_UK; + placeManager->setLocales(locales); + QCOMPARE(placeManager->locales().count(), 2); + QCOMPARE(placeManager->locales().at(0), en_AU); + QCOMPARE(placeManager->locales().at(1), en_UK); +} + +void tst_QPlaceManager::testMatchUnsupported() +{ + QPlaceMatchRequest request; + QPlaceMatchReply *reply = placeManager->matchingPlaces(request); + QVERIFY(checkSignals(reply, QPlaceReply::UnsupportedError)); +} + +void tst_QPlaceManager::compatiblePlace() +{ + QPlace place; + place.setPlaceId(QStringLiteral("4-8-15-16-23-42")); + place.setName(QStringLiteral("Island")); + place.setVisibility(QLocation::PublicVisibility); + + QPlace compatPlace = placeManager->compatiblePlace(place); + QVERIFY(compatPlace.placeId().isEmpty()); + QCOMPARE(compatPlace.name(), QStringLiteral("Island")); + QCOMPARE(compatPlace.visibility(), QLocation::UnspecifiedVisibility); +} + +void tst_QPlaceManager::cleanupTestCase() +{ + delete provider; +} + +bool tst_QPlaceManager::checkSignals(QPlaceReply *reply, QPlaceReply::Error expectedError) +{ + QSignalSpy finishedSpy(reply, SIGNAL(finished())); + QSignalSpy errorSpy(reply, SIGNAL(error(QPlaceReply::Error,QString))); + QSignalSpy managerFinishedSpy(placeManager, SIGNAL(finished(QPlaceReply*))); + QSignalSpy managerErrorSpy(placeManager,SIGNAL(error(QPlaceReply*,QPlaceReply::Error,QString))); + + if (expectedError != QPlaceReply::NoError) { + //check that we get an error signal from the reply + WAIT_UNTIL(errorSpy.count() == 1); + if (errorSpy.count() != 1) { + qWarning() << "Error signal for search operation not received"; + return false; + } + + //check that we get the correct error from the reply's signal + QPlaceReply::Error actualError = qvariant_cast(errorSpy.at(0).at(0)); + if (actualError != expectedError) { + qWarning() << "Actual error code in reply signal does not match expected error code"; + qWarning() << "Actual error code = " << actualError; + qWarning() << "Expected error coe =" << expectedError; + return false; + } + + //check that we get an error signal from the manager + WAIT_UNTIL(managerErrorSpy.count() == 1); + if (managerErrorSpy.count() !=1) { + qWarning() << "Error signal from manager for search operation not received"; + return false; + } + + //check that we get the correct reply instance in the error signal from the manager + if (qvariant_cast(managerErrorSpy.at(0).at(0)) != reply) { + qWarning() << "Reply instance in error signal from manager is incorrect"; + return false; + } + + //check that we get the correct error from the signal of the manager + actualError = qvariant_cast(managerErrorSpy.at(0).at(1)); + if (actualError != expectedError) { + qWarning() << "Actual error code from manager signal does not match expected error code"; + qWarning() << "Actual error code =" << actualError; + qWarning() << "Expected error code = " << expectedError; + return false; + } + } + + //check that we get a finished signal + WAIT_UNTIL(finishedSpy.count() == 1); + if (finishedSpy.count() !=1) { + qWarning() << "Finished signal from reply not received"; + return false; + } + + if (reply->error() != expectedError) { + qWarning() << "Actual error code does not match expected error code"; + qWarning() << "Actual error code: " << reply->error(); + qWarning() << "Expected error code" << expectedError; + return false; + } + + if (expectedError == QPlaceReply::NoError && !reply->errorString().isEmpty()) { + qWarning() << "Expected error was no error but error string was not empty"; + qWarning() << "Error string=" << reply->errorString(); + return false; + } + + //check that we get the finished signal from the manager + WAIT_UNTIL(managerFinishedSpy.count() == 1); + if (managerFinishedSpy.count() != 1) { + qWarning() << "Finished signal from manager not received"; + return false; + } + + //check that the reply instance in the finished signal from the manager is correct + if (qvariant_cast(managerFinishedSpy.at(0).at(0)) != reply) { + qWarning() << "Reply instance in finished signal from manager is incorrect"; + return false; + } + + return true; +} + +QTEST_GUILESS_MAIN(tst_QPlaceManager) + +#include "tst_qplacemanager.moc" diff --git a/tests/auto/qplacemanager_nokia/qplacemanager_nokia.pro b/tests/auto/qplacemanager_nokia/qplacemanager_nokia.pro new file mode 100644 index 0000000..41f5998 --- /dev/null +++ b/tests/auto/qplacemanager_nokia/qplacemanager_nokia.pro @@ -0,0 +1,7 @@ +CONFIG += testcase +TARGET = tst_qplacemanager_nokia + +SOURCES += tst_qplacemanager_nokia.cpp + +QT += location testlib + diff --git a/tests/auto/qplacemanager_nokia/tst_qplacemanager_nokia.cpp b/tests/auto/qplacemanager_nokia/tst_qplacemanager_nokia.cpp new file mode 100644 index 0000000..7e1f649 --- /dev/null +++ b/tests/auto/qplacemanager_nokia/tst_qplacemanager_nokia.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include +#include + +#ifndef WAIT_UNTIL +#define WAIT_UNTIL(__expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + } while (0) +#endif + +Q_DECLARE_METATYPE(QPlaceIdReply *); + +QT_USE_NAMESPACE + +class tst_QPlaceManagerNokia : public QObject +{ + Q_OBJECT +public: + tst_QPlaceManagerNokia(); + +private Q_SLOTS: + void initTestCase(); + void unsupportedFunctions(); + +private: + bool checkSignals(QPlaceReply *reply, QPlaceReply::Error expectedError); + QGeoServiceProvider *provider; + QPlaceManager *placeManager; + QCoreApplication *coreApp; +}; + +tst_QPlaceManagerNokia::tst_QPlaceManagerNokia() +{ +} + +void tst_QPlaceManagerNokia::initTestCase() +{ + qRegisterMetaType(); + + QStringList providers = QGeoServiceProvider::availableServiceProviders(); + + QVariantMap params; + params.insert(QStringLiteral("here.app_id"), "stub"); + params.insert(QStringLiteral("here.token"), "stub"); + provider = new QGeoServiceProvider("here", params); + placeManager = provider->placeManager(); + QVERIFY(placeManager); +} + +void tst_QPlaceManagerNokia::unsupportedFunctions() +{ + QPlace place; + place.setName(QStringLiteral("Brisbane")); + QPlaceIdReply *savePlaceReply = placeManager->savePlace(place); + QVERIFY(savePlaceReply); + QVERIFY(checkSignals(savePlaceReply, QPlaceReply::UnsupportedError)); + QCOMPARE(savePlaceReply->operationType(), QPlaceIdReply::SavePlace); + + QPlaceIdReply *removePlaceReply = placeManager->removePlace(place.placeId()); + QVERIFY(removePlaceReply); + QVERIFY(checkSignals(removePlaceReply, QPlaceReply::UnsupportedError)); + QCOMPARE(removePlaceReply->operationType(), QPlaceIdReply::RemovePlace); + + QPlaceCategory category; + category.setName(QStringLiteral("Accommodation")); + QPlaceIdReply *saveCategoryReply = placeManager->saveCategory(category); + QVERIFY(saveCategoryReply); + QVERIFY(checkSignals(saveCategoryReply, QPlaceReply::UnsupportedError)); + QCOMPARE(saveCategoryReply->operationType(), QPlaceIdReply::SaveCategory); + + QPlaceIdReply *removeCategoryReply = placeManager->removeCategory(category.categoryId()); + QVERIFY(removeCategoryReply); + QVERIFY(checkSignals(removeCategoryReply, QPlaceReply::UnsupportedError)); + QCOMPARE(removeCategoryReply->operationType(), QPlaceIdReply::RemoveCategory); +} + +bool tst_QPlaceManagerNokia::checkSignals(QPlaceReply *reply, QPlaceReply::Error expectedError) +{ + QSignalSpy finishedSpy(reply, SIGNAL(finished())); + QSignalSpy errorSpy(reply, SIGNAL(error(QPlaceReply::Error,QString))); + QSignalSpy managerFinishedSpy(placeManager, SIGNAL(finished(QPlaceReply*))); + QSignalSpy managerErrorSpy(placeManager,SIGNAL(error(QPlaceReply*,QPlaceReply::Error,QString))); + + if (expectedError != QPlaceReply::NoError) { + //check that we get an error signal from the reply + WAIT_UNTIL(errorSpy.count() == 1); + if (errorSpy.count() != 1) { + qWarning() << "Error signal for operation not received"; + return false; + } + + //check that we get the correct error from the reply's signal + QPlaceReply::Error actualError = qvariant_cast(errorSpy.at(0).at(0)); + if (actualError != expectedError) { + qWarning() << "Actual error code in reply signal does not match expected error code"; + qWarning() << "Actual error code = " << actualError; + qWarning() << "Expected error coe =" << expectedError; + return false; + } + + //check that we get an error signal from the manager + WAIT_UNTIL(managerErrorSpy.count() == 1); + if (managerErrorSpy.count() !=1) { + qWarning() << "Error signal from manager for search operation not received"; + return false; + } + + //check that we get the correct reply instance in the error signal from the manager + if (qvariant_cast(managerErrorSpy.at(0).at(0)) != reply) { + qWarning() << "Reply instance in error signal from manager is incorrect"; + return false; + } + + //check that we get the correct error from the signal of the manager + actualError = qvariant_cast(managerErrorSpy.at(0).at(1)); + if (actualError != expectedError) { + qWarning() << "Actual error code from manager signal does not match expected error code"; + qWarning() << "Actual error code =" << actualError; + qWarning() << "Expected error code = " << expectedError; + return false; + } + } + + //check that we get a finished signal + WAIT_UNTIL(finishedSpy.count() == 1); + if (finishedSpy.count() !=1) { + qWarning() << "Finished signal from reply not received"; + return false; + } + + if (reply->error() != expectedError) { + qWarning() << "Actual error code does not match expected error code"; + qWarning() << "Actual error code: " << reply->error(); + qWarning() << "Expected error code" << expectedError; + return false; + } + + if (expectedError == QPlaceReply::NoError && !reply->errorString().isEmpty()) { + qWarning() << "Expected error was no error but error string was not empty"; + qWarning() << "Error string=" << reply->errorString(); + return false; + } + + //check that we get the finished signal from the manager + WAIT_UNTIL(managerFinishedSpy.count() == 1); + if (managerFinishedSpy.count() != 1) { + qWarning() << "Finished signal from manager not received"; + return false; + } + + //check that the reply instance in the finished signal from the manager is correct + if (qvariant_cast(managerFinishedSpy.at(0).at(0)) != reply) { + qWarning() << "Reply instance in finished signal from manager is incorrect"; + return false; + } + + return true; +} + +QTEST_GUILESS_MAIN(tst_QPlaceManagerNokia) + +#include "tst_qplacemanager_nokia.moc" diff --git a/tests/auto/qplacemanager_unsupported/qplacemanager_unsupported.pro b/tests/auto/qplacemanager_unsupported/qplacemanager_unsupported.pro new file mode 100644 index 0000000..57898ca --- /dev/null +++ b/tests/auto/qplacemanager_unsupported/qplacemanager_unsupported.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacemanager_unsupported + +SOURCES += tst_qplacemanager_unsupported.cpp + +CONFIG -= app_bundle + +QT += location testlib diff --git a/tests/auto/qplacemanager_unsupported/tst_qplacemanager_unsupported.cpp b/tests/auto/qplacemanager_unsupported/tst_qplacemanager_unsupported.cpp new file mode 100644 index 0000000..4171610 --- /dev/null +++ b/tests/auto/qplacemanager_unsupported/tst_qplacemanager_unsupported.cpp @@ -0,0 +1,277 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QPlaceManagerUnsupported : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void testMetadata(); + void testLocales(); + + void testGetPlaceDetails(); + void testGetPlaceContent(); + void testSearch(); + void testSearchSuggestions(); + + void testSavePlace(); + void testRemovePlace(); + void testSaveCategory(); + void testRemoveCategory(); + + void testCategories(); + + void compatiblePlace(); + + void testMatchUnsupported(); + +private: + void checkSignals(QPlaceReply *reply, QPlaceReply::Error expectedError, bool *failed); + bool checkSignals(QPlaceReply *reply, QPlaceReply::Error expectedError); + + QGeoServiceProvider *m_provider; + QPlaceManager *m_manager; +}; + +void tst_QPlaceManagerUnsupported::initTestCase() +{ + /* + * Set custom path since CI doesn't install test plugins + */ +#ifdef Q_OS_WIN + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../../plugins")); +#else + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +#endif + + m_provider = 0; + m_manager = 0; + + QStringList providers = QGeoServiceProvider::availableServiceProviders(); + QVERIFY(providers.contains("test.places.unsupported")); + + m_provider = new QGeoServiceProvider("test.places.unsupported"); + QVERIFY(m_provider); + QCOMPARE(m_provider->error(), QGeoServiceProvider::NotSupportedError); + m_provider->setAllowExperimental(true); + QCOMPARE(m_provider->error(), QGeoServiceProvider::NoError); + + m_manager = m_provider->placeManager(); + QVERIFY(m_manager); +} + +void tst_QPlaceManagerUnsupported::cleanupTestCase() +{ + delete m_provider; +} + +void tst_QPlaceManagerUnsupported::testMetadata() +{ + QCOMPARE(m_manager->managerName(), QStringLiteral("test.places.unsupported")); + QCOMPARE(m_manager->managerVersion(), 1); + QCOMPARE(m_provider->placesFeatures(), QGeoServiceProvider::NoPlacesFeatures); +} + +void tst_QPlaceManagerUnsupported::testLocales() +{ + QVERIFY(m_manager->locales().isEmpty()); + + QLocale locale(QLocale::Norwegian, QLocale::Norway); + m_manager->setLocale(locale); + + QVERIFY(m_manager->locales().isEmpty()); + + QList locales; + QLocale en_AU = QLocale(QLocale::English, QLocale::Australia); + QLocale en_UK = QLocale(QLocale::English, QLocale::UnitedKingdom); + locales << en_AU << en_UK; + m_manager->setLocales(locales); + + QVERIFY(m_manager->locales().isEmpty()); +} + +void tst_QPlaceManagerUnsupported::testGetPlaceDetails() +{ + QPlaceDetailsReply *reply = m_manager->getPlaceDetails(QString()); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; +} + +void tst_QPlaceManagerUnsupported::testGetPlaceContent() +{ + QPlaceContentReply *reply = m_manager->getPlaceContent(QPlaceContentRequest()); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; +} + +void tst_QPlaceManagerUnsupported::testSearch() +{ + QPlaceSearchReply *reply = m_manager->search(QPlaceSearchRequest()); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; +} + +void tst_QPlaceManagerUnsupported::testSearchSuggestions() +{ + QPlaceSearchSuggestionReply *reply = m_manager->searchSuggestions(QPlaceSearchRequest()); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; +} + +void tst_QPlaceManagerUnsupported::testSavePlace() +{ + QPlaceIdReply *reply = m_manager->savePlace(QPlace()); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; +} + +void tst_QPlaceManagerUnsupported::testRemovePlace() +{ + QPlaceIdReply *reply = m_manager->removePlace(QString()); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; +} + +void tst_QPlaceManagerUnsupported::testSaveCategory() +{ + QPlaceIdReply *reply = m_manager->saveCategory(QPlaceCategory()); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; +} + +void tst_QPlaceManagerUnsupported::testRemoveCategory() +{ + QPlaceIdReply *reply = m_manager->removeCategory(QString()); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; +} + +void tst_QPlaceManagerUnsupported::testCategories() +{ + QPlaceReply *reply = m_manager->initializeCategories(); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; + + QVERIFY(m_manager->childCategoryIds().isEmpty()); + QVERIFY(m_manager->parentCategoryId(QString()).isEmpty()); + QCOMPARE(m_manager->category(QString()), QPlaceCategory()); +} + +void tst_QPlaceManagerUnsupported::compatiblePlace() +{ + QPlace place; + place.setPlaceId(QStringLiteral("4-8-15-16-23-42")); + place.setName(QStringLiteral("Island")); + place.setVisibility(QLocation::PublicVisibility); + + QPlace compatPlace = m_manager->compatiblePlace(place); + QCOMPARE(compatPlace, QPlace()); +} + +void tst_QPlaceManagerUnsupported::testMatchUnsupported() +{ + QPlaceMatchReply *reply = m_manager->matchingPlaces(QPlaceMatchRequest()); + if (!checkSignals(reply, QPlaceReply::UnsupportedError)) + return; +} + +void tst_QPlaceManagerUnsupported::checkSignals(QPlaceReply *reply, + QPlaceReply::Error expectedError, bool *failed) +{ + *failed = true; + + QSignalSpy finishedSpy(reply, SIGNAL(finished())); + QSignalSpy errorSpy(reply, SIGNAL(error(QPlaceReply::Error,QString))); + QSignalSpy managerFinishedSpy(m_manager, SIGNAL(finished(QPlaceReply*))); + QSignalSpy managerErrorSpy(m_manager,SIGNAL(error(QPlaceReply*,QPlaceReply::Error,QString))); + + if (expectedError != QPlaceReply::NoError) { + //check that we get an error signal from the reply + QTRY_VERIFY(errorSpy.count() == 1); + + //check that we get the correct error from the reply's signal + QPlaceReply::Error actualError = qvariant_cast(errorSpy.at(0).at(0)); + QCOMPARE(actualError, expectedError); + + //check that we get an error signal from the manager + QTRY_VERIFY(managerErrorSpy.count() == 1); + + //check that we get the correct reply instance in the error signal from the manager + QPlaceReply *managerReply = qvariant_cast(managerErrorSpy.at(0).at(0)); + QCOMPARE(managerReply, reply); + + //check that we get the correct error from the signal of the manager + actualError = qvariant_cast(managerErrorSpy.at(0).at(1)); + QCOMPARE(actualError, expectedError); + } + + //check that we get a finished signal + QTRY_VERIFY(finishedSpy.count() == 1); + + QCOMPARE(reply->error(), expectedError); + + QCOMPARE(reply->errorString().isEmpty(), expectedError == QPlaceReply::NoError); + + //check that we get the finished signal from the manager + QTRY_VERIFY(managerFinishedSpy.count() == 1); + + //check that the reply instance in the finished signal from the manager is correct + QPlaceReply *managerReply = qvariant_cast(managerFinishedSpy.at(0).at(0)); + QCOMPARE(managerReply, reply); + + *failed = false; +} + +bool tst_QPlaceManagerUnsupported::checkSignals(QPlaceReply *reply, + QPlaceReply::Error expectedError) +{ + bool failed; + checkSignals(reply, expectedError, &failed); + return failed; +} + +QTEST_GUILESS_MAIN(tst_QPlaceManagerUnsupported) + +#include "tst_qplacemanager_unsupported.moc" diff --git a/tests/auto/qplacematchreply/qplacematchreply.pro b/tests/auto/qplacematchreply/qplacematchreply.pro new file mode 100644 index 0000000..00c1dcd --- /dev/null +++ b/tests/auto/qplacematchreply/qplacematchreply.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacematchreply + +SOURCES += tst_qplacematchreply.cpp + +QT += location testlib diff --git a/tests/auto/qplacematchreply/tst_qplacematchreply.cpp b/tests/auto/qplacematchreply/tst_qplacematchreply.cpp new file mode 100644 index 0000000..34ee7ba --- /dev/null +++ b/tests/auto/qplacematchreply/tst_qplacematchreply.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class TestMatchReply : public QPlaceMatchReply +{ + Q_OBJECT +public: + TestMatchReply(QObject *parent) : QPlaceMatchReply(parent) {} + TestMatchReply() {} + + void setPlaces(const QList &places) { + QPlaceMatchReply::setPlaces(places); + } + + void setRequest(const QPlaceMatchRequest &request) { + QPlaceMatchReply::setRequest(request); + } +}; + +class tst_QPlaceMatchReply : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceMatchReply(); + +private Q_SLOTS: + void constructorTest(); + void typeTest(); + void requestTest(); +// void resultsTest(); +}; + +tst_QPlaceMatchReply::tst_QPlaceMatchReply() +{ +} + +void tst_QPlaceMatchReply::constructorTest() +{ + QPlaceMatchReply *reply = new TestMatchReply(this); + QVERIFY(reply->parent() == this); + delete reply; +} + +void tst_QPlaceMatchReply::typeTest() +{ + TestMatchReply *reply = new TestMatchReply(this); + QVERIFY(reply->type() == QPlaceReply::MatchReply); + delete reply; +} + +void tst_QPlaceMatchReply::requestTest() +{ + TestMatchReply *reply = new TestMatchReply(this); + QPlaceMatchRequest request; + + QPlace place1; + place1.setName(QStringLiteral("place1")); + + QPlace place2; + place2.setName(QStringLiteral("place2")); + + QList places; + places << place1 << place2; + + request.setPlaces(places); + + reply->setRequest(request); + QCOMPARE(reply->request(), request); + + reply->setRequest(QPlaceMatchRequest()); + QCOMPARE(reply->request(), QPlaceMatchRequest()); + delete reply; +} + + +QTEST_APPLESS_MAIN(tst_QPlaceMatchReply) + +#include "tst_qplacematchreply.moc" diff --git a/tests/auto/qplacematchrequest/qplacematchrequest.pro b/tests/auto/qplacematchrequest/qplacematchrequest.pro new file mode 100644 index 0000000..558cd2e --- /dev/null +++ b/tests/auto/qplacematchrequest/qplacematchrequest.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacematchrequest +SOURCES += tst_qplacematchrequest.cpp + +QT += location testlib diff --git a/tests/auto/qplacematchrequest/tst_qplacematchrequest.cpp b/tests/auto/qplacematchrequest/tst_qplacematchrequest.cpp new file mode 100644 index 0000000..03ba59a --- /dev/null +++ b/tests/auto/qplacematchrequest/tst_qplacematchrequest.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include + +QT_USE_NAMESPACE + +class tst_QPlaceMatchRequest : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceMatchRequest(); + +private Q_SLOTS: + void constructorTest(); + void placesTest(); + void resultsTest(); + void parametersTest(); + void clearTest(); +}; + +tst_QPlaceMatchRequest::tst_QPlaceMatchRequest() +{ +} + +void tst_QPlaceMatchRequest::constructorTest() +{ + QPlaceMatchRequest request; + QVariantMap params; + params.insert(QStringLiteral("key"), QStringLiteral("val")); + + QPlace place1; + place1.setName(QStringLiteral("place1")); + + QPlace place2; + place2.setName(QStringLiteral("place2")); + + QList places; + places << place1 << place2; + + request.setPlaces(places); + request.setParameters(params); + + QPlaceMatchRequest copy(request); + QCOMPARE(copy, request); + QCOMPARE(copy.places(), places); + QCOMPARE(copy.parameters(), params); +} + +void tst_QPlaceMatchRequest::placesTest() +{ + QPlaceMatchRequest request; + QCOMPARE(request.places().count(), 0); + + QPlace place1; + place1.setName(QStringLiteral("place1")); + + QPlace place2; + place2.setName(QStringLiteral("place2")); + + QList places; + places << place1 << place2; + + request.setPlaces(places); + QCOMPARE(request.places(), places); + + request.setPlaces(QList()); + QCOMPARE(request.places().count(), 0); +} + +void tst_QPlaceMatchRequest::resultsTest() +{ + QPlaceMatchRequest request; + QCOMPARE(request.places().count(), 0); + + QPlace place1; + place1.setName(QStringLiteral("place1")); + QPlaceResult result1; + result1.setPlace(place1); + + QPlace place2; + place2.setName(QStringLiteral("place2")); + QPlaceResult result2; + result2.setPlace(place2); + + QList results; + results << result1 << result2; + + request.setResults(results); + + QCOMPARE(request.places().count(), 2); + QCOMPARE(request.places().at(0), place1); + QCOMPARE(request.places().at(1), place2); + + request.setResults(QList()); + QCOMPARE(request.places().count(), 0); +} + +void tst_QPlaceMatchRequest::parametersTest() +{ + QPlaceMatchRequest request; + QVERIFY(request.parameters().isEmpty()); + + QVariantMap params; + params.insert(QStringLiteral("key"), QStringLiteral("value")); + + request.setParameters(params); + QCOMPARE(request.parameters(), params); +} + +void tst_QPlaceMatchRequest::clearTest() +{ + QPlaceMatchRequest request; + QVariantMap params; + params.insert(QStringLiteral("key"), QStringLiteral("value")); + + QPlace place1; + place1.setName(QStringLiteral("place1")); + + QPlace place2; + place2.setName(QStringLiteral("place2")); + + QList places; + places << place1 << place2; + + request.setPlaces(places); + request.setParameters(params); + + request.clear(); + QVERIFY(request.places().isEmpty()); + QVERIFY(request.parameters().isEmpty()); +} + +QTEST_APPLESS_MAIN(tst_QPlaceMatchRequest) + +#include "tst_qplacematchrequest.moc" diff --git a/tests/auto/qplaceperiod/qplaceperiod.pro b/tests/auto/qplaceperiod/qplaceperiod.pro new file mode 100644 index 0000000..c680a75 --- /dev/null +++ b/tests/auto/qplaceperiod/qplaceperiod.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplaceperiod + +SOURCES += tst_qplaceperiod.cpp + +QT += location testlib +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/qplaceperiod/tst_qplaceperiod.cpp b/tests/auto/qplaceperiod/tst_qplaceperiod.cpp new file mode 100644 index 0000000..78db546 --- /dev/null +++ b/tests/auto/qplaceperiod/tst_qplaceperiod.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QPlacePeriod : public QObject +{ + Q_OBJECT + +public: + tst_QPlacePeriod(); + +private Q_SLOTS: + void constructorTest(); + void startDateTest(); + void startTimeTest(); + void endDateTest(); + void endTimeTest(); + void operatorsTest(); +}; + +tst_QPlacePeriod::tst_QPlacePeriod() +{ +} + +void tst_QPlacePeriod::constructorTest() +{ + QPlacePeriod testObj; + testObj.setStartTime(QTime::currentTime()); + QPlacePeriod *testObjPtr = new QPlacePeriod(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(testObjPtr->startTime() == testObj.startTime(), "Copy constructor - start time"); + delete testObjPtr; +} + +void tst_QPlacePeriod::startDateTest() +{ + QPlacePeriod testObj; + QVERIFY2(testObj.startDate().isNull() == true, "Wrong default value"); + QDate date = QDate::currentDate(); + testObj.setStartDate(date); + QVERIFY2(testObj.startDate() == date, "Wrong value returned"); +} + +void tst_QPlacePeriod::startTimeTest() +{ + QPlacePeriod testObj; + QVERIFY2(testObj.startTime().isNull() == true, "Wrong default value"); + QTime time = QTime::currentTime(); + testObj.setStartTime(time); + QVERIFY2(testObj.startTime() == time, "Wrong value returned"); +} + +void tst_QPlacePeriod::endDateTest() +{ + QPlacePeriod testObj; + QVERIFY2(testObj.endDate().isNull() == true, "Wrong default value"); + QDate date = QDate::currentDate(); + testObj.setEndDate(date); + QVERIFY2(testObj.endDate() == date, "Wrong value returned"); +} + +void tst_QPlacePeriod::endTimeTest() +{ + QPlacePeriod testObj; + QVERIFY2(testObj.endTime().isNull() == true, "Wrong default value"); + QTime time = QTime::currentTime(); + testObj.setEndTime(time); + QVERIFY2(testObj.endTime() == time, "Wrong value returned"); +} + +void tst_QPlacePeriod::operatorsTest() +{ + QPlacePeriod testObj; + QTime time = QTime::currentTime(); + testObj.setEndTime(time); + QPlacePeriod testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj.setEndTime(QTime::currentTime().addSecs(102021)); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +QTEST_APPLESS_MAIN(tst_QPlacePeriod); + +#include "tst_qplaceperiod.moc" diff --git a/tests/auto/qplaceratings/qplaceratings.pro b/tests/auto/qplaceratings/qplaceratings.pro new file mode 100644 index 0000000..b17b6aa --- /dev/null +++ b/tests/auto/qplaceratings/qplaceratings.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplaceratings + +SOURCES += tst_qplaceratings.cpp + +QT += location testlib diff --git a/tests/auto/qplaceratings/tst_qplaceratings.cpp b/tests/auto/qplaceratings/tst_qplaceratings.cpp new file mode 100644 index 0000000..4de19dc --- /dev/null +++ b/tests/auto/qplaceratings/tst_qplaceratings.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QPlaceRatings : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceRatings(); + +private Q_SLOTS: + void constructorTest(); + void averageTest(); + void countTest(); + void operatorsTest(); + void isEmptyTest(); +}; + +tst_QPlaceRatings::tst_QPlaceRatings() +{ +} + +void tst_QPlaceRatings::constructorTest() +{ + QPlaceRatings testObj; + Q_UNUSED(testObj); + + QPlaceRatings *testObjPtr = new QPlaceRatings(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(testObjPtr->count() == 0, "Copy constructor - wrong count"); + QVERIFY2(testObjPtr->average() == 0, "Copy constructor - wrong average"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + delete testObjPtr; +} + +void tst_QPlaceRatings::averageTest() +{ + QPlaceRatings testObj; + QVERIFY2(qFuzzyCompare(testObj.average(), 0) , "Wrong default average"); + testObj.setAverage(-10.23); + QCOMPARE(testObj.average(), -10.23); +} + +void tst_QPlaceRatings::countTest() +{ + QPlaceRatings testObj; + QVERIFY2(testObj.count() == 0, "Wrong default value"); + testObj.setCount(-1002); + QVERIFY2(testObj.count() == -1002, "Wrong value returned"); +} + +void tst_QPlaceRatings::operatorsTest() +{ + QPlaceRatings testObj; + testObj.setAverage(0.123); + QPlaceRatings testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setCount(-10); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +void tst_QPlaceRatings::isEmptyTest() +{ + QPlaceRatings ratings; + + QVERIFY(ratings.isEmpty()); + + ratings.setCount(1); + QVERIFY(!ratings.isEmpty()); + ratings.setCount(0); + QVERIFY(ratings.isEmpty()); + + ratings.setMaximum(1); + QVERIFY(!ratings.isEmpty()); + ratings.setMaximum(0); + QVERIFY(ratings.isEmpty()); + + ratings.setAverage(1); + QVERIFY(!ratings.isEmpty()); + ratings.setAverage(0); + QVERIFY(ratings.isEmpty()); +} + +QTEST_APPLESS_MAIN(tst_QPlaceRatings); + +#include "tst_qplaceratings.moc" diff --git a/tests/auto/qplacereply/qplacereply.pro b/tests/auto/qplacereply/qplacereply.pro new file mode 100644 index 0000000..3d18e71 --- /dev/null +++ b/tests/auto/qplacereply/qplacereply.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacereply + +SOURCES += tst_qplacereply.cpp + +QT += location testlib diff --git a/tests/auto/qplacereply/tst_qplacereply.cpp b/tests/auto/qplacereply/tst_qplacereply.cpp new file mode 100644 index 0000000..a67028d --- /dev/null +++ b/tests/auto/qplacereply/tst_qplacereply.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class TestReply : public QPlaceReply +{ +public: + TestReply(QObject *parent) : QPlaceReply(parent) {} + void setFinished(bool finished) { QPlaceReply::setFinished(finished); } + void setError(QPlaceReply::Error error, const QString &errorString) { + QPlaceReply::setError(error,errorString); + } +}; + +class tst_QPlaceReply : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceReply(); + +private Q_SLOTS: + void constructorTest(); + void typeTest(); + void finishedTest(); + void errorTest(); +}; + +tst_QPlaceReply::tst_QPlaceReply() +{ + +} + +void tst_QPlaceReply::constructorTest() +{ + TestReply *reply = new TestReply(this); + QCOMPARE(reply->parent(), this); + delete reply; +} + +void tst_QPlaceReply::typeTest() +{ + TestReply *reply = new TestReply(this); + QCOMPARE(reply->type(), QPlaceReply::Reply); + + delete reply; +} + +void tst_QPlaceReply::finishedTest() +{ + TestReply *reply = new TestReply(this); + QCOMPARE(reply->isFinished(), false); + reply->setFinished(true); + QCOMPARE(reply->isFinished(), true); + + delete reply; +} + +void tst_QPlaceReply::errorTest() +{ + TestReply *reply = new TestReply(this); + QCOMPARE(reply->error(), QPlaceReply::NoError); + QCOMPARE(reply->errorString(), QString()); + + reply->setError(QPlaceReply::CommunicationError, QStringLiteral("Could not connect to server")); + QCOMPARE(reply->error(), QPlaceReply::CommunicationError); + QCOMPARE(reply->errorString(), QStringLiteral("Could not connect to server")); + + reply->setError(QPlaceReply::NoError, QString()); + QCOMPARE(reply->error(), QPlaceReply::NoError); + QCOMPARE(reply->errorString(), QString()); + + delete reply; +} + +QTEST_APPLESS_MAIN(tst_QPlaceReply) + +#include "tst_qplacereply.moc" diff --git a/tests/auto/qplaceresult/qplaceresult.pro b/tests/auto/qplaceresult/qplaceresult.pro new file mode 100644 index 0000000..966c240 --- /dev/null +++ b/tests/auto/qplaceresult/qplaceresult.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplaceresult + +SOURCES += tst_qplaceresult.cpp + +QT += location testlib diff --git a/tests/auto/qplaceresult/tst_qplaceresult.cpp b/tests/auto/qplaceresult/tst_qplaceresult.cpp new file mode 100644 index 0000000..4074d0d --- /dev/null +++ b/tests/auto/qplaceresult/tst_qplaceresult.cpp @@ -0,0 +1,270 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#include "../utils/qlocationtestutils_p.h" + +QT_USE_NAMESPACE + +class tst_QPlaceResult : public QObject +{ + Q_OBJECT + +public: + QPlaceResult initialSubObject(); + bool checkType(const QPlaceSearchResult &); + void detach(QPlaceSearchResult *); + void setSubClassProperty(QPlaceResult *); + +private Q_SLOTS: + void constructorTest(); + void title(); + void icon(); + void distance(); + void place(); + void sponsored(); + void conversion(); +}; + +QPlaceResult tst_QPlaceResult::initialSubObject() +{ + QPlaceResult placeResult; + placeResult.setTitle(QStringLiteral("title")); + + QPlaceIcon icon; + QVariantMap parameters; + parameters.insert(QPlaceIcon::SingleUrl, + QUrl(QStringLiteral("file:///opt/icons/icon.png"))); + icon.setParameters(parameters); + placeResult.setIcon(icon); + + QPlace place; + place.setName(QStringLiteral("place")); + placeResult.setPlace(place); + + placeResult.setDistance(5); + placeResult.setSponsored(true); + + return placeResult; +} + +bool tst_QPlaceResult::checkType(const QPlaceSearchResult &result) +{ + return result.type() == QPlaceSearchResult::PlaceResult; +} + +void tst_QPlaceResult::detach(QPlaceSearchResult * result) +{ + result->setTitle("title"); +} + +void tst_QPlaceResult::setSubClassProperty(QPlaceResult *result) +{ + result->setSponsored(false); +} + +void tst_QPlaceResult::constructorTest() +{ + QPlaceResult result; + QCOMPARE(result.type(), QPlaceSearchResult::PlaceResult); + + result.setTitle(QStringLiteral("title")); + + QPlaceIcon icon; + QVariantMap parameters; + parameters.insert(QStringLiteral("paramKey"), QStringLiteral("paramValue")); + icon.setParameters(parameters); + result.setIcon(icon); + + QPlace place; + place.setName("place"); + result.setPlace(place); + + result.setDistance(500); + result.setSponsored(true); + + //check copy constructor + QPlaceResult result2(result); + QCOMPARE(result2.title(), QStringLiteral("title")); + QCOMPARE(result2.icon(), icon); + QCOMPARE(result2.place(), place); + QVERIFY(qFuzzyCompare(result.distance(), 500)); + QCOMPARE(result2.isSponsored(), true); + + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + //check results are the same after detachment of underlying shared data pointer + result2.setTitle("title"); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + //check construction of SearchResult using a PlaceResult + QPlaceSearchResult searchResult(result); + QCOMPARE(searchResult.title(), QStringLiteral("title")); + QCOMPARE(searchResult.icon(), icon); + QVERIFY(QLocationTestUtils::compareEquality(searchResult, result)); + QVERIFY(searchResult.type() == QPlaceSearchResult::PlaceResult); + result2 = searchResult; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + //check construction of a SearchResult using a SearchResult + //that is actually a PlaceResult underneath + QPlaceSearchResult searchResult2(searchResult); + QCOMPARE(searchResult2.title(), QStringLiteral("title")); + QCOMPARE(searchResult2.icon(), icon); + QVERIFY(QLocationTestUtils::compareEquality(searchResult2, result)); + QVERIFY(QLocationTestUtils::compareEquality(searchResult, searchResult2)); + QVERIFY(searchResult2.type() == QPlaceSearchResult::PlaceResult); + result2 = searchResult2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceResult::title() +{ + QPlaceResult result; + QVERIFY(result.title().isEmpty()); + + result.setTitle(QStringLiteral("title")); + QCOMPARE(result.title(), QStringLiteral("title")); + + result.setTitle(QString()); + QVERIFY(result.title().isEmpty()); + + QPlaceResult result2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + result2.setTitle("title"); + QVERIFY(QLocationTestUtils::compareInequality(result, result2)); + + result.setTitle("title"); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceResult::icon() +{ + QPlaceResult result; + QVERIFY(result.icon().isEmpty()); + + QPlaceIcon icon; + QVariantMap iconParams; + iconParams.insert(QStringLiteral("paramKey"), QStringLiteral("paramValue")); + icon.setParameters(iconParams); + result.setIcon(icon); + QCOMPARE(result.icon(), icon); + + result.setIcon(QPlaceIcon()); + QVERIFY(result.icon().isEmpty()); + + QPlaceResult result2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + result2.setIcon(icon); + QVERIFY(QLocationTestUtils::compareInequality(result, result2)); + + result.setIcon(icon); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceResult::distance() +{ + QPlaceResult result; + QVERIFY(qIsNaN(result.distance())); + + result.setDistance(3.14); + QVERIFY(qFuzzyCompare(result.distance(), 3.14)); + + result.setDistance(qQNaN()); + QVERIFY(qIsNaN(result.distance())); + + QPlaceResult result2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + result2.setDistance(3.14); + QVERIFY(QLocationTestUtils::compareInequality(result, result2)); + + result.setDistance(3.14); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceResult::place() +{ + QPlaceResult result; + QCOMPARE(result.place(), QPlace()); + + QPlace place; + place.setName("place"); + result.setPlace (place); + QCOMPARE(result.place(), place); + + result.setPlace(QPlace()); + QCOMPARE(result.place(), QPlace()); + + QPlaceResult result2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + result2.setPlace(place); + QVERIFY(QLocationTestUtils::compareInequality(result, result2)); + + result.setPlace(place); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceResult::sponsored() +{ + QPlaceResult result; + QCOMPARE(result.isSponsored(), false); + + result.setSponsored(true); + QCOMPARE(result.isSponsored(), true); + + result.setSponsored(false); + QCOMPARE(result.isSponsored(), false); + + QPlaceResult result2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + result2.setSponsored(true); + QVERIFY(QLocationTestUtils::compareInequality(result, result2)); + + result.setSponsored(true); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceResult::conversion() +{ + QLocationTestUtils::testConversion(this); +} + +QTEST_APPLESS_MAIN(tst_QPlaceResult) + +#include "tst_qplaceresult.moc" diff --git a/tests/auto/qplacereview/qplacereview.pro b/tests/auto/qplacereview/qplacereview.pro new file mode 100644 index 0000000..950e7a3 --- /dev/null +++ b/tests/auto/qplacereview/qplacereview.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacereview + +SOURCES += tst_qplacereview.cpp + +QT += location testlib diff --git a/tests/auto/qplacereview/tst_qplacereview.cpp b/tests/auto/qplacereview/tst_qplacereview.cpp new file mode 100644 index 0000000..7f7edfe --- /dev/null +++ b/tests/auto/qplacereview/tst_qplacereview.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "../utils/qlocationtestutils_p.h" + +QT_USE_NAMESPACE + +class tst_QPlaceReview : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceReview(); + + //needed for QLocationTestUtils::testConversion + QPlaceReview initialSubObject(); + bool checkType(const QPlaceContent &); + void detach(QPlaceContent *); + void setSubClassProperty(QPlaceReview *); + +private Q_SLOTS: + void constructorTest(); + void supplierTest(); + void dateTest(); + void textTest(); + void languageTest(); + void ratingTest(); + void reviewIdTest(); + void titleTest(); + void userTest(); + void operatorsTest(); + void conversionTest(); +}; + +tst_QPlaceReview::tst_QPlaceReview() +{ +} + +QPlaceReview tst_QPlaceReview::initialSubObject() +{ + QPlaceUser user; + user.setName("user 1"); + user.setUserId("0001"); + + QPlaceSupplier supplier; + supplier.setName("supplier"); + supplier.setSupplierId("1"); + + QPlaceReview review; + review.setTitle("title"); + review.setText("text"); + review.setRating(4.5); + review.setLanguage("en"); + review.setDateTime(QDateTime::fromString("01:02 03/04/2000", + "hh:mm dd/MM/yyyy")); + review.setUser(user); + review.setSupplier(supplier); + review.setAttribution("attribution"); + + return review; +} + +bool tst_QPlaceReview::checkType(const QPlaceContent &content) +{ + return content.type() == QPlaceContent::ReviewType; +} + +void tst_QPlaceReview::detach(QPlaceContent *content) +{ + content->setAttribution("attribution"); +} + +void tst_QPlaceReview::setSubClassProperty(QPlaceReview *review) +{ + review->setTitle("new title"); +} + +void tst_QPlaceReview::constructorTest() +{ + QPlaceReview testObj; + testObj.setLanguage("testId"); + QPlaceReview *testObjPtr = new QPlaceReview(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + delete testObjPtr; +} + +void tst_QPlaceReview::supplierTest() +{ + QPlaceReview testObj; + QVERIFY2(testObj.supplier().supplierId() == QString(), "Wrong default value"); + QPlaceSupplier sup; + sup.setName("testName1"); + sup.setSupplierId("testId"); + testObj.setSupplier(sup); + QVERIFY2(testObj.supplier() == sup, "Wrong value returned"); +} + +void tst_QPlaceReview::dateTest() +{ + QPlaceReview testObj; + QCOMPARE(testObj.dateTime(), QDateTime()); + + QDateTime dt = QDateTime::currentDateTime(); + testObj.setDateTime(dt); + QCOMPARE(testObj.dateTime(), dt); +} + +void tst_QPlaceReview::textTest() +{ + QPlaceReview testObj; + QVERIFY2(testObj.text() == QString(), "Wrong default value"); + testObj.setText("testText"); + QVERIFY2(testObj.text() == "testText", "Wrong value returned"); +} + +void tst_QPlaceReview::languageTest() +{ + QPlaceReview testObj; + QVERIFY2(testObj.language() == QString(), "Wrong default value"); + testObj.setLanguage("testText"); + QVERIFY2(testObj.language() == "testText", "Wrong value returned"); +} + +void tst_QPlaceReview::ratingTest() +{ + QPlaceReview testObj; + QVERIFY2(testObj.rating() == 0, "Wrong default value"); + testObj.setRating(-10); + QCOMPARE(testObj.rating(), -10.0); + testObj.setRating(3.4); + QCOMPARE(testObj.rating(), 3.4); +} + +void tst_QPlaceReview::operatorsTest() +{ + QPlaceReview testObj; + testObj.setText("testValue"); + QPlaceReview testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setLanguage("testValue2"); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +void tst_QPlaceReview::reviewIdTest() +{ + QPlaceReview testObj; + QVERIFY2(testObj.reviewId() == QString(), "Wrong default value"); + testObj.setReviewId("testText"); + QVERIFY2(testObj.reviewId() == "testText", "Wrong value returned"); +} +void tst_QPlaceReview::titleTest() +{ + QPlaceReview testObj; + QVERIFY2(testObj.title() == QString(), "Wrong default value"); + testObj.setTitle("testText"); + QVERIFY2(testObj.title() == "testText", "Wrong value returned"); +} + +void tst_QPlaceReview::userTest() +{ + QPlaceReview review; + QVERIFY(review.user().userId().isEmpty()); + QVERIFY(review.user().name().isEmpty()); + QPlaceUser user; + user.setUserId(QStringLiteral("11111")); + user.setName(QStringLiteral("Bob")); + + review.setUser(user); + QCOMPARE(review.user().userId(), QStringLiteral("11111")); + QCOMPARE(review.user().name(), QStringLiteral("Bob")); + + review.setUser(QPlaceUser()); + QVERIFY(review.user().userId().isEmpty()); + QVERIFY(review.user().name().isEmpty()); +} + +void tst_QPlaceReview::conversionTest() +{ + QLocationTestUtils::testConversion(this); +} + +QTEST_APPLESS_MAIN(tst_QPlaceReview) + +#include "tst_qplacereview.moc" diff --git a/tests/auto/qplacesearchreply/qplacesearchreply.pro b/tests/auto/qplacesearchreply/qplacesearchreply.pro new file mode 100644 index 0000000..8a57839 --- /dev/null +++ b/tests/auto/qplacesearchreply/qplacesearchreply.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacesearchreply + +SOURCES += tst_qplacesearchreply.cpp + +QT += location testlib diff --git a/tests/auto/qplacesearchreply/tst_qplacesearchreply.cpp b/tests/auto/qplacesearchreply/tst_qplacesearchreply.cpp new file mode 100644 index 0000000..14c951e --- /dev/null +++ b/tests/auto/qplacesearchreply/tst_qplacesearchreply.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + + +QT_USE_NAMESPACE + +class TestSearchReply : public QPlaceSearchReply +{ + Q_OBJECT +public: + TestSearchReply(QObject *parent) : QPlaceSearchReply(parent) {} + TestSearchReply() {} + + void setResults(const QList &results) { + QPlaceSearchReply::setResults(results); + } + + void setRequest(const QPlaceSearchRequest &request) { + QPlaceSearchReply::setRequest(request); + } +}; + +class tst_QPlaceSearchReply : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceSearchReply(); + +private Q_SLOTS: + void constructorTest(); + void typeTest(); + void requestTest(); + void resultsTest(); +}; + +tst_QPlaceSearchReply::tst_QPlaceSearchReply() +{ +} + +void tst_QPlaceSearchReply::constructorTest() +{ + TestSearchReply *reply = new TestSearchReply(this); + QVERIFY(reply->parent() == this); + delete reply; +} + +void tst_QPlaceSearchReply::typeTest() +{ + TestSearchReply *reply = new TestSearchReply(this); + QVERIFY(reply->type() == QPlaceReply::SearchReply); + delete reply; +} + +void tst_QPlaceSearchReply::requestTest() +{ + TestSearchReply *reply = new TestSearchReply(this); + QPlaceSearchRequest request; + request.setLimit(10); + + QGeoCircle circle; + circle.setCenter(QGeoCoordinate(10,20)); + request.setSearchArea(circle); + + request.setSearchTerm("pizza"); + + reply->setRequest(request); + QCOMPARE(reply->request(), request); + reply->setRequest(QPlaceSearchRequest()); + QCOMPARE(reply->request(), QPlaceSearchRequest()); + delete reply; +} + +void tst_QPlaceSearchReply::resultsTest() +{ + TestSearchReply *reply = new TestSearchReply(this); + QList results; + QPlace winterfell; + winterfell.setName("Winterfell"); + QPlace casterlyRock; + casterlyRock.setName("Casterly Rock"); + QPlace stormsEnd; + stormsEnd.setName("Storm's end"); + + QPlaceResult result1; + result1.setPlace(winterfell); + QPlaceResult result2; + result2.setPlace(casterlyRock); + QPlaceResult result3; + result3.setPlace(stormsEnd); + results << result1 << result2 << result3; + + reply->setResults(results); + QCOMPARE(reply->results(), results); + reply->setResults(QList()); + QCOMPARE(reply->results(), QList()); + delete reply; +} + +QTEST_APPLESS_MAIN(tst_QPlaceSearchReply) + +#include "tst_qplacesearchreply.moc" diff --git a/tests/auto/qplacesearchrequest/qplacesearchrequest.pro b/tests/auto/qplacesearchrequest/qplacesearchrequest.pro new file mode 100644 index 0000000..45d5d1a --- /dev/null +++ b/tests/auto/qplacesearchrequest/qplacesearchrequest.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacesearchrequest +SOURCES += tst_qplacesearchrequest.cpp + +QT += location testlib diff --git a/tests/auto/qplacesearchrequest/tst_qplacesearchrequest.cpp b/tests/auto/qplacesearchrequest/tst_qplacesearchrequest.cpp new file mode 100644 index 0000000..959fede --- /dev/null +++ b/tests/auto/qplacesearchrequest/tst_qplacesearchrequest.cpp @@ -0,0 +1,268 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QPlaceSearchRequest : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceSearchRequest(); + +private Q_SLOTS: + void constructorTest(); + void searchTermTest(); + void categoriesTest(); + void boundingCircleTest(); + void boundingBoxTest(); + void searchAreaTest(); + void visibilityScopeTest(); + void relevanceHintTest(); + void searchContextTest(); + void operatorsTest(); + void clearTest(); +}; + +tst_QPlaceSearchRequest::tst_QPlaceSearchRequest() +{ +} + +void tst_QPlaceSearchRequest::constructorTest() +{ + QPlaceSearchRequest testObj; + Q_UNUSED(testObj); + + QPlaceSearchRequest *testObjPtr = new QPlaceSearchRequest(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + delete testObjPtr; +} + +void tst_QPlaceSearchRequest::searchTermTest() +{ + QPlaceSearchRequest testObj; + QVERIFY2(testObj.searchTerm() == QString(), "Wrong default value"); + testObj.setSearchTerm("testText"); + QVERIFY2(testObj.searchTerm() == "testText", "Wrong value returned"); +} + +void tst_QPlaceSearchRequest::categoriesTest() +{ + QPlaceSearchRequest testObj; + QVERIFY2(testObj.categories().count() == 0, "Wrong default value"); + QPlaceCategory cat; + cat.setCategoryId("45346"); + testObj.setCategory(cat); + QVERIFY2(testObj.categories().count() == 1, "Wrong categories count returned"); + QVERIFY2(testObj.categories()[0] == cat, "Wrong category returned"); + + testObj.setCategory(QPlaceCategory()); + QVERIFY(testObj.categories().isEmpty()); +} + +void tst_QPlaceSearchRequest::boundingCircleTest() +{ + QPlaceSearchRequest query; + QVERIFY2(query.searchArea() == QGeoShape(), "Wrong default value"); + QGeoCircle circle; + circle.setCenter(QGeoCoordinate(30,20)); + circle.setRadius(500.0); + query.setSearchArea(circle); + + QVERIFY(query.searchArea() != QGeoShape()); + QVERIFY(query.searchArea().type() == QGeoShape::CircleType); + QVERIFY(query.searchArea() == circle); + + QGeoCircle retrievedCircle = query.searchArea(); + QVERIFY2(retrievedCircle.center() == QGeoCoordinate(30,20), "Wrong value returned"); + QVERIFY2(retrievedCircle.radius() == 500.0, "Wrong value returned"); + query.clear(); + QVERIFY2(query.searchArea() == QGeoShape(), "Search area not cleared"); +} + +void tst_QPlaceSearchRequest::boundingBoxTest() +{ + QPlaceSearchRequest query; + QVERIFY2(query.searchArea() == QGeoShape(), "Wrong default value"); + QGeoRectangle box; + + box.setTopLeft(QGeoCoordinate(30,20)); + box.setBottomRight(QGeoCoordinate(10,50)); + query.setSearchArea(box); + + QVERIFY(query.searchArea() != QGeoShape()); + QVERIFY(query.searchArea().type() == QGeoShape::RectangleType); + QVERIFY(query.searchArea() == box); + + QGeoRectangle retrievedBox = query.searchArea(); + QVERIFY2(retrievedBox.topLeft() == QGeoCoordinate(30,20), "Wrong value returned"); + QVERIFY2(retrievedBox.bottomRight() == QGeoCoordinate(10,50), "Wrong value returned"); + + query.clear(); + QVERIFY2(query.searchArea() == QGeoShape(), "Wrong cleared value returned"); +} + +void tst_QPlaceSearchRequest::searchAreaTest() +{ + //test assignment of new search area over an old search area + QPlaceSearchRequest *query = new QPlaceSearchRequest; + QGeoCircle circle; + circle.setCenter(QGeoCoordinate(30,20)); + circle.setRadius(500.0); + query->setSearchArea(circle); + + QVERIFY(query->searchArea() == circle); + QGeoRectangle box; + box.setTopLeft(QGeoCoordinate(30,20)); + box.setBottomRight(QGeoCoordinate(10,50)); + query->setSearchArea(box); + QVERIFY2(query->searchArea() == box, "New search area not assigned"); +} + +void tst_QPlaceSearchRequest::visibilityScopeTest() +{ + QPlaceSearchRequest query; + QVERIFY2(query.visibilityScope() == QLocation::UnspecifiedVisibility, "Wrong default value"); + + query.setVisibilityScope(QLocation::DeviceVisibility); + QCOMPARE(query.visibilityScope(), QLocation::DeviceVisibility); + + query.setVisibilityScope(QLocation::DeviceVisibility | QLocation::PublicVisibility); + QVERIFY(query.visibilityScope() & QLocation::DeviceVisibility); + QVERIFY(!(query.visibilityScope() & QLocation::PrivateVisibility)); + QVERIFY(query.visibilityScope() & QLocation::PublicVisibility); +} + +void tst_QPlaceSearchRequest::relevanceHintTest() +{ + QPlaceSearchRequest request; + QCOMPARE(request.relevanceHint(), QPlaceSearchRequest::UnspecifiedHint); + request.setRelevanceHint(QPlaceSearchRequest::DistanceHint); + QCOMPARE(request.relevanceHint(), QPlaceSearchRequest::DistanceHint); + request.setRelevanceHint(QPlaceSearchRequest::UnspecifiedHint); + QCOMPARE(request.relevanceHint(), QPlaceSearchRequest::UnspecifiedHint); +} + +void tst_QPlaceSearchRequest::searchContextTest() +{ + QPlaceSearchRequest request; + QVERIFY(!request.searchContext().value().isValid()); + request.setSearchContext(QUrl(QStringLiteral("http://www.example.com/"))); + QCOMPARE(request.searchContext().value(), QUrl(QStringLiteral("http://www.example.com/"))); +} + +void tst_QPlaceSearchRequest::operatorsTest() +{ + QPlaceSearchRequest testObj; + testObj.setSearchTerm(QStringLiteral("testValue")); + QPlaceSearchRequest testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setSearchTerm(QStringLiteral("abc")); + QVERIFY2(testObj != testObj2, "Object should be different"); + testObj2.setSearchTerm(QStringLiteral("testValue")); + QVERIFY(testObj == testObj2); + + QGeoRectangle b1(QGeoCoordinate(20,20), QGeoCoordinate(10,30)); + QGeoRectangle b2(QGeoCoordinate(20,20), QGeoCoordinate(10,30)); + QGeoRectangle b3(QGeoCoordinate(40,40), QGeoCoordinate(10,40)); + + //testing that identical boxes match + testObj.setSearchArea(b1); + testObj2.setSearchArea(b2); + QVERIFY2(testObj == testObj2, "Identical box areas are not identified as matching"); + + //test that different boxes do not match + testObj2.setSearchArea(b3); + QVERIFY2(testObj != testObj2, "Different box areas identified as matching"); + + QGeoCircle c1(QGeoCoordinate(5,5),500); + QGeoCircle c2(QGeoCoordinate(5,5),500); + QGeoCircle c3(QGeoCoordinate(9,9),600); + + //test that identical cirlces match + testObj.setSearchArea(c1); + testObj2.setSearchArea(c2); + QVERIFY2(testObj == testObj2, "Identical circle areas are not identified as matching"); + + //test that different circle don't match + testObj2.setSearchArea(c3); + QVERIFY2(testObj != testObj2, "Different circle areas identified as matching"); + + //test that circles and boxes do not match + QGeoRectangle b4(QGeoCoordinate(20,20),QGeoCoordinate(10,30)); + QGeoCircle c4(QGeoCoordinate(20,20),500); + testObj.setSearchArea(b4); + testObj2.setSearchArea(c4); + QVERIFY2(testObj != testObj2, "Circle and box identified as matching"); + + //test that identical visibility scopes match + testObj.clear(); + testObj2.clear(); + testObj.setVisibilityScope(QLocation::PublicVisibility); + testObj2.setVisibilityScope(QLocation::PublicVisibility); + QVERIFY2(testObj == testObj2, "Identical scopes not identified as matching"); + + //test that different scopes do not match + testObj2.setVisibilityScope(QLocation::PrivateVisibility); + QVERIFY2(testObj != testObj2, "Different scopes identified as matching"); + + //test that different search contexts do not match + testObj.clear(); + testObj2.clear(); + testObj2.setSearchContext(QUrl(QStringLiteral("http://www.example.com/"))); + QVERIFY(testObj != testObj2); +} + +void tst_QPlaceSearchRequest::clearTest() +{ + QPlaceSearchRequest req; + req.setSearchTerm("pizza"); + req.setSearchArea(QGeoCircle(QGeoCoordinate(1,1), 5000)); + QPlaceCategory category; + category.setName("Fast Food"); + req.setCategory(category); + req.setLimit(100); + + req.clear(); + QVERIFY(req.searchTerm().isEmpty()); + QVERIFY(req.searchArea() == QGeoShape()); + QVERIFY(req.categories().isEmpty()); + QVERIFY(req.limit() == -1); +} + +QTEST_APPLESS_MAIN(tst_QPlaceSearchRequest) + +#include "tst_qplacesearchrequest.moc" diff --git a/tests/auto/qplacesearchresult/qplacesearchresult.pro b/tests/auto/qplacesearchresult/qplacesearchresult.pro new file mode 100644 index 0000000..935819a --- /dev/null +++ b/tests/auto/qplacesearchresult/qplacesearchresult.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacesearchresult + +SOURCES += tst_qplacesearchresult.cpp + +QT += location testlib diff --git a/tests/auto/qplacesearchresult/tst_qplacesearchresult.cpp b/tests/auto/qplacesearchresult/tst_qplacesearchresult.cpp new file mode 100644 index 0000000..9306392 --- /dev/null +++ b/tests/auto/qplacesearchresult/tst_qplacesearchresult.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QPlaceSearchResult : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void constructorTest(); + void title(); + void icon(); + void operators(); +}; + +void tst_QPlaceSearchResult::constructorTest() +{ + QPlaceSearchResult result; + + QCOMPARE(result.type(), QPlaceSearchResult::UnknownSearchResult); + QVERIFY(result.title().isEmpty()); + QVERIFY(result.icon().isEmpty()); + + result.setTitle(QStringLiteral("title")); + QPlaceIcon icon; + QVariantMap parameters; + parameters.insert(QStringLiteral("paramKey"), QStringLiteral("paramValue")); + icon.setParameters(parameters); + result.setIcon(icon); + + QPlaceSearchResult result2(result); + QCOMPARE(result2.title(), QStringLiteral("title")); + QCOMPARE(result2.icon().parameters().value(QStringLiteral("paramKey")).toString(), + QStringLiteral("paramValue")); + + QCOMPARE(result2, result); +} + +void tst_QPlaceSearchResult::title() +{ + QPlaceSearchResult result; + QVERIFY(result.title().isEmpty()); + result.setTitle(QStringLiteral("title")); + QCOMPARE(result.title(), QStringLiteral("title")); + result.setTitle(QString()); + QVERIFY(result.title().isEmpty()); +} + +void tst_QPlaceSearchResult::icon() +{ + QPlaceSearchResult result; + QVERIFY(result.icon().isEmpty()); + QPlaceIcon icon; + QVariantMap iconParams; + iconParams.insert(QStringLiteral("paramKey"), QStringLiteral("paramValue")); + result.setIcon(icon); + QCOMPARE(result.icon(), icon); + result.setIcon(QPlaceIcon()); + QVERIFY(result.icon().isEmpty()); +} + +void tst_QPlaceSearchResult::operators() +{ + QPlaceSearchResult result1; + QPlaceSearchResult result2; + + QVERIFY(result1 == result2); + QVERIFY(!(result1 != result2)); + + result1.setTitle(QStringLiteral("title")); + QVERIFY(!(result1 == result2)); + QVERIFY(result1 != result2); + + result2.setTitle(QStringLiteral("title")); + QVERIFY(result1 == result2); + QVERIFY(!(result1 != result2)); +} + +QTEST_APPLESS_MAIN(tst_QPlaceSearchResult) + +#include "tst_qplacesearchresult.moc" diff --git a/tests/auto/qplacesearchsuggestionreply/qplacesearchsuggestionreply.pro b/tests/auto/qplacesearchsuggestionreply/qplacesearchsuggestionreply.pro new file mode 100644 index 0000000..c436333 --- /dev/null +++ b/tests/auto/qplacesearchsuggestionreply/qplacesearchsuggestionreply.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacesearchsuggestionreply + +SOURCES += tst_qplacesearchsuggestionreply.cpp + +QT += location testlib diff --git a/tests/auto/qplacesearchsuggestionreply/tst_qplacesearchsuggestionreply.cpp b/tests/auto/qplacesearchsuggestionreply/tst_qplacesearchsuggestionreply.cpp new file mode 100644 index 0000000..8670e44 --- /dev/null +++ b/tests/auto/qplacesearchsuggestionreply/tst_qplacesearchsuggestionreply.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class SuggestionReply : public QPlaceSearchSuggestionReply +{ + Q_OBJECT +public: + SuggestionReply(QObject *parent) : QPlaceSearchSuggestionReply(parent){} + + void setSuggestions(const QStringList &suggestions) { + QPlaceSearchSuggestionReply::setSuggestions(suggestions); + } +}; + +class tst_QPlaceSearchSuggestionReply : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceSearchSuggestionReply(); + +private Q_SLOTS: + void constructorTest(); + void typeTest(); + void suggestionsTest(); +}; + +tst_QPlaceSearchSuggestionReply::tst_QPlaceSearchSuggestionReply() +{ +} + +void tst_QPlaceSearchSuggestionReply::constructorTest() +{ + SuggestionReply *reply = new SuggestionReply(this); + QCOMPARE(reply->parent(), this); + + delete reply; +} + +void tst_QPlaceSearchSuggestionReply::typeTest() +{ + SuggestionReply *reply = new SuggestionReply(this); + QCOMPARE(reply->type(), QPlaceReply::SearchSuggestionReply); + + delete reply; +} + +void tst_QPlaceSearchSuggestionReply::suggestionsTest() +{ + QStringList suggestions; + suggestions << QStringLiteral("one") << QStringLiteral("two") + << QStringLiteral("three"); + + SuggestionReply *reply = new SuggestionReply(this); + reply->setSuggestions(suggestions); + QCOMPARE(reply->suggestions(), suggestions); + + delete reply; +} + +QTEST_APPLESS_MAIN(tst_QPlaceSearchSuggestionReply) + +#include "tst_qplacesearchsuggestionreply.moc" diff --git a/tests/auto/qplacesupplier/qplacesupplier.pro b/tests/auto/qplacesupplier/qplacesupplier.pro new file mode 100644 index 0000000..06715f4 --- /dev/null +++ b/tests/auto/qplacesupplier/qplacesupplier.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplacesupplier + +SOURCES += tst_qplacesupplier.cpp + +QT += location testlib diff --git a/tests/auto/qplacesupplier/tst_qplacesupplier.cpp b/tests/auto/qplacesupplier/tst_qplacesupplier.cpp new file mode 100644 index 0000000..6d6bdf8 --- /dev/null +++ b/tests/auto/qplacesupplier/tst_qplacesupplier.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QPlaceSupplier : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceSupplier(); + +private Q_SLOTS: + void constructorTest(); + void nameTest(); + void supplierIdTest(); + void urlTest(); + void iconTest(); + void operatorsTest(); + void isEmptyTest(); +}; + +tst_QPlaceSupplier::tst_QPlaceSupplier() +{ +} + +void tst_QPlaceSupplier::constructorTest() +{ + QPlaceSupplier testObj; + Q_UNUSED(testObj); + + QPlaceSupplier *testObjPtr = new QPlaceSupplier(testObj); + QVERIFY2(testObjPtr != NULL, "Copy constructor - null"); + QVERIFY2(*testObjPtr == testObj, "Copy constructor - compare"); + delete testObjPtr; +} + +void tst_QPlaceSupplier::nameTest() +{ + QPlaceSupplier testObj; + QVERIFY2(testObj.name() == QString(), "Wrong default value"); + testObj.setName("testText"); + QVERIFY2(testObj.name() == "testText", "Wrong value returned"); +} + +void tst_QPlaceSupplier::supplierIdTest() +{ + QPlaceSupplier testObj; + QVERIFY2(testObj.supplierId() == QString(), "Wrong default value"); + testObj.setSupplierId("testText"); + QVERIFY2(testObj.supplierId() == "testText", "Wrong value returned"); +} + +void tst_QPlaceSupplier::urlTest() +{ + QPlaceSupplier testObj; + const QUrl testUrl = QUrl::fromEncoded("http://example.com/testUrl"); + QVERIFY2(testObj.url() == QString(), "Wrong default value"); + testObj.setUrl(testUrl); + QVERIFY2(testObj.url() == testUrl, "Wrong value returned"); +} + +void tst_QPlaceSupplier::iconTest() +{ + QPlaceSupplier testObj; + QVERIFY(testObj.icon().isEmpty()); + QPlaceIcon icon; + QVariantMap iconParams; + iconParams.insert(QPlaceIcon::SingleUrl, QUrl::fromEncoded("http://example.com/icon.png")); + icon.setParameters(iconParams); + testObj.setIcon(icon); + QCOMPARE(testObj.icon(), icon); + QCOMPARE(testObj.icon().url(), QUrl::fromEncoded("http://example.com/icon.png")); + + testObj.setIcon(QPlaceIcon()); + QVERIFY(testObj.icon().isEmpty()); + QCOMPARE(testObj.icon().url(), QUrl()); +} + +void tst_QPlaceSupplier::operatorsTest() +{ + QPlaceSupplier testObj; + testObj.setName(QStringLiteral("Acme")); + QPlaceIcon icon; + QVariantMap iconParams; + iconParams.insert(QPlaceIcon::SingleUrl, QUrl::fromEncoded("http://example.com/icon.png")); + icon.setParameters(iconParams); + testObj.setIcon(icon); + testObj.setSupplierId(QStringLiteral("34292")); + + QPlaceSupplier testObj2; + testObj2 = testObj; + QVERIFY2(testObj == testObj2, "Not copied correctly"); + testObj2.setSupplierId(QStringLiteral("testValue2")); + QVERIFY2(testObj != testObj2, "Object should be different"); +} + +void tst_QPlaceSupplier::isEmptyTest() +{ + QPlaceIcon icon; + QVariantMap iconParametersMap; + iconParametersMap.insert(QStringLiteral("Para"), QStringLiteral("meter")); + icon.setParameters(iconParametersMap); + QVERIFY(!icon.isEmpty()); + + QPlaceSupplier supplier; + + QVERIFY(supplier.isEmpty()); + + // name + supplier.setName(QStringLiteral("Name")); + QVERIFY(!supplier.isEmpty()); + supplier.setName(QString()); + QVERIFY(supplier.isEmpty()); + + // supplierId + supplier.setSupplierId(QStringLiteral("1")); + QVERIFY(!supplier.isEmpty()); + supplier.setSupplierId(QString()); + QVERIFY(supplier.isEmpty()); + + // url + supplier.setUrl(QUrl(QStringLiteral("www.example.com"))); + QVERIFY(!supplier.isEmpty()); + supplier.setUrl(QUrl()); + QVERIFY(supplier.isEmpty()); + + // icon + supplier.setIcon(icon); + QVERIFY(!supplier.isEmpty()); + supplier.setIcon(QPlaceIcon()); + QVERIFY(supplier.isEmpty()); +} + +QTEST_APPLESS_MAIN(tst_QPlaceSupplier); + +#include "tst_qplacesupplier.moc" diff --git a/tests/auto/qplaceuser/qplaceuser.pro b/tests/auto/qplaceuser/qplaceuser.pro new file mode 100644 index 0000000..3eab126 --- /dev/null +++ b/tests/auto/qplaceuser/qplaceuser.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qplaceuser + +SOURCES += tst_qplaceuser.cpp + +QT += location testlib diff --git a/tests/auto/qplaceuser/tst_qplaceuser.cpp b/tests/auto/qplaceuser/tst_qplaceuser.cpp new file mode 100644 index 0000000..086b184 --- /dev/null +++ b/tests/auto/qplaceuser/tst_qplaceuser.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QPlaceUser : public QObject +{ + Q_OBJECT + +public: + tst_QPlaceUser(); + +private Q_SLOTS: + void constructorTest(); + void nameTest(); + void userIdTest(); + void operatorsTest(); + void operatorsTest_data(); +}; + +tst_QPlaceUser::tst_QPlaceUser() +{ +} + +void tst_QPlaceUser::constructorTest() +{ + QPlaceUser user; + QVERIFY(user.name().isEmpty()); + QVERIFY(user.userId().isEmpty()); + + user.setName(QStringLiteral("Thomas Anderson")); + user.setUserId(QStringLiteral("Neo")); + + QPlaceUser user2(user); + QCOMPARE(user2.name(), QStringLiteral("Thomas Anderson")); + QCOMPARE(user2.userId(), QStringLiteral("Neo")); +} + +void tst_QPlaceUser::nameTest() +{ + QPlaceUser user; + user.setName(QStringLiteral("Thomas Anderson")); + QCOMPARE(user.name(), QStringLiteral("Thomas Anderson")); + user.setName(QString()); + QVERIFY(user.name().isEmpty()); +} + +void tst_QPlaceUser::userIdTest() +{ + QPlaceUser user; + user.setUserId(QStringLiteral("Neo")); + QCOMPARE(user.userId(), QStringLiteral("Neo")); + user.setUserId(QString()); + QVERIFY(user.userId().isEmpty()); +} + +void tst_QPlaceUser::operatorsTest() +{ + QPlaceUser user1; + user1.setName(QStringLiteral("Thomas Anderson")); + user1.setUserId(QStringLiteral("Neo")); + + QPlaceUser user2; + user2.setName(QStringLiteral("Thomas Anderson")); + user2.setUserId(QStringLiteral("Neo")); + + QVERIFY(user1 == user2); + QVERIFY(!(user1 != user2)); + QVERIFY(user2 == user1); + QVERIFY(!(user2 != user1)); + + QPlaceUser user3; + QVERIFY(!(user1 == user3)); + QVERIFY(user1 != user3); + QVERIFY(!(user3 == user1)); + QVERIFY(user3 != user1); + + user3 = user1; + QVERIFY(user1 == user3); + QVERIFY(!(user1 != user3)); + QVERIFY(user3 == user1); + QVERIFY(!(user3 != user1)); + + QFETCH(QString, field); + + if (field == QStringLiteral("name")) + user3.setName(QStringLiteral("bob")); + else if (field == QStringLiteral("userId")) + user3.setUserId(QStringLiteral("Morpheus")); + else + qFatal("Unknown data field"); + + QVERIFY(!(user1 == user3)); + QVERIFY(user1 != user3); + QVERIFY(!(user3 == user1)); + QVERIFY(user3 != user1); +} + +void tst_QPlaceUser::operatorsTest_data() +{ + QTest::addColumn("field"); + + QTest::newRow("user name") << "name"; + QTest::newRow("user id") << "userId"; +} + +QTEST_APPLESS_MAIN(tst_QPlaceUser) + +#include "tst_qplaceuser.moc" diff --git a/tests/auto/qproposedsearchresult/qproposedsearchresult.pro b/tests/auto/qproposedsearchresult/qproposedsearchresult.pro new file mode 100644 index 0000000..bae784c --- /dev/null +++ b/tests/auto/qproposedsearchresult/qproposedsearchresult.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qproposedsearchresult + +SOURCES += tst_qproposedsearchresult.cpp + +QT += location testlib diff --git a/tests/auto/qproposedsearchresult/tst_qproposedsearchresult.cpp b/tests/auto/qproposedsearchresult/tst_qproposedsearchresult.cpp new file mode 100644 index 0000000..8693445 --- /dev/null +++ b/tests/auto/qproposedsearchresult/tst_qproposedsearchresult.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Aaron McCarthy +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "../utils/qlocationtestutils_p.h" + +QT_USE_NAMESPACE + +class tst_QPlaceProposedSearchResult : public QObject +{ + Q_OBJECT + +public: + QPlaceProposedSearchResult initialSubObject(); + bool checkType(const QPlaceSearchResult &result); + void detach(QPlaceSearchResult *result); + void setSubClassProperty(QPlaceProposedSearchResult *result); + +private Q_SLOTS: + void constructorTest(); + void title(); + void icon(); + void searchRequest(); + void conversion(); +}; + +QPlaceProposedSearchResult tst_QPlaceProposedSearchResult::initialSubObject() +{ + QPlaceProposedSearchResult proposedSearchResult; + proposedSearchResult.setTitle(QStringLiteral("title")); + + QPlaceIcon icon; + QVariantMap parameters; + parameters.insert(QPlaceIcon::SingleUrl, + QUrl(QStringLiteral("file:///opt/icons/icon.png"))); + icon.setParameters(parameters); + proposedSearchResult.setIcon(icon); + + QPlaceSearchRequest searchRequest; + searchRequest.setSearchContext(QUrl(QStringLiteral("http://www.example.com/"))); + proposedSearchResult.setSearchRequest(searchRequest); + + return proposedSearchResult; +} + +bool tst_QPlaceProposedSearchResult::checkType(const QPlaceSearchResult &result) +{ + return result.type() == QPlaceSearchResult::ProposedSearchResult; +} + +void tst_QPlaceProposedSearchResult::detach(QPlaceSearchResult *result) +{ + result->setTitle(QStringLiteral("title")); +} + +void tst_QPlaceProposedSearchResult::setSubClassProperty(QPlaceProposedSearchResult *result) +{ + QPlaceSearchRequest request; + request.setSearchContext(QUrl(QStringLiteral("http://www.example.com/place-search"))); + result->setSearchRequest(request); +} + +void tst_QPlaceProposedSearchResult::constructorTest() +{ + QPlaceProposedSearchResult result; + QCOMPARE(result.type(), QPlaceSearchResult::ProposedSearchResult); + + result.setTitle(QStringLiteral("title")); + + QPlaceIcon icon; + QVariantMap parameters; + parameters.insert(QStringLiteral("paramKey"), QStringLiteral("paramValue")); + icon.setParameters(parameters); + result.setIcon(icon); + + QPlaceSearchRequest searchRequest; + searchRequest.setSearchContext(QUrl(QStringLiteral("http://www.example.com/place-search"))); + result.setSearchRequest(searchRequest); + + //check copy constructor + QPlaceProposedSearchResult result2(result); + QCOMPARE(result2.title(), QStringLiteral("title")); + QCOMPARE(result2.icon(), icon); + QCOMPARE(result2.searchRequest(), searchRequest); + + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + //check results are the same after detachment of underlying shared data pointer + result2.setTitle(QStringLiteral("title")); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + //check construction of SearchResult using a ProposedSearchResult + QPlaceSearchResult searchResult(result); + QCOMPARE(searchResult.title(), QStringLiteral("title")); + QCOMPARE(searchResult.icon(), icon); + QVERIFY(QLocationTestUtils::compareEquality(searchResult, result)); + QVERIFY(searchResult.type() == QPlaceSearchResult::ProposedSearchResult); + result2 = searchResult; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + //check construction of a SearchResult using a SearchResult + //that is actually a PlaceResult underneath + QPlaceSearchResult searchResult2(searchResult); + QCOMPARE(searchResult2.title(), QStringLiteral("title")); + QCOMPARE(searchResult2.icon(), icon); + QVERIFY(QLocationTestUtils::compareEquality(searchResult2, result)); + QVERIFY(QLocationTestUtils::compareEquality(searchResult, searchResult2)); + QVERIFY(searchResult2.type() == QPlaceSearchResult::ProposedSearchResult); + result2 = searchResult2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceProposedSearchResult::title() +{ + QPlaceProposedSearchResult result; + QVERIFY(result.title().isEmpty()); + + result.setTitle(QStringLiteral("title")); + QCOMPARE(result.title(), QStringLiteral("title")); + + result.setTitle(QString()); + QVERIFY(result.title().isEmpty()); + + QPlaceProposedSearchResult result2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + result2.setTitle("title"); + QVERIFY(QLocationTestUtils::compareInequality(result, result2)); + + result.setTitle("title"); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceProposedSearchResult::icon() +{ + QPlaceProposedSearchResult result; + QVERIFY(result.icon().isEmpty()); + + QPlaceIcon icon; + QVariantMap iconParams; + iconParams.insert(QStringLiteral("paramKey"), QStringLiteral("paramValue")); + icon.setParameters(iconParams); + result.setIcon(icon); + QCOMPARE(result.icon(), icon); + + result.setIcon(QPlaceIcon()); + QVERIFY(result.icon().isEmpty()); + + QPlaceProposedSearchResult result2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + result2.setIcon(icon); + QVERIFY(QLocationTestUtils::compareInequality(result, result2)); + + result.setIcon(icon); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceProposedSearchResult::searchRequest() +{ + QPlaceProposedSearchResult result; + QCOMPARE(result.searchRequest(), QPlaceSearchRequest()); + + QPlaceSearchRequest placeSearchRequest; + placeSearchRequest.setSearchContext(QUrl(QStringLiteral("http://www.example.com/"))); + result.setSearchRequest(placeSearchRequest); + QCOMPARE(result.searchRequest(), placeSearchRequest); + + result.setSearchRequest(QPlaceSearchRequest()); + QCOMPARE(result.searchRequest(), QPlaceSearchRequest()); + + QPlaceProposedSearchResult result2; + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); + + result2.setSearchRequest(placeSearchRequest); + QVERIFY(QLocationTestUtils::compareInequality(result, result2)); + + result.setSearchRequest(placeSearchRequest); + QVERIFY(QLocationTestUtils::compareEquality(result, result2)); +} + +void tst_QPlaceProposedSearchResult::conversion() +{ + QLocationTestUtils::testConversion(this); +} + +QTEST_APPLESS_MAIN(tst_QPlaceProposedSearchResult) + +#include "tst_qproposedsearchresult.moc" diff --git a/tests/auto/utils/qlocationtestutils.cpp b/tests/auto/utils/qlocationtestutils.cpp new file mode 100644 index 0000000..d6e7785 --- /dev/null +++ b/tests/auto/utils/qlocationtestutils.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlocationtestutils_p.h" + +bool QLocationTestUtils::hasDefaultSource() +{ + return false; +} + +bool QLocationTestUtils::hasDefaultMonitor() +{ + return false; +} + +QString QLocationTestUtils::addNmeaChecksumAndBreaks(const QString &sentence) +{ + Q_ASSERT(sentence[0] == '$' && sentence[sentence.length()-1] == '*'); + + // XOR byte value of all characters between '$' and '*' + int result = 0; + for (int i=1; i +#include +#include + +namespace QLocationTestUtils +{ + bool hasDefaultSource(); + bool hasDefaultMonitor(); + + QString addNmeaChecksumAndBreaks(const QString &sentence); + + QString createRmcSentence(const QDateTime &dt); + QString createGgaSentence(const QTime &time); + QString createGgaSentence(int lat, int lng, const QTime &time); + QString createZdaSentence(const QDateTime &dt); + QString createGsaSentence(); + + //The purpose of compareEquality() is to test equality + //operators where it is expected that A == B. + template + bool compareEquality(const A &first, const B &second) { + if (first != second) { + qWarning() << "compareEquality() failed: first != second"; + return false; + } + + if (second != first) { + qWarning() << "compareEquality() failed: second != first"; + return false; + } + + if (!(first == second)) { + qWarning() << "compareEquality() failed: !(first == second)"; + return false; + } + + if (!(second == first)) { + qWarning() << "compareEquality() failed: !(second == first)"; + return false; + } + + return true; + } + + //The purpose of compareInequality() is to test equality + //operators where it is expected that A != B. + //Using !compareEquality(...) is not sufficient because + //only the first operator checked would end up being tested. + template + bool compareInequality(const A &first, const B &second) { + if (!(first != second)){ + qWarning() << "compareInequality() failed: !(first != second)"; + return false; + } + + if (!(second != first)) { + qWarning() << "compareInequality() failed: !(second != first)"; + return false; + } + + if (first == second) { + qWarning() << "compareInequality() failed: first == second)"; + return false; + } + + if (second == first) { + qWarning() << "compareInequality() failed: second == first"; + return false; + } + return true; + } + + // Tests conversions between sub and base classes + // TC (test case) must implement: + // SubClass initialSubObject(); + // bool checkType(const BaseClass &) + // void detach(BaseClass *) - calls a mutator method, but doesn't actually modify the + // property to something different. + // void setSubClassProperty(SubClass *) - sets a property in the subclass instance + template + void testConversion(TC *tc) { + SubClass sub = tc->initialSubObject(); + //check conversion from SubClass -> BaseClass + //using assignment operator + BaseClass base; + base = sub; + QVERIFY(QLocationTestUtils::compareEquality(base, sub)); + QVERIFY(tc->checkType(base)); + + //check comparing base classes + BaseClass base2; + base2 = sub; + QVERIFY(QLocationTestUtils::compareEquality(base, base2)); + + //check conversion from BaseClass -> SubClass + //using assignment operator + SubClass sub2; + sub2 = base; + QVERIFY(QLocationTestUtils::compareEquality(sub, sub2)); + QVERIFY(tc->checkType(sub2)); + + //check that equality still holds with detachment of underlying data pointer + tc->detach(&base); + sub2 = base; + QVERIFY(QLocationTestUtils::compareEquality(sub, sub2)); + QVERIFY(QLocationTestUtils::compareEquality(sub, base)); + QVERIFY(QLocationTestUtils::compareEquality(base, base2)); + + //check that comparing objects are not the same + //when an underlying subclass field has been modified + tc->setSubClassProperty(&sub2); + base2 = sub2; + QVERIFY(QLocationTestUtils::compareInequality(sub, sub2)); + QVERIFY(QLocationTestUtils::compareInequality(sub, base2)); + QVERIFY(QLocationTestUtils::compareInequality(base, base2)); + + //check conversion from SubClass -> BaseClass + //using copy constructor + BaseClass base3(sub); + QVERIFY(QLocationTestUtils::compareEquality(sub, base3)); + QVERIFY(QLocationTestUtils::compareEquality(base, base3)); + + //check conversion from BaseClass -> SubClass + //using copy constructor + SubClass sub3(base3); + QVERIFY(QLocationTestUtils::compareEquality(sub, sub3)); + + //check conversion to subclass using a default base class instance + BaseClass baseDefault; + SubClass subDefault; + SubClass sub4(baseDefault); + QVERIFY(QLocationTestUtils::compareEquality(sub4, subDefault)); + + SubClass sub5 = baseDefault; + QVERIFY(QLocationTestUtils::compareEquality(sub5, subDefault)); + } +}; + +#endif diff --git a/tests/global/global.cfg b/tests/global/global.cfg new file mode 100644 index 0000000..8cc6269 --- /dev/null +++ b/tests/global/global.cfg @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/plugins/declarativetestplugin/declarativetestplugin.pro b/tests/plugins/declarativetestplugin/declarativetestplugin.pro new file mode 100644 index 0000000..0a99e7a --- /dev/null +++ b/tests/plugins/declarativetestplugin/declarativetestplugin.pro @@ -0,0 +1,27 @@ +CXX_MODULE = location +TARGET = declarative_location_test +TARGETPATH = QtLocation/Test + +QT += gui-private qml quick location testlib + +INCLUDEPATH += ../../../src/imports/location +INCLUDEPATH += ../../../src/location + +HEADERS += \ + qdeclarativepinchgenerator_p.h \ + qdeclarativelocationtestmodel_p.h \ + testhelper.h + +SOURCES += \ + locationtest.cpp \ + qdeclarativepinchgenerator.cpp \ + qdeclarativelocationtestmodel.cpp + +IMPORT_FILES = \ + qmldir + +load(qml_plugin) + + +# must be after load(qml_plugin) +include(../imports.pri) diff --git a/tests/plugins/declarativetestplugin/locationtest.cpp b/tests/plugins/declarativetestplugin/locationtest.cpp new file mode 100644 index 0000000..f0389d9 --- /dev/null +++ b/tests/plugins/declarativetestplugin/locationtest.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativepinchgenerator_p.h" +#include "qdeclarativelocationtestmodel_p.h" +#include "testhelper.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +static QObject *helper_factory(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine); + Q_UNUSED(scriptEngine); + TestHelper *helper = new TestHelper(); + return helper; +} + +class QLocationDeclarativeTestModule: public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") +public: + virtual void registerTypes(const char* uri) + { + if (QLatin1String(uri) == QLatin1String("QtLocation.Test")) { + qmlRegisterType(uri, 5, 5, "PinchGenerator"); + qmlRegisterType(uri, 5, 5, "TestModel"); + qmlRegisterSingletonType(uri, 5, 6, "LocationTestHelper", helper_factory); + } else { + qWarning() << "Unsupported URI given to load location test QML plugin: " << QLatin1String(uri); + } + } +}; + +#include "locationtest.moc" + +QT_END_NAMESPACE + diff --git a/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel.cpp b/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel.cpp new file mode 100644 index 0000000..e000459 --- /dev/null +++ b/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativelocationtestmodel_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QDeclarativeLocationTestModel::QDeclarativeLocationTestModel(QObject *parent): + QAbstractListModel(parent), + delay_(0), + datacount_(0), + componentCompleted_(false), + crazyLevel_(0), + crazyMode_(false) +{ + // seed crazy random generator + qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid()); + timer_.setSingleShot(true); + connect(&timer_, SIGNAL(timeout()), this, SLOT(timerFired())); +} + +QDeclarativeLocationTestModel::~QDeclarativeLocationTestModel() +{ + if (timer_.isActive()) + timer_.stop(); + if (!dataobjects_.isEmpty()) { + qDeleteAll(dataobjects_); + dataobjects_.clear(); + } +} + +void QDeclarativeLocationTestModel::timerFired() +{ + //qDebug() << "timer fired" ; + repopulate(); + if (crazyMode_) { + //qDebug() << "raw randomw value: " << qrand(); + int delay = (qAbs(qrand()) % crazyLevel_); // writing software is exact science + delay = qMax(1000, delay); // 3 ms at minimum + qDebug() << "starting timer with : " << delay; + timer_.start(delay); + } +} + +void QDeclarativeLocationTestModel::componentComplete() +{ + componentCompleted_ = true; + scheduleRepopulation(); +} + + +int QDeclarativeLocationTestModel::datacount() const +{ + return datacount_; +} + +void QDeclarativeLocationTestModel::setDatacount(int datacount) +{ + if (datacount_ == datacount) + return; + datacount_ = datacount; + emit datacountChanged(); + scheduleRepopulation(); +} + +int QDeclarativeLocationTestModel::delay() const +{ + return delay_; +} + +void QDeclarativeLocationTestModel::setDelay(int delay) +{ + if (delay_ == delay) + return; + delay_ = delay; + emit delayChanged(); +} + +QString QDeclarativeLocationTestModel::datatype() const +{ + return datatype_; +} + +void QDeclarativeLocationTestModel::setDatatype(QString datatype) +{ + if (datatype_ == datatype) + return; + datatype_ = datatype; + emit datatypeChanged(); + scheduleRepopulation(); +} + +int QDeclarativeLocationTestModel::crazyLevel() const +{ + return crazyLevel_; +} + +void QDeclarativeLocationTestModel::setCrazyLevel(int level) +{ + if (level == crazyLevel_) + return; + crazyLevel_ = level; + reset(); + scheduleRepopulation(); + emit crazyLevelChanged(); +} + +bool QDeclarativeLocationTestModel::crazyMode() const +{ + return crazyMode_; +} + +void QDeclarativeLocationTestModel::setCrazyMode(bool mode) +{ + if (mode == crazyMode_) + return; + crazyMode_ = mode; + //if (!crazyMode_) + //reset(); + //else + if (crazyMode_) + scheduleRepopulation(); + emit crazyModeChanged(); +} + +// only coordinate datatype for now to get started with, +// refactor if more usecases for the model emerge. +void QDeclarativeLocationTestModel::repopulate() +{ + double latitude = -30; + double longitude = 153; + beginResetModel(); + if (!dataobjects_.isEmpty()) { + qDeleteAll(dataobjects_); + dataobjects_.clear(); + } + int datacount = datacount_; + if (crazyMode_) + datacount = (qAbs(qrand()) % datacount_); + + for (int i = 0; i < datacount; ++i) { + DataObject* dataobject = new DataObject; + dataobject->coordinate_ = QGeoCoordinate(latitude, longitude); + dataobjects_.append(dataobject); + longitude -= 0.2; + latitude += 0.2; + } + endResetModel(); +} + +void QDeclarativeLocationTestModel::update() +{ + scheduleRepopulation(); +} + +void QDeclarativeLocationTestModel::reset() +{ + if (timer_.isActive()) + timer_.stop(); + beginResetModel(); + if (!dataobjects_.isEmpty()) { + qDeleteAll(dataobjects_); + dataobjects_.clear(); + } + endResetModel(); +} + +void QDeclarativeLocationTestModel::scheduleRepopulation() +{ + if (!componentCompleted_) + return; + + if (datacount_ <= 0) + return; + + if (timer_.isActive()) + timer_.stop(); + + if (crazyMode_) { + // start generating arbitrary amount of data at arbitrary intervals + int delay = (qAbs(qrand()) % crazyLevel_); // writing software is exact science + delay = qMax(3, delay); // 3 ms at minimum + qDebug() << "starting timer with : " << delay; + timer_.start(delay); + } else { + // just update + if (delay_ > 0) + timer_.start(delay_); + else + repopulate(); + } +} + +int QDeclarativeLocationTestModel::rowCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return dataobjects_.count(); +} + +// Returns the stored under the given role for the item referred to by the index. +QVariant QDeclarativeLocationTestModel::data(const QModelIndex& index, int role) const +{ + switch (role) { + case TestDataRole: + if (dataobjects_.at(index.row())) { + return QVariant::fromValue(qobject_cast(dataobjects_.at(index.row()))); + } + break; + } + return QVariant(); +} + +QHash QDeclarativeLocationTestModel::roleNames() const +{ + QHash roles = QAbstractListModel::roleNames(); + roles.insert(TestDataRole, "modeldata"); + return roles; +} + +QT_END_NAMESPACE diff --git a/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel_p.h b/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel_p.h new file mode 100644 index 0000000..925125a --- /dev/null +++ b/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel_p.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVELOCATIONTESTMODEL_H +#define QDECLARATIVELOCATIONTESTMODEL_H + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class DataObject: public QObject +{ + Q_OBJECT + Q_PROPERTY(QGeoCoordinate coordinate READ coordinate CONSTANT) + +public: + DataObject() {} + ~DataObject() {} + + QGeoCoordinate coordinate_; + QGeoCoordinate coordinate() const {return coordinate_;} +}; + +class QDeclarativeLocationTestModel : public QAbstractListModel, public QQmlParserStatus +{ + Q_OBJECT + Q_PROPERTY(int datacount READ datacount WRITE setDatacount NOTIFY datacountChanged) + Q_PROPERTY(int delay READ delay WRITE setDelay NOTIFY delayChanged) + Q_PROPERTY(bool crazyMode READ crazyMode WRITE setCrazyMode NOTIFY crazyModeChanged) + Q_PROPERTY(int crazyLevel READ crazyLevel WRITE setCrazyLevel NOTIFY crazyLevelChanged) + Q_PROPERTY(QString datatype READ datatype WRITE setDatatype NOTIFY datatypeChanged) + Q_INTERFACES(QQmlParserStatus) + +public: + QDeclarativeLocationTestModel(QObject* parent = 0); + ~QDeclarativeLocationTestModel(); + + enum Roles { + TestDataRole = Qt::UserRole + 500 + }; + + // from QQmlParserStatus + virtual void componentComplete(); + virtual void classBegin() {} + + // From QAbstractListModel + virtual int rowCount(const QModelIndex &parent) const; + virtual QVariant data(const QModelIndex &index, int role) const; + virtual QHash roleNames() const; + + int datacount() const; + void setDatacount(int datacount); + + int delay() const; + void setDelay(int delay); + + int crazyLevel() const; + void setCrazyLevel(int level); + + bool crazyMode() const; + void setCrazyMode(bool mode); + + QString datatype() const; + void setDatatype(QString datatype); + + //Q_INVOKABLE void clear(); + Q_INVOKABLE void reset(); + Q_INVOKABLE void update(); + //Q_INVOKABLE void reset(); + +signals: + void countChanged(); + void datacountChanged(); + void datatypeChanged(); + void delayChanged(); + void modelChanged(); + void crazyLevelChanged(); + void crazyModeChanged(); + +private slots: + void repopulate(); + void timerFired(); + +private: + void scheduleRepopulation(); + +private: + int delay_; + int datacount_; + bool componentCompleted_; + QString datatype_; + QTimer timer_; + QList dataobjects_; + int crazyLevel_; + bool crazyMode_; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tests/plugins/declarativetestplugin/qdeclarativepinchgenerator.cpp b/tests/plugins/declarativetestplugin/qdeclarativepinchgenerator.cpp new file mode 100644 index 0000000..3026cd9 --- /dev/null +++ b/tests/plugins/declarativetestplugin/qdeclarativepinchgenerator.cpp @@ -0,0 +1,382 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativepinchgenerator_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QDeclarativePinchGenerator::QDeclarativePinchGenerator(): + target_(0), + state_(Invalid), + window_(0), + activeSwipe_(0), + replayTimer_(-1), + replayBookmark_(-1), + masterSwipe_(-1), + replaySpeedFactor_(1.0), + enabled_(true) +{ + setAcceptedMouseButtons(Qt::LeftButton | Qt::MidButton | Qt::RightButton); + swipeTimer_.invalidate(); + device_ = new QTouchDevice; + device_->setType(QTouchDevice::TouchScreen); + QWindowSystemInterface::registerTouchDevice(device_); +} + +QDeclarativePinchGenerator::~QDeclarativePinchGenerator() +{ + clear(); +} + +void QDeclarativePinchGenerator::componentComplete() +{ + QQuickItem::componentComplete(); +} + +void QDeclarativePinchGenerator::mousePressEvent(QMouseEvent *event) +{ + if (state_ != Idle || !enabled_) { + event->ignore(); + return; + } + Q_ASSERT(!activeSwipe_); + Q_ASSERT(!swipeTimer_.isValid()); + // Start recording a pinch gesture. + activeSwipe_ = new Swipe; + activeSwipe_->touchPoints << event->pos(); + activeSwipe_->durations << 0; + swipeTimer_.start(); + setState(Recording); +} + +void QDeclarativePinchGenerator::mouseMoveEvent(QMouseEvent *event) +{ + if (state_ != Recording || !enabled_) { + event->ignore(); + return; + } + Q_ASSERT(activeSwipe_); + Q_ASSERT(swipeTimer_.isValid()); + + activeSwipe_->touchPoints << event->pos(); + activeSwipe_->durations << swipeTimer_.elapsed(); + swipeTimer_.restart(); +} + +void QDeclarativePinchGenerator::mouseReleaseEvent(QMouseEvent *event) +{ + if (state_ != Recording || !enabled_) { + event->ignore(); + return; + } + Q_ASSERT(activeSwipe_); + Q_ASSERT(swipeTimer_.isValid()); + activeSwipe_->touchPoints << event->pos(); + activeSwipe_->durations << swipeTimer_.elapsed(); + + if (swipes_.count() == SWIPES_REQUIRED) + delete swipes_.takeFirst(); + swipes_ << activeSwipe_; + activeSwipe_ = 0; + swipeTimer_.invalidate(); + if (window_ && target_) setState(Idle); else setState(Invalid); +} + +void QDeclarativePinchGenerator::mouseDoubleClickEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + if (!enabled_) { + event->ignore(); + return; + } + stop(); + clear(); + if (window_ && target_) setState(Idle); else setState(Invalid); +} + +void QDeclarativePinchGenerator::keyPressEvent(QKeyEvent *e) +{ + if (!enabled_) { + e->ignore(); + } + + if (e->key() == Qt::Key_C) { + clear(); + } else if (e->key() == Qt::Key_R) { + replay(); + } else if (e->key() == Qt::Key_S) { + stop(); + } else if (e->key() == Qt::Key_Plus) { + setReplaySpeedFactor(replaySpeedFactor() + 0.1); + } else if (e->key() == Qt::Key_Minus) { + setReplaySpeedFactor(replaySpeedFactor() - 0.1); + } else { + qDebug() << metaObject()->className() << "Unsupported key event."; + } +} + +bool QDeclarativePinchGenerator::enabled() const +{ + return enabled_; +} + + +void QDeclarativePinchGenerator::setEnabled(bool enabled) +{ + if (enabled == enabled_) + return; + enabled_ = enabled; + if (!enabled_) { + stop(); + clear(); + } + emit enabledChanged(); +} + + +qreal QDeclarativePinchGenerator::replaySpeedFactor() const +{ + return replaySpeedFactor_; +} + +void QDeclarativePinchGenerator::setReplaySpeedFactor(qreal factor) +{ + if (factor == replaySpeedFactor_ || factor < 0.001) + return; + replaySpeedFactor_ = factor; + emit replaySpeedFactorChanged(); +} + + +QString QDeclarativePinchGenerator::state() const +{ + switch (state_) { + case Invalid: + return "Invalid"; + case Idle: + return "Idle"; + break; + case Recording: + return "Recording"; + break; + case Replaying: + return "Replaying"; + break; + default: + Q_ASSERT(false); + } + return "How emberassing"; +} + +void QDeclarativePinchGenerator::setState(GeneratorState state) +{ + if (state == state_) + return; + state_ = state; + emit stateChanged(); +} + +void QDeclarativePinchGenerator::itemChange(ItemChange change, const ItemChangeData & data) +{ + if (change == ItemSceneChange) { + window_ = data.window; + if (target_) + setState(Idle); + } +} + +void QDeclarativePinchGenerator::timerEvent(QTimerEvent *event) +{ + Q_ASSERT(replayTimer_ == event->timerId()); + Q_ASSERT(state_ == Replaying); + + int slaveSwipe = masterSwipe_ ^ 1; + + int masterCount = swipes_.at(masterSwipe_)->touchPoints.count(); + int slaveCount = swipes_.at(slaveSwipe)->touchPoints.count(); + + if (replayBookmark_ == 0) { + QTest::touchEvent(window_, device_) + .press(0, swipes_.at(masterSwipe_)->touchPoints.at(replayBookmark_)) + .press(1, swipes_.at(slaveSwipe)->touchPoints.at(replayBookmark_)); + } else if (replayBookmark_ == (slaveCount - 1)) { + if (masterCount != slaveCount) { + QTest::touchEvent(window_, device_) + .move(0, swipes_.at(masterSwipe_)->touchPoints.at(replayBookmark_)) + .release(1, swipes_.at(slaveSwipe)->touchPoints.at(replayBookmark_)); + } else { + QTest::touchEvent(window_, device_) + .release(0, swipes_.at(masterSwipe_)->touchPoints.at(replayBookmark_)) + .release(1, swipes_.at(slaveSwipe)->touchPoints.at(replayBookmark_)); + } + } else if (replayBookmark_ == (masterCount - 1)) { + QTest::touchEvent(window_, device_) + .release(0, swipes_.at(masterSwipe_)->touchPoints.at(replayBookmark_)); + } + else { + QTest::touchEvent(window_, device_) + .move(0, swipes_.at(masterSwipe_)->touchPoints.at(replayBookmark_)) + .move(1, swipes_.at(slaveSwipe)->touchPoints.at(replayBookmark_)); + } + + replayBookmark_++; + if (replayBookmark_ >= swipes_.at(masterSwipe_)->touchPoints.count()) + stop(); + else { + killTimer(replayTimer_); + replayTimer_ = startTimer((swipes_.at(masterSwipe_)->durations.at(replayBookmark_) + 5) / replaySpeedFactor_ ); + } +} + +QQuickItem* QDeclarativePinchGenerator::target() const +{ + return target_; +} + +void QDeclarativePinchGenerator::setTarget(QQuickItem* target) +{ + if (target == target_) + return; + target_ = target; + stop(); + clear(); + if (window_) + setState(Idle); + else + setState(Invalid); + emit targetChanged(); +} + +void QDeclarativePinchGenerator::pinch(QPoint point1From, + QPoint point1To, + QPoint point2From, + QPoint point2To, + int interval1, + int interval2, + int samples1, + int samples2) +{ + Q_ASSERT(interval1 > 10); + Q_ASSERT(interval2 > 10); + Q_ASSERT(samples1 >= 2); // we need press and release events at minimum + Q_ASSERT(samples2 >= 2); + + clear(); + + Swipe* swipe1 = new Swipe; + Swipe* swipe2 = new Swipe; + for (int i = 0; i < samples1; ++i) { + swipe1->touchPoints << point1From + (point1To - point1From) / samples1 * i; + swipe1->durations << interval1; + } + for (int i = 0; i < samples2; ++i) { + swipe2->touchPoints << point2From + (point2To - point2From) / samples2 * i; + swipe2->durations << interval2; + } + swipes_ << swipe1 << swipe2; + Q_ASSERT(swipes_.at(0)); + Q_ASSERT(swipes_.at(1)); + + masterSwipe_ = (samples1 >= samples2) ? 0 : 1; + + replayTimer_ = startTimer(swipes_.at(masterSwipe_)->durations.at(0) / replaySpeedFactor_); + replayBookmark_ = 0; + setState(Replaying); +} + +void QDeclarativePinchGenerator::pinchPress(QPoint point1From, QPoint point2From) +{ + QTest::touchEvent(window_, device_).press(0, point1From).press(1, point2From); +} + +void QDeclarativePinchGenerator::pinchMoveTo(QPoint point1To, QPoint point2To) +{ + QTest::touchEvent(window_, device_).move(0, point1To).move(1, point2To); +} + +void QDeclarativePinchGenerator::pinchRelease(QPoint point1To, QPoint point2To) +{ + QTest::touchEvent(window_, device_).release(0, point1To).release(1, point2To); +} + +void QDeclarativePinchGenerator::replay() +{ + if (state_ != Idle) { + qDebug() << "Wrong state, will not replay pinch, state: " << state_; + return; + } + if (swipes_.count() < SWIPES_REQUIRED) { + qDebug() << "Too few swipes, cannot replay, amount: " << swipes_.count(); + return; + } + if ((swipes_.at(0)->touchPoints.count() < 2) || (swipes_.at(1)->touchPoints.count() < 2)) { + qDebug() << "Too few touchpoints, won't replay, amount: " << + swipes_.at(0)->touchPoints.count() << (swipes_.at(1)->touchPoints.count() < 2); + return; + } + + masterSwipe_ = (swipes_.at(0)->touchPoints.count() >= swipes_.at(1)->touchPoints.count()) ? 0 : 1; + + replayTimer_ = startTimer(swipes_.at(masterSwipe_)->touchPoints.count() / replaySpeedFactor_); + replayBookmark_ = 0; + setState(Replaying); +} + +void QDeclarativePinchGenerator::clear() +{ + stop(); + delete activeSwipe_; + activeSwipe_ = 0; + if (!swipes_.isEmpty()) { + qDeleteAll(swipes_); + swipes_.clear(); + } +} + +void QDeclarativePinchGenerator::stop() +{ + if (state_ != Replaying) + return; + // stop replay + Q_ASSERT(replayTimer_ != -1); + killTimer(replayTimer_); + replayTimer_ = -1; + setState(Idle); +} + +int QDeclarativePinchGenerator::startDragDistance() +{ + return qApp->styleHints()->startDragDistance(); +} + +QT_END_NAMESPACE diff --git a/tests/plugins/declarativetestplugin/qdeclarativepinchgenerator_p.h b/tests/plugins/declarativetestplugin/qdeclarativepinchgenerator_p.h new file mode 100644 index 0000000..23d8b65 --- /dev/null +++ b/tests/plugins/declarativetestplugin/qdeclarativepinchgenerator_p.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPINCHGENERATOR_H +#define QDECLARATIVEPINCHGENERATOR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SWIPES_REQUIRED 2 + +QT_BEGIN_NAMESPACE + +typedef struct { + QList touchPoints; + QList durations; +} Swipe; + +class QDeclarativePinchGenerator : public QQuickItem +{ + Q_OBJECT + + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(QString state READ state NOTIFY stateChanged) + Q_PROPERTY(qreal replaySpeedFactor READ replaySpeedFactor WRITE setReplaySpeedFactor NOTIFY replaySpeedFactorChanged) + Q_PROPERTY(QQuickItem* target READ target WRITE setTarget NOTIFY targetChanged) + Q_INTERFACES(QQmlParserStatus) + +public: + QDeclarativePinchGenerator(); + ~QDeclarativePinchGenerator(); + + QString state() const; + QQuickItem* target() const; + void setTarget(QQuickItem* target); + qreal replaySpeedFactor() const; + void setReplaySpeedFactor(qreal factor); + bool enabled() const; + void setEnabled(bool enabled); + + Q_INVOKABLE void replay(); + Q_INVOKABLE void clear(); + Q_INVOKABLE void stop(); + Q_INVOKABLE int startDragDistance(); + + // programmatic interface, useful for autotests + Q_INVOKABLE void pinch(QPoint point1From, + QPoint point1To, + QPoint point2From, + QPoint point2To, + int interval1 = 20, + int interval2 = 20, + int samples1 = 10, + int samples2 = 10); + + Q_INVOKABLE void pinchPress(QPoint point1From, QPoint point2From); + Q_INVOKABLE void pinchMoveTo(QPoint point1To, QPoint point2To); + Q_INVOKABLE void pinchRelease(QPoint point1To, QPoint point2To); + +signals: + void stateChanged(); + void targetChanged(); + void replaySpeedFactorChanged(); + void enabledChanged(); + +public: + enum GeneratorState { + Invalid = 0, + Idle = 1, + Recording = 2, + Replaying = 3 + }; + + // from QQmlParserStatus + virtual void componentComplete(); + // from QQuickItem + void itemChange(ItemChange change, const ItemChangeData & data); + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *event); + void timerEvent(QTimerEvent *event); + +private: + void setState(GeneratorState state); + +private: + QQuickItem* target_; + GeneratorState state_; + QQuickWindow* window_; + QList swipes_; + Swipe* activeSwipe_; + QElapsedTimer swipeTimer_; + int replayTimer_; + int replayBookmark_; + int masterSwipe_; + qreal replaySpeedFactor_; + bool enabled_; + QTouchDevice* device_; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tests/plugins/declarativetestplugin/qmldir b/tests/plugins/declarativetestplugin/qmldir new file mode 100644 index 0000000..c2582ed --- /dev/null +++ b/tests/plugins/declarativetestplugin/qmldir @@ -0,0 +1,3 @@ +module QtLocation.Test +plugin declarative_location_test +classname QLocationDeclarativeTestModule diff --git a/tests/plugins/declarativetestplugin/testhelper.h b/tests/plugins/declarativetestplugin/testhelper.h new file mode 100644 index 0000000..c6d9f3b --- /dev/null +++ b/tests/plugins/declarativetestplugin/testhelper.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTHELPER_H +#define TESTHELPER_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class TestHelper: public QObject +{ + Q_OBJECT +public: + TestHelper(QObject *parent = Q_NULLPTR):QObject(parent){} + Q_INVOKABLE bool waitForPolished(QQuickItem *item, int timeout = 10000) const + { + QSignalSpy spy(item->window(), &QQuickWindow::afterAnimating); + return spy.wait(timeout); + } +}; + +QT_END_NAMESPACE + +#endif // TESTHELPER_H diff --git a/tests/plugins/imports.pri b/tests/plugins/imports.pri new file mode 100644 index 0000000..00f9333 --- /dev/null +++ b/tests/plugins/imports.pri @@ -0,0 +1,5 @@ +!contains(DESTDIR, $$[QT_INSTALL_QML]/$$TARGETPATH) { + importfiles.files = $$IMPORT_FILES + importfiles.path = $$DESTDIR + COPIES += importfiles +} diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 0000000..4fa2b33 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS = auto +qtHaveModule(location):qtHaveModule(quick): SUBDIRS += plugins/declarativetestplugin